Merge remote branch 'upstream/next' into next

This commit is contained in:
Craig Earls 2011-10-06 22:07:01 -07:00
commit b400d65be0
59 changed files with 675 additions and 463 deletions

38
acprep
View file

@ -245,8 +245,8 @@ class CommandLineApp(object):
force_exit = True # If true, always ends run() with sys.exit() force_exit = True # If true, always ends run() with sys.exit()
log_handler = None log_handler = None
darwin_gcc = False darwin_gcc = False
boost_version = "1_46_1" boost_version = "1_47_0"
boost_major = "1_46_1" boost_major = "1_47"
options = { options = {
'debug': False, 'debug': False,
@ -338,7 +338,7 @@ class CommandLineApp(object):
self.log.setLevel(logging.DEBUG) self.log.setLevel(logging.DEBUG)
elif self.options.verbose: elif self.options.verbose:
self.log.setLevel(logging.INFO) self.log.setLevel(logging.INFO)
exit_code = 0 exit_code = 0
try: try:
# We could just call main() and catch a TypeError, but that would # We could just call main() and catch a TypeError, but that would
@ -928,7 +928,7 @@ class PrepareBuild(CommandLineApp):
def setup_system_directories(self): def setup_system_directories(self):
boost_include = self.boost_info.include_directory() boost_include = self.boost_info.include_directory()
boost_library = self.boost_info.library_directory() boost_library = self.boost_info.library_directory()
if re.match('/opt/local', self.boost_info.home_path): if re.match('/opt/local', self.boost_info.home_path):
self.log.debug("Setting Python home to /opt/local based on Boost's location") self.log.debug("Setting Python home to /opt/local based on Boost's location")
self.envvars['PYTHON_HOME'] = '/opt/local' self.envvars['PYTHON_HOME'] = '/opt/local'
@ -1252,7 +1252,7 @@ class PrepareBuild(CommandLineApp):
home_path = '/usr/local/stow/boost_%s-%s' % \ home_path = '/usr/local/stow/boost_%s-%s' % \
(self.boost_version, self.boost_inc_ident), (self.boost_version, self.boost_inc_ident),
suffix = '-%s-sd-%s' % \ suffix = '-%s-sd-%s' % \
(self.boost_lib_ident, self.boost_version), (self.boost_lib_ident, self.boost_major),
file_suffix = '.dylib', file_suffix = '.dylib',
include_path = 'include/boost-%s' % self.boost_major): include_path = 'include/boost-%s' % self.boost_major):
pass pass
@ -1260,7 +1260,7 @@ class PrepareBuild(CommandLineApp):
home_path = '/usr/local/stow/boost_%s-%s' % \ home_path = '/usr/local/stow/boost_%s-%s' % \
(self.boost_version, self.boost_inc_ident), (self.boost_version, self.boost_inc_ident),
suffix = '-%s-d-%s' % \ suffix = '-%s-d-%s' % \
(self.boost_lib_ident, self.boost_version), (self.boost_lib_ident, self.boost_major),
file_suffix = '.dylib', file_suffix = '.dylib',
include_path = 'include/boost-%s' % self.boost_major): include_path = 'include/boost-%s' % self.boost_major):
pass pass
@ -1274,7 +1274,7 @@ class PrepareBuild(CommandLineApp):
home_path = '/usr/local/stow/boost_%s-%s' % \ home_path = '/usr/local/stow/boost_%s-%s' % \
(self.boost_version, self.boost_inc_ident), (self.boost_version, self.boost_inc_ident),
suffix = '-%s-s-%s' % \ suffix = '-%s-s-%s' % \
(self.boost_lib_ident, self.boost_version), (self.boost_lib_ident, self.boost_major),
file_suffix = '.dylib', file_suffix = '.dylib',
include_path = 'include/boost-%s' % self.boost_major): include_path = 'include/boost-%s' % self.boost_major):
pass pass
@ -1282,7 +1282,7 @@ class PrepareBuild(CommandLineApp):
home_path = '/usr/local/stow/boost_%s-%s' % \ home_path = '/usr/local/stow/boost_%s-%s' % \
(self.boost_version, self.boost_inc_ident), (self.boost_version, self.boost_inc_ident),
suffix = '-%s-%s' % \ suffix = '-%s-%s' % \
(self.boost_lib_ident, self.boost_version), (self.boost_lib_ident, self.boost_major),
file_suffix = '.dylib', file_suffix = '.dylib',
include_path = 'include/boost-%s' % self.boost_major): include_path = 'include/boost-%s' % self.boost_major):
pass pass
@ -1518,7 +1518,7 @@ class PrepareBuild(CommandLineApp):
match = re.search('/opt/local/lib/(.+?)\.dylib', line) match = re.search('/opt/local/lib/(.+?)\.dylib', line)
if not match: if not match:
continue continue
lib = match.group(0) lib = match.group(0)
base = basename(lib) base = basename(lib)
@ -1587,7 +1587,7 @@ class PrepareBuild(CommandLineApp):
def phase_distcheck(self, *args): def phase_distcheck(self, *args):
self.log.info('Executing phase: distcheck') self.log.info('Executing phase: distcheck')
self.configure_flavor('default', False) self.configure_flavor('default', False)
environ, conf_args = self.configure_environment() environ, conf_args = self.configure_environment()
@ -1621,7 +1621,7 @@ class PrepareBuild(CommandLineApp):
'%s/' % self.source_dir, '%s/' % source_copy_dir) '%s/' % self.source_dir, '%s/' % source_copy_dir)
self.source_dir = source_copy_dir self.source_dir = source_copy_dir
def phase_proof(self, *args): def phase_proof(self, *args):
self.log.info('Executing phase: proof') self.log.info('Executing phase: proof')
@ -1633,15 +1633,15 @@ class PrepareBuild(CommandLineApp):
self.configure_flavor('opt', reset=False) self.configure_flavor('opt', reset=False)
self.log.info('=== Testing opt ===') self.log.info('=== Testing opt ===')
self.phase_make('fullcheck') self.phase_make('fullcheck')
self.configure_flavor('gcov', reset=False) self.configure_flavor('gcov', reset=False)
self.log.info('=== Testing gcov ===') self.log.info('=== Testing gcov ===')
self.phase_make('check') self.phase_make('check')
self.configure_flavor('debug', reset=False) self.configure_flavor('debug', reset=False)
self.log.info('=== Testing debug ===') self.log.info('=== Testing debug ===')
self.phase_make('fullcheck') self.phase_make('fullcheck')
self.configure_flavor('default', reset=False) self.configure_flavor('default', reset=False)
self.log.info('=== Testing default ===') self.log.info('=== Testing default ===')
self.phase_make('fullcheck') self.phase_make('fullcheck')
@ -1654,14 +1654,14 @@ class PrepareBuild(CommandLineApp):
self.log.info('Executing phase: makeall') self.log.info('Executing phase: makeall')
self.configure_flavor('opt', reset) self.configure_flavor('opt', reset)
system_hh_gch = join(self.source_dir, 'src', 'system.hh.gch') system_hh_gch = join(self.source_dir, 'src', 'system.hh.gch')
if exists(system_hh_gch): if exists(system_hh_gch):
os.remove(system_hh_gch) os.remove(system_hh_gch)
self.log.info('=== Building opt ===') self.log.info('=== Building opt ===')
self.phase_make(*args) self.phase_make(*args)
self.configure_flavor('gcov', reset) self.configure_flavor('gcov', reset)
system_hh_gch = join(self.source_dir, 'src', 'system.hh.gch') system_hh_gch = join(self.source_dir, 'src', 'system.hh.gch')
@ -1670,7 +1670,7 @@ class PrepareBuild(CommandLineApp):
self.log.info('=== Building gcov ===') self.log.info('=== Building gcov ===')
self.phase_make(*args) self.phase_make(*args)
system_hh_gch = join(self.source_dir, 'src', 'system.hh.gch') system_hh_gch = join(self.source_dir, 'src', 'system.hh.gch')
if exists(system_hh_gch): if exists(system_hh_gch):
os.remove(system_hh_gch) os.remove(system_hh_gch)
@ -1686,7 +1686,7 @@ class PrepareBuild(CommandLineApp):
self.log.info('=== Building debug ===') self.log.info('=== Building debug ===')
self.phase_make(*args) self.phase_make(*args)
self.configure_flavor('default', reset) self.configure_flavor('default', reset)
######################################################################### #########################################################################
@ -1696,7 +1696,7 @@ class PrepareBuild(CommandLineApp):
def phase_help(self, *args): def phase_help(self, *args):
self.option_parser.print_help() self.option_parser.print_help()
print """ print """
Of the optional ARGS, the first is an optional build FLAVOR, with the default Of the optional ARGS, the first is an optional build FLAVOR, with the default
being 'debug': being 'debug':

View file

@ -6,6 +6,22 @@ Then include the following line in your .vimrc or in ~/.vim/filetype.vim
You can also use a modeline like this in every ledger file You can also use a modeline like this in every ledger file
vim:filetype=ledger vim:filetype=ledger
Tips and useful commands
======================================================================
• Try account-completion (as explained below)
• :call LedgerSetDate(line('.'), 'effective')
will set today's date as the effective date of the current
transaction. You can use also 'actual' in place of 'effective'
or pass in a different date measured as seconds since 1st Jan 1970.
• :call LedgerSetTransactionState(line('.'), '*')
sets the state of the current transaction to '*'. You can
use this in custom mappings.
• :call LedgerToggleTransactionState(line('.'), ' *?!')
will toggle through the provided transaction states.
You can map this to double-clicking for example:
noremap <silent><buffer> <2-LeftMouse>
\ :call LedgerToggleTransactionState(line('.'), ' *?!')<CR>
Configuration Configuration
====================================================================== ======================================================================
Include the following let-statements somewhere in your .vimrc Include the following let-statements somewhere in your .vimrc
@ -35,7 +51,7 @@ to modify the behaviour of the ledger filetype.
Completion Completion
====================================================================== ======================================================================
Omni completion is implemented for account names and tags. Omni completion is currently implemented for account names only.
Accounts Accounts
---------------------------------------------------------------------- ----------------------------------------------------------------------
@ -52,38 +68,11 @@ When you want to complete on a virtual transaction,
it's currently best to keep the cursor in front of the closing bracket. 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. 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 License
====================================================================== ======================================================================
Copyright 2009 by Johann Klähn Copyright 2011-2009 by Johann Klähn
Copyright 2009 by Stefan Karrmann Copyright 2009 by Stefan Karrmann
Copyright 2005 by Wolfgang Oertl Copyright 2005 by Wolfgang Oertl
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by

View file

@ -1,6 +1,5 @@
" Vim filetype plugin file " Vim filetype plugin file
" filetype: ledger " filetype: ledger
" Version: 0.1.0
" by Johann Klähn; Use according to the terms of the GPL>=2. " by Johann Klähn; Use according to the terms of the GPL>=2.
" vim:ts=2:sw=2:sts=2:foldmethod=marker " vim:ts=2:sw=2:sts=2:foldmethod=marker
@ -137,22 +136,33 @@ function! LedgerComplete(findstart, base) "{{{1
if a:findstart if a:findstart
let lnum = line('.') let lnum = line('.')
let line = getline('.') let line = getline('.')
let lastcol = col('.') - 2
let b:compl_context = '' let b:compl_context = ''
if line =~ '^\s\+[^[:blank:];]' "{{{2 (account) if line =~ '^\s\+[^[:blank:];]' "{{{2 (account)
let b:compl_context = 'account' " only allow completion when in or at end of account name
if matchend(line, '^\s\+\%(\S \S\|\S\)\+') <= lastcol if matchend(line, '^\s\+\%(\S \S\|\S\)\+') >= col('.') - 1
" only allow completion when in or at end of account name " the start of the first non-blank character
return -1 " (excluding virtual-transaction-marks)
" is the beginning of the account name
let b:compl_context = 'account'
return matchend(line, '^\s\+[\[(]\?')
endif endif
" the start of the first non-blank character elseif line =~ '^\d' "{{{2 (description)
" (excluding virtual-transaction-marks) let pre = matchend(line, '^\d\S\+\%(([^)]*)\|[*?!]\|\s\)\+')
" is the beginning of the account name if pre < col('.') - 1
return matchend(line, '^\s\+[\[(]\?') let b:compl_context = 'description'
else "}}} return pre
return -1 endif
endif elseif line =~ '^$' "{{{2 (new line)
let b:compl_context = 'new'
endif "}}}
return -1
else else
if ! exists('b:compl_cache')
let b:compl_cache = s:collect_completion_data()
let b:compl_cache['#'] = changenr()
endif
let results = []
if b:compl_context == 'account' "{{{2 (account) if b:compl_context == 'account' "{{{2 (account)
unlet! b:compl_context unlet! b:compl_context
let hierarchy = split(a:base, ':') let hierarchy = split(a:base, ':')
@ -160,7 +170,7 @@ function! LedgerComplete(findstart, base) "{{{1
call add(hierarchy, '') call add(hierarchy, '')
endif endif
let results = LedgerFindInTree(LedgerGetAccountHierarchy(), hierarchy) let results = LedgerFindInTree(b:compl_cache.accounts, hierarchy)
" sort by alphabet and reverse because it will get reversed one more time " sort by alphabet and reverse because it will get reversed one more time
if g:ledger_detailed_first if g:ledger_detailed_first
let results = reverse(sort(results, 's:sort_accounts_by_depth')) let results = reverse(sort(results, 's:sort_accounts_by_depth'))
@ -168,10 +178,19 @@ function! LedgerComplete(findstart, base) "{{{1
let results = sort(results) let results = sort(results)
endif endif
call insert(results, a:base) call insert(results, a:base)
return results elseif b:compl_context == 'description' "{{{2 (description)
else "}}} let results = [a:base] + s:filter_items(b:compl_cache.descriptions, a:base)
elseif b:compl_context == 'new' "{{{2 (new line)
return [strftime('%Y/%m/%d')]
endif "}}}
" no completion (apart from a:base) found. update cache if file has changed
if len(results) <= 1 && b:compl_cache['#'] != changenr()
unlet b:compl_cache
return LedgerComplete(a:findstart, a:base)
else
unlet! b:compl_context unlet! b:compl_context
return [] return results
endif endif
endif endif
endf "}}} endf "}}}
@ -195,21 +214,6 @@ function! LedgerFindInTree(tree, levels) "{{{1
return results return results
endf "}}} 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! LedgerToggleTransactionState(lnum, ...) function! LedgerToggleTransactionState(lnum, ...)
if a:0 == 1 if a:0 == 1
let chars = a:1 let chars = a:1
@ -278,6 +282,51 @@ function! LedgerSetDate(lnum, type, ...) "{{{1
call setline(trans['head'], trans.format_head()) call setline(trans['head'], trans.format_head())
endf "}}} endf "}}}
function! s:collect_completion_data() "{{{1
let transactions = s:get_transactions()
let cache = {'descriptions': [], 'tags': {}, 'accounts': {}}
let accounts = []
for xact in transactions
" collect descriptions
if index(cache.descriptions, xact['description']) < 0
call add(cache.descriptions, xact['description'])
endif
let [t, postings] = xact.parse_body()
let tagdicts = [t]
" collect account names
for posting in postings
if has_key(posting, 'tags')
call add(tagdicts, posting.tags)
endif
" remove virtual-transaction-marks
let name = substitute(posting.account, '\%(^\s*[\[(]\?\|[\])]\?\s*$\)', '', 'g')
if index(accounts, name) < 0
call add(accounts, name)
endif
endfor
" collect tags
for tags in tagdicts | for [tag, val] in items(tags)
let values = get(cache.tags, tag, [])
if index(values, val) < 0
call add(values, val)
endif
let cache.tags[tag] = values
endfor | endfor
endfor
for account in accounts
let last = cache.accounts
for part in split(account, ':')
let last[part] = get(last, part, {})
let last = last[part]
endfor
endfor
return cache
endf "}}}
let s:transaction = {} "{{{1 let s:transaction = {} "{{{1
function! s:transaction.new() dict function! s:transaction.new() dict
return copy(s:transaction) return copy(s:transaction)
@ -293,7 +342,15 @@ function! s:transaction.from_lnum(lnum) dict "{{{2
let trans['head'] = head let trans['head'] = head
let trans['tail'] = tail let trans['tail'] = tail
let parts = split(getline(head), '\s\+') " split off eventual comments at the end of line
let line = split(getline(head), '\ze\s*\%(\t\| \);', 1)
if len(line) > 1
let trans['appendix'] = join(line[1:], '')
endif
" parse rest of line
" FIXME (minor): will not preserve spacing (see 'join(parts)')
let parts = split(line[0], '\s\+')
if parts[0] ==# '~' if parts[0] ==# '~'
let trans['expr'] = join(parts[1:]) let trans['expr'] = join(parts[1:])
return trans return trans
@ -318,8 +375,6 @@ function! s:transaction.from_lnum(lnum) dict "{{{2
call remove(parts, 0) call remove(parts, 0)
endfor endfor
" FIXME: this will break comments at the end of this 'head' line
" they need 2 spaces in front of the semicolon
let trans['description'] = join(parts) let trans['description'] = join(parts)
return trans return trans
endf "}}} endf "}}}
@ -402,7 +457,11 @@ function! s:transaction.format_head() dict "{{{2
if has_key(self, 'code') | call add(parts, '('.self['code'].')') | endif if has_key(self, 'code') | call add(parts, '('.self['code'].')') | endif
if has_key(self, 'state') | call add(parts, self['state']) | endif if has_key(self, 'state') | call add(parts, self['state']) | endif
if has_key(self, 'description') | call add(parts, self['description']) | endif if has_key(self, 'description') | call add(parts, self['description']) | endif
return join(parts)
let line = join(parts)
if has_key(self, 'appendix') | let line .= self['appendix'] | endif
return line
endf "}}} endf "}}}
"}}} "}}}
@ -518,7 +577,7 @@ endf "}}}
" return only those items that start with a specified keyword " return only those items that start with a specified keyword
function! s:filter_items(list, keyword) "{{{2 function! s:filter_items(list, keyword) "{{{2
return filter(a:list, 'v:val =~ ''^\V'.substitute(a:keyword, '\\', '\\\\', 'g').'''') return filter(copy(a:list), 'v:val =~ ''^\V'.substitute(a:keyword, '\\', '\\\\', 'g').'''')
endf "}}} endf "}}}
" return all lines matching an expression, returning only the matched part " return all lines matching an expression, returning only the matched part

View file

@ -1,19 +1,8 @@
" Vim syntax file " Vim syntax file
" filetype: ledger " filetype: ledger
" Version: 0.1.0
" by Johann Klähn; Use according to the terms of the GPL>=2. " 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 Stefan Karrmann; Use according to the terms of the GPL>=2.
" by Wolfgang Oertl; 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 " vim:ts=2:sw=2:sts=2:foldmethod=marker
if version < 600 if version < 600

View file

@ -5,8 +5,8 @@
STOW_ROOT = /usr/local/stow STOW_ROOT = /usr/local/stow
PRODUCTS = $(HOME)/Products PRODUCTS = $(HOME)/Products
GCC_VERSION = 4.6 GCC_VERSION = 4.5
BOOST_VERSION = 1_46_1 BOOST_VERSION = 1_47_0
CC = gcc-mp-$(GCC_VERSION) CC = gcc-mp-$(GCC_VERSION)
ifeq ($(CC),clang) ifeq ($(CC),clang)
@ -51,7 +51,7 @@ all: boost-build #icu-build boost-icu-build
prepare-boost: prepare-boost:
perl -i -pe 's/local command = \[ common\.get-invocation-command darwin : g\+\+ : .*/local command = [ common.get-invocation-command darwin : g++ : $(CXX) ] ;/;' $(BOOST_SOURCE)/tools/build/v2/tools/darwin.jam perl -i -pe 's/local command = \[ common\.get-invocation-command darwin : g\+\+ : .*/local command = [ common.get-invocation-command darwin : g++ : $(CXX) ] ;/;' $(BOOST_SOURCE)/tools/build/v2/tools/darwin.jam
perl -i -pe 's/flags darwin\.compile OPTIONS : -no-cpp-precomp -gdwarf-2 ;/flags darwin\.compile OPTIONS : -gdwarf-2 ;/;' $(BOOST_SOURCE)/tools/build/v2/tools/darwin.jam perl -i -pe 's/flags darwin\.compile OPTIONS : -no-cpp-precomp -gdwarf-2 (-fexceptions )?;/flags darwin\.compile OPTIONS : -gdwarf-2 \1;/;' $(BOOST_SOURCE)/tools/build/v2/tools/darwin.jam
boost-build: prepare-boost boost-build: prepare-boost
(cd $(BOOST_SOURCE) && \ (cd $(BOOST_SOURCE) && \

View file

@ -53,4 +53,30 @@
(provide 'ledger) (provide 'ledger)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun ledger-create-test ()
(interactive)
(save-restriction
(org-narrow-to-subtree)
(save-excursion
(let (text beg)
(goto-char (point-min))
(forward-line 1)
(setq beg (point))
(search-forward ":PROPERTIES:")
(goto-char (line-beginning-position))
(setq text (buffer-substring-no-properties beg (point)))
(goto-char (point-min))
(re-search-forward ":ID:\\s-+\\([^-]+\\)")
(find-file-other-window
(format "~/src/ledger/test/regress/%s.test" (match-string 1)))
(sit-for 0)
(insert text)
(goto-char (point-min))
(while (not (eobp))
(goto-char (line-beginning-position))
(delete-char 3)
(forward-line 1))))))
;;; ledger.el ends here ;;; ledger.el ends here

View file

@ -433,7 +433,9 @@ dropped."
;;;###autoload ;;;###autoload
(define-derived-mode ledger-mode text-mode "Ledger" (define-derived-mode ledger-mode text-mode "Ledger"
"A mode for editing ledger data files." "A mode for editing ledger data files.
\\{ledger-mode-map}"
(set (make-local-variable 'comment-start) " ; ") (set (make-local-variable 'comment-start) " ; ")
(set (make-local-variable 'comment-end) "") (set (make-local-variable 'comment-end) "")
(set (make-local-variable 'indent-tabs-mode) nil) (set (make-local-variable 'indent-tabs-mode) nil)
@ -632,8 +634,7 @@ dropped."
(defvar ledger-reconcile-mode-abbrev-table) (defvar ledger-reconcile-mode-abbrev-table)
(define-derived-mode ledger-reconcile-mode text-mode "Reconcile" (defvar ledger-reconcile-mode-map
"A mode for reconciling ledger entries."
(let ((map (make-sparse-keymap))) (let ((map (make-sparse-keymap)))
(define-key map [(control ?m)] 'ledger-reconcile-visit) (define-key map [(control ?m)] 'ledger-reconcile-visit)
(define-key map [return] 'ledger-reconcile-visit) (define-key map [return] 'ledger-reconcile-visit)
@ -647,7 +648,12 @@ dropped."
(define-key map [?p] 'previous-line) (define-key map [?p] 'previous-line)
(define-key map [?s] 'ledger-reconcile-save) (define-key map [?s] 'ledger-reconcile-save)
(define-key map [?q] 'ledger-reconcile-quit) (define-key map [?q] 'ledger-reconcile-quit)
(use-local-map map))) map))
(define-derived-mode ledger-reconcile-mode text-mode "Reconcile"
"A mode for reconciling ledger entries.
\\{ledger-reconcile-mode-map}")
;; Context sensitivity ;; Context sensitivity
@ -807,8 +813,7 @@ specified line, returns nil."
(defvar ledger-report-mode-abbrev-table) (defvar ledger-report-mode-abbrev-table)
(define-derived-mode ledger-report-mode text-mode "Ledger-Report" (defvar ledger-report-mode-map
"A mode for viewing ledger reports."
(let ((map (make-sparse-keymap))) (let ((map (make-sparse-keymap)))
(define-key map [? ] 'scroll-up) (define-key map [? ] 'scroll-up)
(define-key map [backspace] 'scroll-down) (define-key map [backspace] 'scroll-down)
@ -825,7 +830,10 @@ specified line, returns nil."
'ledger-report-kill) 'ledger-report-kill)
(define-key map [(control ?c) (control ?l) (control ?e)] (define-key map [(control ?c) (control ?l) (control ?e)]
'ledger-report-edit) 'ledger-report-edit)
(use-local-map map))) map))
(define-derived-mode ledger-report-mode text-mode "Ledger-Report"
"A mode for viewing ledger reports.")
(defun ledger-report-read-name () (defun ledger-report-read-name ()
"Read the name of a ledger report to use, with completion. "Read the name of a ledger report to use, with completion.
@ -1201,7 +1209,7 @@ the default."
;; A sample function for $ users ;; A sample function for $ users
(defun ledger-next-amount (&optional end) (defun ledger-next-amount (&optional end)
(when (re-search-forward "\\( \\|\t\\| \t\\)[ \t]*-?\\([A-Z$]+ *\\)?\\(-?[0-9,]+?\\)\\(.[0-9]+\\)?\\( *[A-Z$]+\\)?\\([ \t]*@@?[^\n;]+?\\)?\\([ \t]+;.+?\\)?$" (marker-position end) t) (when (re-search-forward "\\( \\|\t\\| \t\\)[ \t]*-?\\([A-Z$€£]+ *\\)?\\(-?[0-9,]+?\\)\\(.[0-9]+\\)?\\( *[A-Z$€£]+\\)?\\([ \t]*@@?[^\n;]+?\\)?\\([ \t]+;.+?\\)?$" (marker-position end) t)
(goto-char (match-beginning 0)) (goto-char (match-beginning 0))
(skip-syntax-forward " ") (skip-syntax-forward " ")
(- (or (match-end 4) (- (or (match-end 4)

View file

@ -45,7 +45,7 @@ account_t::~account_t()
if (! pair.second->has_flags(ACCOUNT_TEMP) || if (! pair.second->has_flags(ACCOUNT_TEMP) ||
has_flags(ACCOUNT_TEMP)) { has_flags(ACCOUNT_TEMP)) {
checked_delete(pair.second); checked_delete(pair.second);
} }
} }
} }

View file

@ -152,7 +152,7 @@ namespace {
if (mpfr_asprintf(&buf, "%.*RNf", precision, tempfb) < 0) if (mpfr_asprintf(&buf, "%.*RNf", precision, tempfb) < 0)
throw_(amount_error, throw_(amount_error,
_("Cannot output amount to a floating-point representation")); _("Cannot output amount to a floating-point representation"));
DEBUG("amount.convert", "mpfr_print = " << buf DEBUG("amount.convert", "mpfr_print = " << buf
<< " (precision " << precision << " (precision " << precision
<< ", zeros_prec " << zeros_prec << ")"); << ", zeros_prec " << zeros_prec << ")");
@ -1049,16 +1049,12 @@ bool amount_t::parse(std::istream& in, const parse_flags_t& flags)
// Create the commodity if has not already been seen, and update the // Create the commodity if has not already been seen, and update the
// precision if something greater was used for the quantity. // precision if something greater was used for the quantity.
bool newly_created = false;
if (symbol.empty()) { if (symbol.empty()) {
commodity_ = NULL; commodity_ = NULL;
} else { } else {
commodity_ = commodity_pool_t::current_pool->find(symbol); commodity_ = commodity_pool_t::current_pool->find(symbol);
if (! commodity_) { if (! commodity_)
commodity_ = commodity_pool_t::current_pool->create(symbol); commodity_ = commodity_pool_t::current_pool->create(symbol);
newly_created = true;
}
assert(commodity_); assert(commodity_);
if (details) if (details)

View file

@ -349,7 +349,7 @@ public:
return temp; return temp;
} }
void in_place_truncate(); void in_place_truncate();
/** Yields an amount which has lost all of its extra precision, beyond what /** Yields an amount which has lost all of its extra precision, beyond what
the display precision of the commodity would have printed. */ the display precision of the commodity would have printed. */
amount_t floored() const { amount_t floored() const {
@ -358,7 +358,7 @@ public:
return temp; return temp;
} }
void in_place_floor(); void in_place_floor();
/** Yields an amount whose display precision is never truncated, even /** Yields an amount whose display precision is never truncated, even
though its commodity normally displays only rounded values. */ though its commodity normally displays only rounded values. */
amount_t unrounded() const { amount_t unrounded() const {

View file

@ -138,9 +138,9 @@ post_handler_ptr chain_post_handlers(post_handler_ptr base_handler,
report.HANDLED(tail_) ? report.HANDLED(tail_) ?
report.HANDLER(tail_).value.to_int() : 0)); report.HANDLER(tail_).value.to_int() : 0));
// changed_value_posts adds virtual posts to the list to account for changes // display_filter_posts adds virtual posts to the list to account
// in market value of commodities, which otherwise would affect the running // for changes in value of commodities, which otherwise would affect
// total unpredictably. // the running total unpredictably.
display_filter = new display_filter_posts(handler, report, display_filter = new display_filter_posts(handler, report,
report.HANDLED(revalued) && report.HANDLED(revalued) &&
! report.HANDLED(no_rounding)); ! report.HANDLED(no_rounding));

View file

@ -444,7 +444,7 @@ commodity_t::find_price(const optional<commodity_t&>& commodity,
return point; return point;
} }
return none; return none;
} }
optional<price_point_t> optional<price_point_t>
commodity_t::check_for_updated_price(const optional<price_point_t>& point, commodity_t::check_for_updated_price(const optional<price_point_t>& point,
@ -758,7 +758,7 @@ void to_xml(std::ostream& out, const commodity_t& comm,
out << '"'; out << '"';
x.close_attrs(); x.close_attrs();
{ {
push_xml y(out, "symbol"); push_xml y(out, "symbol");
out << y.guard(comm.symbol()); out << y.guard(comm.symbol());

View file

@ -376,7 +376,7 @@ public:
#if defined(DEBUG_ON) #if defined(DEBUG_ON)
, const int indent = 0 , const int indent = 0
#endif #endif
) const; ) const;
optional<price_point_t> optional<price_point_t>
check_for_updated_price(const optional<price_point_t>& point, check_for_updated_price(const optional<price_point_t>& point,

View file

@ -58,7 +58,7 @@ class compare_items
expr_t sort_order; expr_t sort_order;
compare_items(); compare_items();
public: public:
compare_items(const compare_items& other) : sort_order(other.sort_order) { compare_items(const compare_items& other) : sort_order(other.sort_order) {
TRACE_CTOR(compare_items, "copy"); TRACE_CTOR(compare_items, "copy");

View file

@ -62,10 +62,10 @@ value_t convert_command(call_scope_t& args)
post_map_t post_map; post_map_t post_map;
xacts_iterator journal_iter(journal); xacts_iterator journal_iter(journal);
while (xact_t * xact = journal_iter()) { while (xact_t * xact = *journal_iter++) {
post_t * post = NULL; post_t * post = NULL;
xact_posts_iterator xact_iter(*xact); xact_posts_iterator xact_iter(*xact);
while ((post = xact_iter()) != NULL) { while ((post = *xact_iter++) != NULL) {
if (post->account == bucket) if (post->account == bucket)
break; break;
} }
@ -95,7 +95,7 @@ value_t convert_command(call_scope_t& args)
foreach (post_t * post, xact->posts) foreach (post_t * post, xact->posts)
post->amount.in_place_negate(); post->amount.in_place_negate();
} }
bool matched = false; bool matched = false;
if (! xact->posts.front()->amount.is_null()) { if (! xact->posts.front()->amount.is_null()) {
post_map_t::iterator i = post_map.find(- xact->posts.front()->amount); post_map_t::iterator i = post_map.find(- xact->posts.front()->amount);
@ -121,14 +121,10 @@ value_t convert_command(call_scope_t& args)
} }
else { else {
if (xact->posts.front()->account == NULL) { if (xact->posts.front()->account == NULL) {
xacts_iterator xi;
xi.xacts_i = current_xacts.begin();
xi.xacts_end = current_xacts.end();
xi.xacts_uninitialized = false;
// jww (2010-03-07): Bind this logic to an option: --auto-match // jww (2010-03-07): Bind this logic to an option: --auto-match
if (account_t * acct = if (account_t * acct =
lookup_probable_account(xact->payee, xi, bucket).second) lookup_probable_account(xact->payee, current_xacts.rbegin(),
current_xacts.rend(), bucket).second)
xact->posts.front()->account = acct; xact->posts.front()->account = acct;
else else
xact->posts.front()->account = unknown; xact->posts.front()->account = unknown;
@ -141,7 +137,7 @@ value_t convert_command(call_scope_t& args)
} }
else { else {
xact_posts_iterator xact_iter(*xact); xact_posts_iterator xact_iter(*xact);
while (post_t * post = xact_iter()) while (post_t * post = *xact_iter++)
formatter(*post); formatter(*post);
} }
} }

View file

@ -289,7 +289,7 @@ xact_t * csv_reader::read_xact(journal_t& journal, account_t * bucket)
amt.set_commodity(*commodity_pool_t::current_pool->default_commodity); amt.set_commodity(*commodity_pool_t::current_pool->default_commodity);
post->assigned_amount = amt; post->assigned_amount = amt;
} }
xact->add_post(post.release()); xact->add_post(post.release());
return xact.release(); return xact.release();

View file

@ -66,16 +66,6 @@ void draft_t::xact_template_t::dump(std::ostream& out) const
<< _("<Posting copied from last related transaction>") << _("<Posting copied from last related transaction>")
<< std::endl; << std::endl;
} else { } 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) { foreach (const post_template_t& post, posts) {
straccstream accum; straccstream accum;
out << std::endl out << std::endl
@ -245,12 +235,12 @@ xact_t * draft_t::insert(journal_t& journal)
if (tmpl->payee_mask.empty()) if (tmpl->payee_mask.empty())
throw std::runtime_error(_("'xact' command requires at least a payee")); throw std::runtime_error(_("'xact' command requires at least a payee"));
xact_t * matching = NULL; xact_t * matching = NULL;
std::auto_ptr<xact_t> added(new xact_t); std::auto_ptr<xact_t> added(new xact_t);
xacts_iterator xi(journal); if (xact_t * xact =
if (xact_t * xact = lookup_probable_account(tmpl->payee_mask.str(), xi).first) { lookup_probable_account(tmpl->payee_mask.str(), journal.xacts.rbegin(),
journal.xacts.rend()).first) {
DEBUG("draft.xact", "Found payee by lookup: transaction on line " DEBUG("draft.xact", "Found payee by lookup: transaction on line "
<< xact->pos->beg_line); << xact->pos->beg_line);
matching = xact; matching = xact;

View file

@ -93,10 +93,10 @@ string source_context(const path& file,
assert(len < 8192); assert(len < 8192);
std::ostringstream out; std::ostringstream out;
ifstream in(file); ifstream in(file);
in.seekg(pos, std::ios::beg); in.seekg(pos, std::ios::beg);
scoped_array<char> buf(new char[static_cast<std::size_t>(len) + 1]); scoped_array<char> buf(new char[static_cast<std::size_t>(len) + 1]);
in.read(buf.get(), static_cast<std::streamsize>(len)); in.read(buf.get(), static_cast<std::streamsize>(len));
assert(in.gcount() == static_cast<std::streamsize>(len)); assert(in.gcount() == static_cast<std::streamsize>(len));

View file

@ -130,7 +130,7 @@ public:
const optional<string>& original_string = none) { const optional<string>& original_string = none) {
set_text(original_string ? *original_string : "<stream>"); set_text(original_string ? *original_string : "<stream>");
} }
virtual void mark_uncompiled() { virtual void mark_uncompiled() {
compiled = false; compiled = false;
} }

View file

@ -53,7 +53,7 @@ void post_splitter::flush()
{ {
foreach (value_to_posts_map::value_type& pair, posts_map) { foreach (value_to_posts_map::value_type& pair, posts_map) {
preflush_func(pair.first); preflush_func(pair.first);
foreach (post_t * post, pair.second) foreach (post_t * post, pair.second)
(*post_chain)(*post); (*post_chain)(*post);
@ -83,25 +83,6 @@ void post_splitter::operator()(post_t& post)
} }
} }
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&) {
add_error_context(item_context(*post, _("While handling posting")));
throw;
}
}
item_handler<post_t>::flush();
}
void truncate_xacts::flush() void truncate_xacts::flush()
{ {
if (! posts.size()) if (! posts.size())
@ -434,7 +415,7 @@ void collapse_posts::report_subtotal()
bind_scope_t bound_scope(report, *post); bind_scope_t bound_scope(report, *post);
if (only_predicate(bound_scope) && display_predicate(bound_scope)) if (only_predicate(bound_scope) && display_predicate(bound_scope))
displayed_count++; displayed_count++;
} }
if (displayed_count == 1) { if (displayed_count == 1) {
item_handler<post_t>::operator()(*last_post); item_handler<post_t>::operator()(*last_post);
@ -460,6 +441,7 @@ void collapse_posts::report_subtotal()
xact.payee = last_xact->payee; xact.payee = last_xact->payee;
xact._date = (is_valid(earliest_date) ? xact._date = (is_valid(earliest_date) ?
earliest_date : last_xact->_date); earliest_date : last_xact->_date);
DEBUG("filters.collapse", "Pseudo-xact date = " << *xact._date); DEBUG("filters.collapse", "Pseudo-xact date = " << *xact._date);
DEBUG("filters.collapse", "earliest date = " << earliest_date); DEBUG("filters.collapse", "earliest date = " << earliest_date);
DEBUG("filters.collapse", "latest date = " << latest_date); DEBUG("filters.collapse", "latest date = " << latest_date);
@ -523,14 +505,11 @@ display_filter_posts::display_filter_posts(post_handler_ptr handler,
report_t& _report, report_t& _report,
bool _show_rounding) bool _show_rounding)
: item_handler<post_t>(handler), report(_report), : item_handler<post_t>(handler), report(_report),
display_amount_expr(report.HANDLER(display_amount_).expr),
display_total_expr(report.HANDLER(display_total_).expr),
show_rounding(_show_rounding) show_rounding(_show_rounding)
{ {
TRACE_CTOR(display_filter_posts, TRACE_CTOR(display_filter_posts, "post_handler_ptr, report_t&, bool");
"post_handler_ptr, report_t&, account_t&, bool");
display_amount_expr = report.HANDLER(display_amount_).expr;
display_total_expr = report.HANDLER(display_total_).expr;
create_accounts(); create_accounts();
} }
@ -606,17 +585,17 @@ changed_value_posts::changed_value_posts
bool _show_unrealized, bool _show_unrealized,
display_filter_posts * _display_filter) display_filter_posts * _display_filter)
: item_handler<post_t>(handler), report(_report), : item_handler<post_t>(handler), report(_report),
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)),
for_accounts_report(_for_accounts_report), for_accounts_report(_for_accounts_report),
show_unrealized(_show_unrealized), last_post(NULL), show_unrealized(_show_unrealized), last_post(NULL),
display_filter(_display_filter) display_filter(_display_filter)
{ {
TRACE_CTOR(changed_value_posts, "post_handler_ptr, report_t&, bool"); TRACE_CTOR(changed_value_posts,
"post_handler_ptr, report_t&, bool, bool, display_filter_posts *");
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; string gains_equity_account_name;
if (report.HANDLED(unrealized_gains_)) if (report.HANDLED(unrealized_gains_))
@ -755,7 +734,7 @@ void changed_value_posts::output_intermediate_prices(post_t& post,
case value_t::DATE: case value_t::DATE:
default: default:
assert(false); assert(false);
break; break;
} }
bind_scope_t inner_scope(report, temp); bind_scope_t inner_scope(report, temp);
@ -937,8 +916,6 @@ void interval_posts::report_subtotal(const date_interval_t& interval)
void interval_posts::operator()(post_t& post) void interval_posts::operator()(post_t& post)
{ {
date_t date = post.date();
if (! interval.find_period(post.date())) if (! interval.find_period(post.date()))
return; return;
@ -1373,7 +1350,7 @@ inject_posts::inject_posts(post_handler_ptr handler,
account_t * master) account_t * master)
: item_handler<post_t>(handler) : item_handler<post_t>(handler)
{ {
TRACE_CTOR(inject_posts, "post_handler_ptr, string"); TRACE_CTOR(inject_posts, "post_handler_ptr, string, account_t *");
scoped_array<char> buf(new char[tag_list.length() + 1]); scoped_array<char> buf(new char[tag_list.length() + 1]);
std::strcpy(buf.get(), tag_list.c_str()); std::strcpy(buf.get(), tag_list.c_str());
@ -1381,9 +1358,9 @@ inject_posts::inject_posts(post_handler_ptr handler,
for (char * q = std::strtok(buf.get(), ","); for (char * q = std::strtok(buf.get(), ",");
q; q;
q = std::strtok(NULL, ",")) { q = std::strtok(NULL, ",")) {
std::list<string> account_names; std::list<string> account_names;
split_string(q, ':', account_names); split_string(q, ':', account_names);
account_t * account = account_t * account =
create_temp_account_from_path(account_names, temps, master); create_temp_account_from_path(account_names, temps, master);
account->add_flags(ACCOUNT_GENERATED); account->add_flags(ACCOUNT_GENERATED);
@ -1397,13 +1374,12 @@ void inject_posts::operator()(post_t& post)
{ {
foreach (tags_list_pair& pair, tags_list) { foreach (tags_list_pair& pair, tags_list) {
optional<value_t> tag_value = post.get_tag(pair.first, false); optional<value_t> tag_value = post.get_tag(pair.first, false);
// When checking if the transaction has the tag, only inject once
// per transaction.
if (! tag_value && if (! tag_value &&
pair.second.second.find(post.xact) == pair.second.second.end()) { pair.second.second.find(post.xact) == pair.second.second.end() &&
// When checking if the transaction has the tag, only inject once (tag_value = post.xact->get_tag(pair.first)))
// per transaction.
pair.second.second.insert(post.xact); pair.second.second.insert(post.xact);
tag_value = post.xact->get_tag(pair.first);
}
if (tag_value) { if (tag_value) {
xact_t& xact = temps.copy_xact(*post.xact); xact_t& xact = temps.copy_xact(*post.xact);
@ -1422,25 +1398,4 @@ void inject_posts::operator()(post_t& post)
item_handler<post_t>::operator()(post); item_handler<post_t>::operator()(post);
} }
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 } // namespace ledger

View file

@ -73,10 +73,10 @@ public:
post_splitter(post_handler_ptr _post_chain, post_splitter(post_handler_ptr _post_chain,
report_t& _report, report_t& _report,
expr_t _group_by_expr) expr_t _group_by_expr)
: post_chain(_post_chain), report(_report), : post_chain(_post_chain), report(_report),
group_by_expr(_group_by_expr) { group_by_expr(_group_by_expr) {
TRACE_CTOR(post_splitter, "scope_t&, post_handler_ptr, expr_t"); TRACE_CTOR(post_splitter, "scope_t&, post_handler_ptr, expr_t");
preflush_func = bind(&post_splitter::print_title, this, _1); preflush_func = bind(&post_splitter::print_title, this, _1);
} }
virtual ~post_splitter() { virtual ~post_splitter() {
TRACE_DTOR(post_splitter); TRACE_DTOR(post_splitter);
@ -97,6 +97,7 @@ public:
virtual void clear() { virtual void clear() {
posts_map.clear(); posts_map.clear();
post_chain->clear(); post_chain->clear();
item_handler<post_t>::clear();
} }
}; };
@ -145,14 +146,28 @@ public:
} }
}; };
class posts_iterator; template <typename Iterator>
class pass_down_posts : public item_handler<post_t> class pass_down_posts : public item_handler<post_t>
{ {
pass_down_posts(); pass_down_posts();
public: public:
pass_down_posts(post_handler_ptr handler, posts_iterator& iter); pass_down_posts(post_handler_ptr handler, Iterator& iter)
: item_handler<post_t>(handler) {
TRACE_CTOR(pass_down_posts, "post_handler_ptr, posts_iterator");
while (post_t * post = *iter++) {
try {
item_handler<post_t>::operator()(*post);
}
catch (const std::exception&) {
add_error_context(item_context(*post, _("While handling posting")));
throw;
}
}
item_handler<post_t>::flush();
}
virtual ~pass_down_posts() { virtual ~pass_down_posts() {
TRACE_DTOR(pass_down_posts); TRACE_DTOR(pass_down_posts);
@ -295,7 +310,7 @@ public:
virtual void clear() { virtual void clear() {
sorter.clear(); sorter.clear();
last_xact = NULL; last_xact = NULL;
item_handler<post_t>::clear(); item_handler<post_t>::clear();
} }
}; };
@ -365,8 +380,9 @@ public:
virtual void clear() { virtual void clear() {
temps.clear(); temps.clear();
comms.clear();
last_xact = NULL; last_xact = NULL;
item_handler<post_t>::clear(); item_handler<post_t>::clear();
} }
}; };
@ -442,7 +458,7 @@ public:
} }
virtual void flush() { virtual void flush() {
report_subtotal(); report_subtotal();
item_handler<post_t>::flush(); item_handler<post_t>::flush();
} }
@ -463,7 +479,7 @@ public:
temps.clear(); temps.clear();
create_accounts(); create_accounts();
component_posts.clear(); component_posts.clear();
item_handler<post_t>::clear(); item_handler<post_t>::clear();
} }
}; };
@ -504,9 +520,9 @@ class display_filter_posts : public item_handler<post_t>
// This filter requires that calc_posts be used at some point // This filter requires that calc_posts be used at some point
// later in the chain. // later in the chain.
report_t& report;
expr_t display_amount_expr; expr_t display_amount_expr;
expr_t display_total_expr; expr_t display_total_expr;
report_t& report;
bool show_rounding; bool show_rounding;
value_t last_display_total; value_t last_display_total;
temporaries_t temps; temporaries_t temps;
@ -552,9 +568,9 @@ class changed_value_posts : public item_handler<post_t>
// This filter requires that calc_posts be used at some point // This filter requires that calc_posts be used at some point
// later in the chain. // later in the chain.
report_t& report;
expr_t total_expr; expr_t total_expr;
expr_t display_total_expr; expr_t display_total_expr;
report_t& report;
bool changed_values_only; bool changed_values_only;
bool for_accounts_report; bool for_accounts_report;
bool show_unrealized; bool show_unrealized;
@ -984,8 +1000,7 @@ class inject_posts : public item_handler<post_t>
// Account filters // Account filters
// //
class accounts_iterator; template <typename Iterator>
class pass_down_accounts : public item_handler<account_t> class pass_down_accounts : public item_handler<account_t>
{ {
pass_down_accounts(); pass_down_accounts();
@ -995,9 +1010,24 @@ class pass_down_accounts : public item_handler<account_t>
public: public:
pass_down_accounts(acct_handler_ptr handler, pass_down_accounts(acct_handler_ptr handler,
accounts_iterator& iter, Iterator& iter,
const optional<predicate_t>& _pred = none, const optional<predicate_t>& _pred = none,
const optional<scope_t&>& _context = none); const optional<scope_t&>& _context = none)
: item_handler<account_t>(handler), pred(_pred), context(_context) {
TRACE_CTOR(pass_down_accounts, "acct_handler_ptr, accounts_iterator, ...");
while (account_t * 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();
}
virtual ~pass_down_accounts() { virtual ~pass_down_accounts() {
TRACE_DTOR(pass_down_accounts); TRACE_DTOR(pass_down_accounts);

View file

@ -271,14 +271,14 @@ void generate_posts_iterator::generate_date(std::ostream& out)
out.width(4); out.width(4);
out.fill('0'); out.fill('0');
out << year_gen(); out << year_gen();
out.width(1); out.width(1);
out << '/'; out << '/';
out.width(2); out.width(2);
out.fill('0'); out.fill('0');
out << mon_gen(); out << mon_gen();
out.width(1); out.width(1);
out << '/'; out << '/';
@ -350,9 +350,10 @@ void generate_posts_iterator::generate_xact(std::ostream& out)
out << '\n'; out << '\n';
} }
post_t * generate_posts_iterator::operator()() void generate_posts_iterator::increment()
{ {
post_t * post = posts(); post_t * post = *posts++;
if (post == NULL && quantity > 0) { if (post == NULL && quantity > 0) {
std::ostringstream buf; std::ostringstream buf;
generate_xact(buf); generate_xact(buf);
@ -364,7 +365,7 @@ post_t * generate_posts_iterator::operator()()
if (session.journal->parse(in, session) != 0) { if (session.journal->parse(in, session) != 0) {
VERIFY(session.journal->xacts.back()->valid()); VERIFY(session.journal->xacts.back()->valid());
posts.reset(*session.journal->xacts.back()); posts.reset(*session.journal->xacts.back());
post = posts(); post = *posts++;
} }
} }
catch (std::exception&) { catch (std::exception&) {
@ -382,7 +383,8 @@ post_t * generate_posts_iterator::operator()()
quantity--; quantity--;
} }
return post;
m_node = post;
} }
} // namespace ledger } // namespace ledger

View file

@ -48,7 +48,9 @@ namespace ledger {
class session_t; class session_t;
class generate_posts_iterator : public posts_iterator class generate_posts_iterator
: public iterator_facade_base<generate_posts_iterator, post_t *,
boost::forward_traversal_tag>
{ {
session_t& session; session_t& session;
unsigned int seed; unsigned int seed;
@ -104,8 +106,8 @@ public:
virtual ~generate_posts_iterator() throw() { virtual ~generate_posts_iterator() throw() {
TRACE_DTOR(generate_posts_iterator); TRACE_DTOR(generate_posts_iterator);
} }
virtual post_t * operator()(); virtual void increment();
protected: protected:
void generate_string(std::ostream& out, int len, bool only_alpha = false); void generate_string(std::ostream& out, int len, bool only_alpha = false);

View file

@ -535,7 +535,7 @@ string item_context(const item_t& item, const string& desc)
assert(len < 8192); assert(len < 8192);
std::ostringstream out; std::ostringstream out;
if (item.pos->pathname == path("/dev/stdin")) { if (item.pos->pathname == path("/dev/stdin")) {
out << desc << _(" from standard input:"); out << desc << _(" from standard input:");
return out.str(); return out.str();

View file

@ -41,37 +41,38 @@ void xacts_iterator::reset(journal_t& journal)
{ {
xacts_i = journal.xacts.begin(); xacts_i = journal.xacts.begin();
xacts_end = journal.xacts.end(); xacts_end = journal.xacts.end();
xacts_uninitialized = false; xacts_uninitialized = false;
increment();
} }
xact_t * xacts_iterator::operator()() void xacts_iterator::increment()
{ {
if (xacts_i != xacts_end) if (xacts_i != xacts_end)
return *xacts_i++; m_node = *xacts_i++;
else else
return NULL; m_node = NULL;
} }
void journal_posts_iterator::reset(journal_t& journal) void journal_posts_iterator::reset(journal_t& journal)
{ {
xacts.reset(journal); xacts.reset(journal);
increment();
xact_t * xact = xacts();
if (xact != NULL)
posts.reset(*xact);
} }
post_t * journal_posts_iterator::operator()() void journal_posts_iterator::increment()
{ {
post_t * post = posts(); if (post_t * post = *posts++) {
if (post == NULL) { m_node = post;
xact_t * xact = xacts(); }
if (xact != NULL) { else if (xact_t * xact = *xacts++) {
posts.reset(*xact); posts.reset(*xact);
post = posts(); m_node = *posts++;
} }
else {
m_node = NULL;
} }
return post;
} }
void posts_commodities_iterator::reset(journal_t& journal) void posts_commodities_iterator::reset(journal_t& journal)
@ -80,7 +81,7 @@ void posts_commodities_iterator::reset(journal_t& journal)
std::set<commodity_t *> commodities; std::set<commodity_t *> commodities;
for (post_t * post = journal_posts(); post; post = journal_posts()) { while (const post_t * post = *journal_posts++) {
commodity_t& comm(post->amount.commodity()); commodity_t& comm(post->amount.commodity());
if (comm.flags() & COMMODITY_NOMARKET) if (comm.flags() & COMMODITY_NOMARKET)
continue; continue;
@ -136,47 +137,44 @@ void posts_commodities_iterator::reset(journal_t& journal)
} }
} }
xacts.xacts_i = xact_temps.begin(); xacts.reset(xact_temps.begin(), xact_temps.end());
xacts.xacts_end = xact_temps.end();
xacts.xacts_uninitialized = false; increment();
xact_t * xact = xacts();
if (xact != NULL)
posts.reset(*xact);
} }
post_t * posts_commodities_iterator::operator()() void posts_commodities_iterator::increment()
{ {
post_t * post = posts(); if (post_t * post = *posts++) {
if (post == NULL) { m_node = post;
xact_t * xact = xacts(); }
if (xact != NULL) { else if (xact_t * xact = *xacts++) {
posts.reset(*xact); posts.reset(*xact);
post = posts(); m_node = *posts++;
} }
else {
m_node = NULL;
} }
return post;
} }
account_t * basic_accounts_iterator::operator()() void basic_accounts_iterator::increment()
{ {
while (! accounts_i.empty() && while (! accounts_i.empty() && accounts_i.back() == accounts_end.back()) {
accounts_i.back() == accounts_end.back()) {
accounts_i.pop_back(); accounts_i.pop_back();
accounts_end.pop_back(); accounts_end.pop_back();
} }
if (accounts_i.empty())
return NULL;
account_t * account = (*(accounts_i.back()++)).second; if (accounts_i.empty()) {
assert(account); m_node = NULL;
} else {
account_t * account = (*(accounts_i.back()++)).second;
assert(account);
// If this account has children, queue them up to be iterated next. // If this account has children, queue them up to be iterated next.
if (! account->accounts.empty()) if (! account->accounts.empty())
push_back(*account); push_back(*account);
return account; m_node = account;
}
} }
void sorted_accounts_iterator::push_back(account_t& account) void sorted_accounts_iterator::push_back(account_t& account)
@ -231,7 +229,7 @@ void sorted_accounts_iterator::sort_accounts(account_t& account,
#endif #endif
} }
account_t * sorted_accounts_iterator::operator()() void sorted_accounts_iterator::increment()
{ {
while (! sorted_accounts_i.empty() && while (! sorted_accounts_i.empty() &&
sorted_accounts_i.back() == sorted_accounts_end.back()) { sorted_accounts_i.back() == sorted_accounts_end.back()) {
@ -240,19 +238,22 @@ account_t * sorted_accounts_iterator::operator()()
assert(! accounts_list.empty()); assert(! accounts_list.empty());
accounts_list.pop_back(); accounts_list.pop_back();
} }
if (sorted_accounts_i.empty())
return NULL;
account_t * account = *sorted_accounts_i.back()++; if (sorted_accounts_i.empty()) {
assert(account); m_node = NULL;
} else {
account_t * account = *sorted_accounts_i.back()++;
assert(account);
// If this account has children, queue them up to be iterated next. // If this account has children, queue them up to be iterated next.
if (! flatten_all && ! account->accounts.empty()) if (! flatten_all && ! account->accounts.empty())
push_back(*account); push_back(*account);
// Make sure the sorting value gets recalculated for this account // Make sure the sorting value gets recalculated for this account
account->xdata().drop_flags(ACCOUNT_EXT_SORT_CALC); account->xdata().drop_flags(ACCOUNT_EXT_SORT_CALC);
return account;
m_node = account;
}
} }
} // namespace ledger } // namespace ledger

View file

@ -51,14 +51,35 @@ namespace ledger {
class journal_t; class journal_t;
class posts_iterator : public noncopyable template <typename Derived, typename Value, typename CategoryOrTraversal>
class iterator_facade_base
: public boost::iterator_facade<Derived, Value, CategoryOrTraversal>
{ {
typedef Value node_base;
public: public:
virtual ~posts_iterator() throw() {} iterator_facade_base() : m_node(NULL) {}
virtual post_t * operator()() = 0;
explicit iterator_facade_base(node_base p) : m_node(p) {}
void increment();
private:
friend class boost::iterator_core_access;
bool equal(iterator_facade_base const& other) const {
return this->m_node == other.m_node;
}
node_base& dereference() const { return const_cast<node_base&>(m_node); }
protected:
node_base m_node;
}; };
class xact_posts_iterator : public posts_iterator class xact_posts_iterator
: public iterator_facade_base<xact_posts_iterator, post_t *,
boost::forward_traversal_tag>
{ {
posts_list::iterator posts_i; posts_list::iterator posts_i;
posts_list::iterator posts_end; posts_list::iterator posts_end;
@ -66,33 +87,33 @@ class xact_posts_iterator : public posts_iterator
bool posts_uninitialized; bool posts_uninitialized;
public: public:
xact_posts_iterator() : posts_uninitialized(true) { xact_posts_iterator() : posts_uninitialized(true) {}
TRACE_CTOR(xact_posts_iterator, "");
}
xact_posts_iterator(xact_t& xact) xact_posts_iterator(xact_t& xact)
: posts_uninitialized(true) { : posts_uninitialized(true) {
TRACE_CTOR(xact_posts_iterator, "xact_t&");
reset(xact); reset(xact);
} }
virtual ~xact_posts_iterator() throw() { ~xact_posts_iterator() throw() {}
TRACE_DTOR(xact_posts_iterator);
}
void reset(xact_t& xact) { void reset(xact_t& xact) {
posts_i = xact.posts.begin(); posts_i = xact.posts.begin();
posts_end = xact.posts.end(); posts_end = xact.posts.end();
posts_uninitialized = false; posts_uninitialized = false;
increment();
} }
virtual post_t * operator()() { void increment() {
if (posts_uninitialized || posts_i == posts_end) if (posts_uninitialized || posts_i == posts_end)
return NULL; m_node = NULL;
return *posts_i++; else
m_node = *posts_i++;
} }
}; };
class xacts_iterator : public noncopyable class xacts_iterator
: public iterator_facade_base<xacts_iterator, xact_t *,
boost::forward_traversal_tag>
{ {
public: public:
xacts_list::iterator xacts_i; xacts_list::iterator xacts_i;
@ -100,45 +121,49 @@ public:
bool xacts_uninitialized; bool xacts_uninitialized;
xacts_iterator() : xacts_uninitialized(true) { xacts_iterator() : xacts_uninitialized(true) {}
TRACE_CTOR(xacts_iterator, ""); xacts_iterator(journal_t& journal) : xacts_uninitialized(false) {
}
xacts_iterator(journal_t& journal) : xacts_uninitialized(true) {
TRACE_CTOR(xacts_iterator, "journal_t&");
reset(journal); reset(journal);
} }
virtual ~xacts_iterator() throw() { xacts_iterator(xacts_list::iterator beg,
TRACE_DTOR(xacts_iterator); xacts_list::iterator end) : xacts_uninitialized(false) {
reset(beg, end);
} }
~xacts_iterator() throw() {}
void reset(journal_t& journal); void reset(journal_t& journal);
xact_t * operator()(); void reset(xacts_list::iterator beg, xacts_list::iterator end) {
xacts_i = beg;
xacts_end = end;
increment();
}
void increment();
}; };
class journal_posts_iterator : public posts_iterator class journal_posts_iterator
: public iterator_facade_base<journal_posts_iterator, post_t *,
boost::forward_traversal_tag>
{ {
xacts_iterator xacts; xacts_iterator xacts;
xact_posts_iterator posts; xact_posts_iterator posts;
public: public:
journal_posts_iterator() { journal_posts_iterator() {}
TRACE_CTOR(journal_posts_iterator, "");
}
journal_posts_iterator(journal_t& journal) { journal_posts_iterator(journal_t& journal) {
TRACE_CTOR(journal_posts_iterator, "journal_t&");
reset(journal); reset(journal);
} }
virtual ~journal_posts_iterator() throw() { ~journal_posts_iterator() throw() {}
TRACE_DTOR(journal_posts_iterator);
}
void reset(journal_t& journal); void reset(journal_t& journal);
virtual post_t * operator()(); void increment();
}; };
class posts_commodities_iterator : public posts_iterator class posts_commodities_iterator
: public iterator_facade_base<posts_commodities_iterator, post_t *,
boost::forward_traversal_tag>
{ {
protected: protected:
journal_posts_iterator journal_posts; journal_posts_iterator journal_posts;
@ -148,55 +173,44 @@ protected:
xacts_list xact_temps; xacts_list xact_temps;
public: public:
posts_commodities_iterator() { posts_commodities_iterator() {}
TRACE_CTOR(posts_commodities_iterator, "");
}
posts_commodities_iterator(journal_t& journal) { posts_commodities_iterator(journal_t& journal) {
TRACE_CTOR(posts_commodities_iterator, "journal_t&");
reset(journal); reset(journal);
} }
virtual ~posts_commodities_iterator() throw() { ~posts_commodities_iterator() throw() {}
TRACE_DTOR(posts_commodities_iterator);
}
void reset(journal_t& journal); void reset(journal_t& journal);
virtual post_t * operator()(); void increment();
}; };
class accounts_iterator : public noncopyable class basic_accounts_iterator
{ : public iterator_facade_base<basic_accounts_iterator, account_t *,
public: boost::forward_traversal_tag>
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_i;
std::list<accounts_map::const_iterator> accounts_end; std::list<accounts_map::const_iterator> accounts_end;
public: public:
basic_accounts_iterator() { basic_accounts_iterator() {}
TRACE_CTOR(basic_accounts_iterator, "");
}
basic_accounts_iterator(account_t& account) { basic_accounts_iterator(account_t& account) {
TRACE_CTOR(basic_accounts_iterator, "account_t&");
push_back(account); push_back(account);
increment();
} }
virtual ~basic_accounts_iterator() throw() { ~basic_accounts_iterator() throw() {}
TRACE_DTOR(basic_accounts_iterator);
}
void increment();
private:
void push_back(account_t& account) { void push_back(account_t& account) {
accounts_i.push_back(account.accounts.begin()); accounts_i.push_back(account.accounts.begin());
accounts_end.push_back(account.accounts.end()); accounts_end.push_back(account.accounts.end());
} }
virtual account_t * operator()();
}; };
class sorted_accounts_iterator : public accounts_iterator class sorted_accounts_iterator
: public iterator_facade_base<sorted_accounts_iterator, account_t *,
boost::forward_traversal_tag>
{ {
expr_t sort_cmp; expr_t sort_cmp;
bool flatten_all; bool flatten_all;
@ -211,18 +225,17 @@ public:
sorted_accounts_iterator(account_t& account, sorted_accounts_iterator(account_t& account,
const expr_t& _sort_cmp, bool _flatten_all) const expr_t& _sort_cmp, bool _flatten_all)
: sort_cmp(_sort_cmp), flatten_all(_flatten_all) { : sort_cmp(_sort_cmp), flatten_all(_flatten_all) {
TRACE_CTOR(sorted_accounts_iterator, "const expr_t&, bool, account_t&");
push_back(account); push_back(account);
increment();
} }
virtual ~sorted_accounts_iterator() throw() { ~sorted_accounts_iterator() throw() {}
TRACE_DTOR(sorted_accounts_iterator);
}
void increment();
private:
void push_back(account_t& account); void push_back(account_t& account);
void push_all(account_t& account, accounts_deque_t& deque); void push_all(account_t& account, accounts_deque_t& deque);
void sort_accounts(account_t& account, accounts_deque_t& deque); void sort_accounts(account_t& account, accounts_deque_t& deque);
virtual account_t * operator()();
}; };
} // namespace ledger } // namespace ledger

View file

@ -74,7 +74,7 @@ journal_t::~journal_t()
foreach (period_xact_t * xact, period_xacts) foreach (period_xact_t * xact, period_xacts)
checked_delete(xact); checked_delete(xact);
checked_delete(master); checked_delete(master);
} }

View file

@ -60,9 +60,10 @@ namespace {
} }
std::pair<xact_t *, account_t *> std::pair<xact_t *, account_t *>
lookup_probable_account(const string& ident, lookup_probable_account(const string& ident,
xacts_iterator& iter_func, xacts_list::reverse_iterator iter,
account_t * ref_account) xacts_list::reverse_iterator end,
account_t * ref_account)
{ {
scorecard_t scores; scorecard_t scores;
@ -83,14 +84,15 @@ lookup_probable_account(const string& ident,
" with reference account: " << ref_account->fullname()); " with reference account: " << ref_account->fullname());
#endif #endif
while (xact_t * xact = iter_func()) { xact_t * xact;
while (iter != end && (xact = *iter++) != NULL) {
#if 0 #if 0
// Only consider transactions from the last two years (jww (2010-03-07): // Only consider transactions from the last two years (jww (2010-03-07):
// make this an option) // make this an option)
if ((CURRENT_DATE() - xact->date()).days() > 700) if ((CURRENT_DATE() - xact->date()).days() > 700)
continue; continue;
#endif #endif
// An exact match is worth a score of 100 and terminates the search // An exact match is worth a score of 100 and terminates the search
if (ident == xact->payee) { if (ident == xact->payee) {
DEBUG("lookup", " we have an exact match, score = 100"); DEBUG("lookup", " we have an exact match, score = 100");

View file

@ -47,9 +47,10 @@
namespace ledger { namespace ledger {
std::pair<xact_t *, account_t *> std::pair<xact_t *, account_t *>
lookup_probable_account(const string& ident, lookup_probable_account(const string& ident,
xacts_iterator& iter_func, xacts_list::reverse_iterator iter,
account_t * ref_account = NULL); xacts_list::reverse_iterator end,
account_t * ref_account = NULL);
} // namespace ledger } // namespace ledger

View file

@ -164,6 +164,11 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus, const int depth)
result = as_value(); result = as_value();
break; break;
case O_DEFINE:
//result = left()->calc(scope, locus, depth + 1);
result = NULL_VALUE;
break;
case IDENT: { case IDENT: {
ptr_op_t definition = left(); ptr_op_t definition = left();
if (! definition) { if (! definition) {
@ -416,10 +421,8 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus, const int depth)
break; break;
} }
case LAST:
default: default:
assert(false); throw_(calc_error, _("Unexpected expr node '%1'") << op_context(this));
break;
} }
#if defined(DEBUG_ON) #if defined(DEBUG_ON)
@ -435,7 +438,7 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus, const int depth)
return result; return result;
} }
catch (const std::exception&) { catch (const std::exception&) {
if (locus && ! *locus) if (locus && ! *locus)
*locus = this; *locus = this;
throw; throw;

View file

@ -89,7 +89,7 @@ namespace {
catch (const std::exception&) { catch (const std::exception&) {
if (name[0] == '-') if (name[0] == '-')
add_error_context(_("While parsing option '%1'") << name); add_error_context(_("While parsing option '%1'") << name);
else else
add_error_context(_("While parsing environent variable '%1'") << name); add_error_context(_("While parsing environent variable '%1'") << name);
throw; throw;
@ -156,7 +156,7 @@ namespace {
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) {} : op(_op), truth(_truth), ch(_ch) {}
}; };
} }
strings_list process_arguments(strings_list args, scope_t& scope) strings_list process_arguments(strings_list args, scope_t& scope)
{ {

View file

@ -209,10 +209,12 @@ public:
#define CTOR(type, name) \ #define CTOR(type, name) \
name ## option_t() : option_t<type>(#name) name ## option_t() : option_t<type>(#name)
#define CTOR_(type, name, base) \
name ## option_t() : option_t<type>(#name), base
#define DECL1(type, name, vartype, var, value) \ #define DECL1(type, name, vartype, var, value) \
vartype var ; \ vartype var ; \
name ## option_t() : option_t<type>(#name), var(value) name ## option_t() : option_t<type>(#name), var(value)
#define DO() virtual void handler_thunk(call_scope_t&) #define DO() virtual void handler_thunk(call_scope_t&)
#define DO_(var) virtual void handler_thunk(call_scope_t& var) #define DO_(var) virtual void handler_thunk(call_scope_t& var)

View file

@ -298,7 +298,7 @@ commodity_pool_t::exchange(const amount_t& amount,
annotation.add_flags(ANNOTATION_DATE_CALCULATED); annotation.add_flags(ANNOTATION_DATE_CALCULATED);
if (tag) if (tag)
annotation.add_flags(ANNOTATION_TAG_CALCULATED); annotation.add_flags(ANNOTATION_TAG_CALCULATED);
breakdown.amount = amount_t(amount, annotation); breakdown.amount = amount_t(amount, annotation);
DEBUG("commodity.prices.add", DEBUG("commodity.prices.add",

View file

@ -115,7 +115,7 @@ date_t post_t::actual_date() const
return xact->date(); return xact->date();
} }
return *_date; return *_date;
} }
optional<date_t> post_t::effective_date() const optional<date_t> post_t::effective_date() const
{ {
@ -341,7 +341,7 @@ namespace {
value_t get_value_date(post_t& post) { value_t get_value_date(post_t& post) {
if (post.has_xdata()) { if (post.has_xdata()) {
post_t::xdata_t& xdata(post.xdata()); post_t::xdata_t& xdata(post.xdata());
if (! xdata.value_date.is_not_a_date()) if (! xdata.value_date.is_not_a_date())
return xdata.value_date; return xdata.value_date;
} }
return post.date(); return post.date();

View file

@ -99,7 +99,7 @@ class ptristream : public std::istream
protected: protected:
ptrinbuf buf; ptrinbuf buf;
public: public:
ptristream(char * ptr, std::size_t len = 0) ptristream(char * ptr, std::size_t len = 0)
: std::istream(0), buf(ptr, len) { : std::istream(0), buf(ptr, len) {
rdbuf(&buf); rdbuf(&buf);

View file

@ -56,7 +56,7 @@ namespace {
datetime_t& moment) { datetime_t& moment) {
return balance.value(moment, in_terms_of); return balance.value(moment, in_terms_of);
} }
boost::optional<amount_t> boost::optional<amount_t>
py_commodity_amount_0(const balance_t& balance) { py_commodity_amount_0(const balance_t& balance) {
return balance.commodity_amount(); return balance.commodity_amount();

View file

@ -181,7 +181,7 @@ namespace {
const datetime_t& date, const amount_t& price) { const datetime_t& date, const amount_t& price) {
commodity.add_price(date, price); commodity.add_price(date, price);
} }
void py_add_price_3(commodity_t& commodity, const datetime_t& date, void py_add_price_3(commodity_t& commodity, const datetime_t& date,
const amount_t& price, const bool reflexive) { const amount_t& price, const bool reflexive) {
commodity.add_price(date, price, reflexive); commodity.add_price(date, price, reflexive);

View file

@ -191,7 +191,7 @@ namespace {
coll->chain = coll->chain =
chain_post_handlers(post_handler_ptr(coll->posts_collector), chain_post_handlers(post_handler_ptr(coll->posts_collector),
coll->report); coll->report);
pass_down_posts(coll->chain, walker); pass_down_posts<journal_posts_iterator>(coll->chain, walker);
} }
catch (...) { catch (...) {
current_report.session.journal.release(); current_report.session.journal.release();

View file

@ -173,7 +173,7 @@ void export_post()
.def("xdata", py_xdata, .def("xdata", py_xdata,
return_internal_reference<>()) return_internal_reference<>())
.def("add_to_value", &post_t::add_to_value) //.def("add_to_value", &post_t::add_to_value)
.def("set_reported_account", &post_t::set_reported_account) .def("set_reported_account", &post_t::set_reported_account)
.def("reported_account", py_reported_account, .def("reported_account", py_reported_account,

View file

@ -140,7 +140,7 @@ void export_xact()
class_< period_xact_t, bases<xact_base_t> > ("PeriodicTransaction") class_< period_xact_t, bases<xact_base_t> > ("PeriodicTransaction")
.def(init<string>()) .def(init<string>())
.add_property("period", .add_property("period",
make_getter(&period_xact_t::period), make_getter(&period_xact_t::period),
make_setter(&period_xact_t::period)) make_setter(&period_xact_t::period))

View file

@ -126,7 +126,7 @@ void python_interpreter_t::initialize()
void python_interpreter_t::hack_system_paths() void python_interpreter_t::hack_system_paths()
{ {
// Hack ledger.__path__ so it points to a real location // Hack ledger.__path__ so it points to a real location
python::object sys_module = python::import("sys"); python::object sys_module = python::import("sys");
python::object sys_dict = sys_module.attr("__dict__"); python::object sys_dict = sys_module.attr("__dict__");
python::list paths(sys_dict["path"]); python::list paths(sys_dict["path"]);
@ -177,7 +177,7 @@ object python_interpreter_t::import_into_main(const string& str)
if (! mod) if (! mod)
throw_(std::runtime_error, throw_(std::runtime_error,
_("Failed to import Python module %1") << str); _("Failed to import Python module %1") << str);
// Import all top-level entries directly into the main namespace // Import all top-level entries directly into the main namespace
main_nspace.update(mod.attr("__dict__")); main_nspace.update(mod.attr("__dict__"));
@ -193,7 +193,7 @@ object python_interpreter_t::import_option(const string& str)
{ {
path file(str); path file(str);
python::object sys_module = python::import("sys"); python::object sys_module = python::import("sys");
python::object sys_dict = sys_module.attr("__dict__"); python::object sys_dict = sys_module.attr("__dict__");
python::list paths(sys_dict["path"]); python::list paths(sys_dict["path"]);
@ -312,7 +312,7 @@ value_t python_interpreter_t::python_command(call_scope_t& args)
delete[] argv; delete[] argv;
throw; throw;
} }
for (std::size_t i = 0; i < args.size() + 1; i++) for (std::size_t i = 0; i < args.size() + 1; i++)
delete[] argv[i]; delete[] argv[i];
delete[] argv; delete[] argv;
@ -445,7 +445,7 @@ namespace {
} }
} }
} }
value_t python_interpreter_t::functor_t::operator()(call_scope_t& args) value_t python_interpreter_t::functor_t::operator()(call_scope_t& args)
{ {
try { try {

View file

@ -48,7 +48,7 @@ public:
: session_t(), main_nspace(), is_initialized(false) { : session_t(), main_nspace(), is_initialized(false) {
TRACE_CTOR(python_interpreter_t, ""); TRACE_CTOR(python_interpreter_t, "");
} }
virtual ~python_interpreter_t() { virtual ~python_interpreter_t() {
TRACE_DTOR(python_interpreter_t); TRACE_DTOR(python_interpreter_t);

View file

@ -173,7 +173,7 @@ namespace boost { namespace python {
arg_to_python(T const& x) \ arg_to_python(T const& x) \
: python::handle<>(expr) {} \ : python::handle<>(expr) {} \
}; \ }; \
} }
// Specialize argument and return value converters for T using expr // Specialize argument and return value converters for T using expr
# define BOOST_PYTHON_TO_PYTHON_BY_VALUE(T, expr, pytype) \ # define BOOST_PYTHON_TO_PYTHON_BY_VALUE(T, expr, pytype) \

View file

@ -127,7 +127,6 @@ query_t::lexer_t::token_t query_t::lexer_t::next_token()
// fall through... // fall through...
default: { default: {
string ident; string ident;
string::const_iterator beg = arg_i;
for (; arg_i != arg_end; ++arg_i) { for (; arg_i != arg_end; ++arg_i) {
switch (*arg_i) { switch (*arg_i) {
case '\0': case '\0':
@ -296,7 +295,7 @@ query_t::parser_t::parse_query_term(query_t::lexer_t::token_t::kind_t tok_contex
if (tok.kind != lexer_t::token_t::TERM) if (tok.kind != lexer_t::token_t::TERM)
throw_(parse_error, throw_(parse_error,
_("Metadata equality operator not followed by term")); _("Metadata equality operator not followed by term"));
expr_t::ptr_op_t arg2 = new expr_t::op_t(expr_t::op_t::VALUE); expr_t::ptr_op_t arg2 = new expr_t::op_t(expr_t::op_t::VALUE);
assert(tok.value); assert(tok.value);
arg2->set_value(mask_t(*tok.value)); arg2->set_value(mask_t(*tok.value));
@ -310,7 +309,7 @@ query_t::parser_t::parse_query_term(query_t::lexer_t::token_t::kind_t tok_contex
} }
break; break;
} }
default: { default: {
node = new expr_t::op_t(expr_t::op_t::O_MATCH); node = new expr_t::op_t(expr_t::op_t::O_MATCH);
@ -536,11 +535,13 @@ query_t::parser_t::parse_query_expr(lexer_t::token_t::kind_t tok_context,
} }
default: default:
break; goto done;
} }
tok = lexer.peek_token(); tok = lexer.peek_token();
} }
done:
;
} }
return limiter; return limiter;

View file

@ -289,7 +289,7 @@ void report_t::parse_query_args(const value_t& args, const string& whence)
normalize_period(); // it needs normalization normalize_period(); // it needs normalization
} }
} }
namespace { namespace {
struct posts_flusher struct posts_flusher
@ -318,7 +318,7 @@ void report_t::posts_report(post_handler_ptr handler)
handler = chain_pre_post_handlers(handler, *this); handler = chain_pre_post_handlers(handler, *this);
journal_posts_iterator walker(*session.journal.get()); journal_posts_iterator walker(*session.journal.get());
pass_down_posts(handler, walker); pass_down_posts<journal_posts_iterator>(handler, walker);
if (! HANDLED(group_by_)) if (! HANDLED(group_by_))
posts_flusher(handler, *this)(value_t()); posts_flusher(handler, *this)(value_t());
@ -334,7 +334,7 @@ void report_t::generate_report(post_handler_ptr handler)
HANDLED(head_) ? HANDLED(head_) ?
static_cast<unsigned int>(HANDLER(head_).value.to_long()) : 50); static_cast<unsigned int>(HANDLER(head_).value.to_long()) : 50);
pass_down_posts(handler, walker); pass_down_posts<generate_posts_iterator>(handler, walker);
} }
void report_t::xact_report(post_handler_ptr handler, xact_t& xact) void report_t::xact_report(post_handler_ptr handler, xact_t& xact)
@ -342,7 +342,7 @@ void report_t::xact_report(post_handler_ptr handler, xact_t& xact)
handler = chain_handlers(handler, *this); handler = chain_handlers(handler, *this);
xact_posts_iterator walker(xact); xact_posts_iterator walker(xact);
pass_down_posts(handler, walker); pass_down_posts<xact_posts_iterator>(handler, walker);
xact.clear_xdata(); xact.clear_xdata();
} }
@ -382,25 +382,34 @@ namespace {
report.HANDLER(display_total_).expr.mark_uncompiled(); report.HANDLER(display_total_).expr.mark_uncompiled();
report.HANDLER(revalued_total_).expr.mark_uncompiled(); report.HANDLER(revalued_total_).expr.mark_uncompiled();
scoped_ptr<accounts_iterator> iter;
if (! report.HANDLED(sort_)) {
iter.reset(new basic_accounts_iterator(*report.session.journal->master));
} else {
expr_t sort_expr(report.HANDLER(sort_).str());
sort_expr.set_context(&report);
iter.reset(new sorted_accounts_iterator(*report.session.journal->master,
sort_expr, report.HANDLED(flat)));
}
if (report.HANDLED(display_)) { if (report.HANDLED(display_)) {
DEBUG("report.predicate", DEBUG("report.predicate",
"Display predicate = " << report.HANDLER(display_).str()); "Display predicate = " << report.HANDLER(display_).str());
pass_down_accounts(handler, *iter.get(), if (! report.HANDLED(sort_)) {
predicate_t(report.HANDLER(display_).str(), basic_accounts_iterator iter(*report.session.journal->master);
report.what_to_keep()), pass_down_accounts<basic_accounts_iterator>
report); (handler, iter, predicate_t(report.HANDLER(display_).str(),
report.what_to_keep()), report);
} else {
expr_t sort_expr(report.HANDLER(sort_).str());
sort_expr.set_context(&report);
sorted_accounts_iterator iter(*report.session.journal->master,
sort_expr, report.HANDLED(flat));
pass_down_accounts<sorted_accounts_iterator>
(handler, iter, predicate_t(report.HANDLER(display_).str(),
report.what_to_keep()), report);
}
} else { } else {
pass_down_accounts(handler, *iter.get()); if (! report.HANDLED(sort_)) {
basic_accounts_iterator iter(*report.session.journal->master);
pass_down_accounts<basic_accounts_iterator>(handler, iter);
} else {
expr_t sort_expr(report.HANDLER(sort_).str());
sort_expr.set_context(&report);
sorted_accounts_iterator iter(*report.session.journal->master,
sort_expr, report.HANDLED(flat));
pass_down_accounts<sorted_accounts_iterator>(handler, iter);
}
} }
report.session.journal->clear_xdata(); report.session.journal->clear_xdata();
@ -428,7 +437,7 @@ void report_t::accounts_report(acct_handler_ptr handler)
// objects created within it during the call to pass_down_posts, which will // objects created within it during the call to pass_down_posts, which will
// be needed later by the pass_down_accounts. // be needed later by the pass_down_accounts.
journal_posts_iterator walker(*session.journal.get()); journal_posts_iterator walker(*session.journal.get());
pass_down_posts(chain, walker); pass_down_posts<journal_posts_iterator>(chain, walker);
if (! HANDLED(group_by_)) if (! HANDLED(group_by_))
accounts_flusher(handler, *this)(value_t()); accounts_flusher(handler, *this)(value_t());
@ -439,7 +448,7 @@ void report_t::commodities_report(post_handler_ptr handler)
handler = chain_handlers(handler, *this); handler = chain_handlers(handler, *this);
posts_commodities_iterator walker(*session.journal.get()); posts_commodities_iterator walker(*session.journal.get());
pass_down_posts(handler, walker); pass_down_posts<posts_commodities_iterator>(handler, walker);
session.journal->clear_xdata(); session.journal->clear_xdata();
} }
@ -648,7 +657,8 @@ value_t report_t::fn_quoted(call_scope_t& args)
std::ostringstream out; std::ostringstream out;
out << '"'; out << '"';
foreach (const char ch, args.get<string>(0)) { string arg(args.get<string>(0));
foreach (const char ch, arg) {
if (ch == '"') if (ch == '"')
out << "\\\""; out << "\\\"";
else else
@ -663,7 +673,8 @@ value_t report_t::fn_join(call_scope_t& args)
{ {
std::ostringstream out; std::ostringstream out;
foreach (const char ch, args.get<string>(0)) { string arg(args.get<string>(0));
foreach (const char ch, arg) {
if (ch != '\n') if (ch != '\n')
out << ch; out << ch;
else else

View file

@ -68,7 +68,7 @@ class xact_t;
// --- The details of #1 and #2 together represent the ItemHandler. // --- The details of #1 and #2 together represent the ItemHandler.
// //
// 3. Mode of the report. Currently there are four modes: // 3. Mode of the report. Currently there are four modes:
// //
// a. Posting or commodity iteration. In this mode, all the journal's // a. Posting or commodity iteration. In this mode, all the journal's
// xacts, the postings of a specific xact, or 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 // commodities are walked. In the first two cases, it's the underlying
@ -86,7 +86,7 @@ class xact_t;
// c. Write journal. In this mode, a single function is called that output // 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 // the journal object as a textual file. #2 is used to print out each
// posting in the journal. // posting in the journal.
// //
// d. Dump binary file. This is just like 'c', except that it dumps out a // d. Dump binary file. This is just like 'c', except that it dumps out a
// binary file and #2 is completely ignored. // binary file and #2 is completely ignored.
// //

View file

@ -646,7 +646,7 @@ class value_scope_t : public child_scope_t
public: public:
value_scope_t(scope_t& _parent, const value_t& _value) value_scope_t(scope_t& _parent, const value_t& _value)
: child_scope_t(_parent), value(_value) {} : child_scope_t(_parent), value(_value) {}
virtual string description() { virtual string description() {
return parent->description(); return parent->description();
} }

135
src/series.h Normal file
View file

@ -0,0 +1,135 @@
/*
* Copyright (c) 2003-2010, 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 series.h
* @author John Wiegley
*
* @ingroup expr
*/
#ifndef _SERIES_H
#define _SERIES_H
#include "scope.h"
namespace ledger {
class expr_series_t
{
protected:
scope_t * context;
public:
optional<std::list<expr_t> > exprs;
expr_t default_expr;
std::string variable;
expr_series_t(const std::string& _variable)
: context(NULL), default_expr(_variable), variable(_variable) {
TRACE_CTOR(expr_series_t, "std::string");
}
expr_series_t(const expr_t& expr, const std::string& _variable)
: context(const_cast<expr_t&>(expr).get_context()),
default_expr(expr), variable(_variable) {
TRACE_CTOR(expr_series_t, "expr_t, std::string");
}
expr_series_t(const expr_series_t& other)
: context(other.context), exprs(other.exprs),
default_expr(other.default_expr), variable(other.variable) {
TRACE_CTOR(expr_series_t, "copy");
}
virtual ~expr_series_t() {
TRACE_DTOR(expr_series_t);
}
scope_t * get_context() {
return context;
}
void set_context(scope_t * scope) {
context = scope;
}
bool empty() const {
return ! exprs || exprs->empty();
}
void push_back(const expr_t& expr) {
if (! exprs)
exprs = std::list<expr_t>();
exprs->push_back(expr);
}
void pop_back() {
assert(exprs);
exprs->pop_back();
}
void mark_uncompiled() {
if (exprs)
foreach (expr_t& expr, *exprs)
expr.mark_uncompiled();
else
default_expr.mark_uncompiled();
}
void compile(scope_t& scope) {
if (exprs)
foreach (expr_t& expr, *exprs)
expr.compile(scope);
else
default_expr.compile(scope);
}
value_t calc(scope_t& scope) {
if (exprs) {
value_t result;
symbol_scope_t sym_scope(scope);
std::size_t len(exprs->size());
foreach (expr_t& expr, *exprs) {
result = expr.calc(sym_scope);
if (--len > 0)
sym_scope.define(symbol_t::FUNCTION, variable,
expr_t::op_t::wrap_value(result));
}
return result;
} else {
return default_expr.calc(scope);
}
}
};
} // namespace ledger
#endif // _SERIES_H

View file

@ -178,7 +178,7 @@ void session_t::close_journal_files()
{ {
journal.reset(); journal.reset();
amount_t::shutdown(); amount_t::shutdown();
journal.reset(new journal_t); journal.reset(new journal_t);
amount_t::initialize(); amount_t::initialize();
} }

View file

@ -158,6 +158,7 @@ typedef std::ostream::pos_type ostream_pos_type;
#include <boost/iostreams/write.hpp> #include <boost/iostreams/write.hpp>
#define BOOST_IOSTREAMS_USE_DEPRECATED 1 #define BOOST_IOSTREAMS_USE_DEPRECATED 1
#include <boost/iostreams/device/file_descriptor.hpp> #include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <boost/iterator/transform_iterator.hpp> #include <boost/iterator/transform_iterator.hpp>
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <boost/operators.hpp> #include <boost/operators.hpp>
@ -204,7 +205,7 @@ namespace serialization {
template <class Archive> template <class Archive>
void serialize(Archive& ar, boost::filesystem::path& p, const unsigned int) void serialize(Archive& ar, boost::filesystem::path& p, const unsigned int)
{ {
std::string s; std::string s;
if (Archive::is_saving::value) if (Archive::is_saving::value)
s = p.string(); s = p.string();

View file

@ -129,7 +129,7 @@ namespace {
(in.peek() == ' ' || in.peek() == '\t')); (in.peek() == ' ' || in.peek() == '\t'));
} }
void read_next_directive(); void read_next_directive();
#if defined(TIMELOG_SUPPORT) #if defined(TIMELOG_SUPPORT)
void clock_in_directive(char * line, bool capitalized); void clock_in_directive(char * line, bool capitalized);
@ -270,7 +270,7 @@ void instance_t::parse()
string err_context = error_context(); string err_context = error_context();
if (! err_context.empty()) if (! err_context.empty())
std::cerr << err_context << std::endl; std::cerr << err_context << std::endl;
if (! current_context.empty()) if (! current_context.empty())
std::cerr << current_context << std::endl; std::cerr << current_context << std::endl;
@ -442,7 +442,7 @@ void instance_t::clock_in_directive(char * line, bool /*capitalized*/)
} }
void instance_t::clock_out_directive(char * line, bool /*capitalized*/) void instance_t::clock_out_directive(char * line, bool /*capitalized*/)
{ {
string datetime(line, 2, 19); string datetime(line, 2, 19);
char * p = skip_ws(line + 22); char * p = skip_ws(line + 22);
@ -546,7 +546,7 @@ void instance_t::automated_xact_directive(char * line)
try { try {
query_t query; query_t query;
keep_details_t keeper(true, true, true); keep_details_t keeper(true, true, true);
expr_t::ptr_op_t expr = expr_t::ptr_op_t expr =
query.parse_args(string_value(skip_ws(line + 1)).to_sequence(), query.parse_args(string_value(skip_ws(line + 1)).to_sequence(),
keeper, false, true); keeper, false, true);
@ -831,7 +831,7 @@ void instance_t::alias_directive(char * line)
void instance_t::fixed_directive(char * line) void instance_t::fixed_directive(char * line)
{ {
if (optional<std::pair<commodity_t *, price_point_t> > price_point = if (optional<std::pair<commodity_t *, price_point_t> > price_point =
commodity_pool_t::current_pool->parse_price_directive(trim_ws(line), commodity_pool_t::current_pool->parse_price_directive(trim_ws(line),
true)) { true)) {
context.state_stack.push_front(fixed_rate_t(price_point->first, context.state_stack.push_front(fixed_rate_t(price_point->first,
@ -1165,11 +1165,7 @@ post_t * instance_t::parse_post(char * line,
// Parse the optional amount // Parse the optional amount
bool saw_amount = false;
if (next && *next && (*next != ';' && *next != '=')) { if (next && *next && (*next != ';' && *next != '=')) {
saw_amount = true;
beg = next - line; beg = next - line;
ptristream stream(next, len - beg); ptristream stream(next, len - beg);
@ -1320,7 +1316,7 @@ post_t * instance_t::parse_post(char * line,
amount_t& amt(*post->assigned_amount); amount_t& amt(*post->assigned_amount);
value_t account_total value_t account_total
(post->account->amount(false).strip_annotations(keep_details_t())); (post->account->amount().strip_annotations(keep_details_t()));
DEBUG("post.assign", DEBUG("post.assign",
"line " << linenum << ": " "account balance = " << account_total); "line " << linenum << ": " "account balance = " << account_total);
@ -1569,6 +1565,7 @@ xact_t * instance_t::parse_xact(char * line,
} }
} }
#if 0
if (xact->_state == item_t::UNCLEARED) { if (xact->_state == item_t::UNCLEARED) {
item_t::state_t result = item_t::CLEARED; item_t::state_t result = item_t::CLEARED;
@ -1582,6 +1579,7 @@ xact_t * instance_t::parse_xact(char * line,
} }
} }
} }
#endif
xact->pos->end_pos = curr_pos; xact->pos->end_pos = curr_pos;
xact->pos->end_line = linenum; xact->pos->end_line = linenum;

View file

@ -280,7 +280,7 @@ optional<date_time::weekdays> string_to_day_of_week(const std::string& str)
else else
return none; return none;
} }
optional<date_time::months_of_year> optional<date_time::months_of_year>
string_to_month_of_year(const std::string& str) string_to_month_of_year(const std::string& str)
{ {
@ -709,12 +709,9 @@ void date_parser_t::determine_when(date_parser_t::lexer_t::token_t& tok,
when += gregorian::years(amount * adjust); when += gregorian::years(amount * adjust);
break; break;
case lexer_t::token_t::TOK_QUARTER: case lexer_t::token_t::TOK_QUARTER:
case lexer_t::token_t::TOK_QUARTERS: { case lexer_t::token_t::TOK_QUARTERS:
date_t temp =
date_duration_t::find_nearest(today, date_duration_t::QUARTERS);
when += gregorian::months(amount * 3 * adjust); when += gregorian::months(amount * 3 * adjust);
break; break;
}
case lexer_t::token_t::TOK_MONTH: case lexer_t::token_t::TOK_MONTH:
case lexer_t::token_t::TOK_MONTHS: case lexer_t::token_t::TOK_MONTHS:
when += gregorian::months(amount * adjust); when += gregorian::months(amount * adjust);

View file

@ -203,7 +203,7 @@ struct date_duration_t
} }
~date_duration_t() throw() { ~date_duration_t() throw() {
TRACE_DTOR(date_duration_t); TRACE_DTOR(date_duration_t);
} }
date_t add(const date_t& date) const { date_t add(const date_t& date) const {
switch (quantum) { switch (quantum) {
@ -431,7 +431,7 @@ public:
out << "from" << range_begin->to_string(); out << "from" << range_begin->to_string();
if (range_end) if (range_end)
out << " to" << range_end->to_string(); out << " to" << range_end->to_string();
return out.str(); return out.str();
} }

View file

@ -333,7 +333,7 @@ value_t& value_t::operator+=(const value_t& val)
for (; i != end(); i++, j++) for (; i != end(); i++, j++)
*i += *j; *i += *j;
} else { } else {
add_error_context(_("While adding %1 to %2:") << *this << val); add_error_context(_("While adding %1 to %2:") << val << *this);
throw_(value_error, _("Cannot add sequences of different lengths")); throw_(value_error, _("Cannot add sequences of different lengths"));
} }
} else { } else {
@ -446,7 +446,7 @@ value_t& value_t::operator+=(const value_t& val)
break; break;
} }
add_error_context(_("While adding %1 to %2:") << *this << val); add_error_context(_("While adding %1 to %2:") << val << *this);
throw_(value_error, _("Cannot add %1 to %2") << val.label() << label()); throw_(value_error, _("Cannot add %1 to %2") << val.label() << label());
return *this; return *this;
@ -465,7 +465,7 @@ value_t& value_t::operator-=(const value_t& val)
for (; i != end(); i++, j++) for (; i != end(); i++, j++)
*i -= *j; *i -= *j;
} else { } else {
add_error_context(_("While subtracting %1 to %2:") << *this << val); add_error_context(_("While subtracting %1 from %2:") << val << *this);
throw_(value_error, _("Cannot subtract sequences of different lengths")); throw_(value_error, _("Cannot subtract sequences of different lengths"));
} }
} else { } else {
@ -588,7 +588,7 @@ value_t& value_t::operator-=(const value_t& val)
break; break;
} }
add_error_context(_("While subtracting %1 from %2:") << *this << val); add_error_context(_("While subtracting %1 from %2:") << val << *this);
throw_(value_error, _("Cannot subtract %1 from %2") << val.label() << label()); throw_(value_error, _("Cannot subtract %1 from %2") << val.label() << label());
return *this; return *this;
@ -670,7 +670,7 @@ value_t& value_t::operator*=(const value_t& val)
break; break;
} }
add_error_context(_("While multiplying %1 with %2:") << *this << val); add_error_context(_("While multiplying %1 with %2:") << val << *this);
throw_(value_error, _("Cannot multiply %1 with %2") << label() << val.label()); throw_(value_error, _("Cannot multiply %1 with %2") << label() << val.label());
return *this; return *this;
@ -748,7 +748,7 @@ value_t& value_t::operator/=(const value_t& val)
break; break;
} }
add_error_context(_("While dividing %1 by %2:") << *this << val); add_error_context(_("While dividing %1 by %2:") << val << *this);
throw_(value_error, _("Cannot divide %1 by %2") << label() << val.label()); throw_(value_error, _("Cannot divide %1 by %2") << label() << val.label());
return *this; return *this;
@ -760,7 +760,7 @@ bool value_t::is_equal_to(const value_t& val) const
switch (type()) { switch (type()) {
case VOID: case VOID:
return val.type() == VOID; return val.type() == VOID;
case BOOLEAN: case BOOLEAN:
if (val.is_boolean()) if (val.is_boolean())
return as_boolean() == val.as_boolean(); return as_boolean() == val.as_boolean();
@ -834,7 +834,7 @@ bool value_t::is_equal_to(const value_t& val) const
break; break;
} }
add_error_context(_("While comparing equality of %1 to %2:") << *this << val); add_error_context(_("While comparing equality of %1 and %2:") << *this << val);
throw_(value_error, _("Cannot compare %1 to %2") << label() << val.label()); throw_(value_error, _("Cannot compare %1 to %2") << label() << val.label());
return *this; return *this;
@ -1263,8 +1263,8 @@ void value_t::in_place_cast(type_t cast_type)
} }
add_error_context(_("While converting %1:") << *this); add_error_context(_("While converting %1:") << *this);
throw_(value_error, throw_(value_error, _("Cannot convert %1 to %2")
_("Cannot convert %1 to %2") << label() << label(cast_type)); << label() << label(cast_type));
} }
void value_t::in_place_negate() void value_t::in_place_negate()
@ -1721,11 +1721,13 @@ string value_t::label(optional<type_t> the_type) const
return _("<invalid>"); return _("<invalid>");
} }
void value_t::print(std::ostream& out, void value_t::print(std::ostream& _out,
const int first_width, const int first_width,
const int latter_width, const int latter_width,
const uint_least8_t flags) const const uint_least8_t flags) const
{ {
std::ostringstream out;
if (first_width > 0 && if (first_width > 0 &&
(! is_amount() || as_amount().is_zero()) && (! is_amount() || as_amount().is_zero()) &&
! is_balance() && ! is_string()) { ! is_balance() && ! is_string()) {
@ -1821,6 +1823,8 @@ void value_t::print(std::ostream& out,
add_error_context(_("While printing %1:") << *this); add_error_context(_("While printing %1:") << *this);
throw_(value_error, _("Cannot print %1") << label()); throw_(value_error, _("Cannot print %1") << label());
} }
_out << out.str();
} }
void value_t::dump(std::ostream& out, const bool relaxed) const void value_t::dump(std::ostream& out, const bool relaxed) const

View file

@ -139,7 +139,7 @@ private:
scope_t *, // SCOPE scope_t *, // SCOPE
boost::any // ANY boost::any // ANY
> data; > data;
type_t type; type_t type;
/** /**

View file

@ -192,7 +192,7 @@ bool xact_base_t::finalize()
DEBUG("xact.finalize", "there were no costs, and a valid top_post"); DEBUG("xact.finalize", "there were no costs, and a valid top_post");
balance_t::amounts_map::const_iterator a = bal.amounts.begin(); balance_t::amounts_map::const_iterator a = bal.amounts.begin();
const amount_t * x = &(*a++).second; const amount_t * x = &(*a++).second;
const amount_t * y = &(*a++).second; const amount_t * y = &(*a++).second;
@ -418,7 +418,7 @@ bool xact_base_t::verify()
amount_t& p(post->cost ? *post->cost : post->amount); amount_t& p(post->cost ? *post->cost : post->amount);
assert(! p.is_null()); assert(! p.is_null());
// If the amount was a cost, it very likely has the "keep_precision" flag // If the amount was a cost, it very likely has the "keep_precision" flag
// set, meaning commodity display precision is ignored when displaying the // set, meaning commodity display precision is ignored when displaying the
// amount. We never want this set for the balance, so we must clear the // amount. We never want this set for the balance, so we must clear the
@ -609,7 +609,7 @@ namespace {
.match(post.reported_account()->fullname()); .match(post.reported_account()->fullname());
else else
break; break;
case expr_t::op_t::O_NOT: case expr_t::op_t::O_NOT:
return ! post_pred(op->left(), post); return ! post_pred(op->left(), post);

View file

@ -61,7 +61,7 @@ public:
xact_base_t() : item_t(), journal(NULL) { xact_base_t() : item_t(), journal(NULL) {
TRACE_CTOR(xact_base_t, ""); TRACE_CTOR(xact_base_t, "");
} }
xact_base_t(const xact_base_t& e); xact_base_t(const xact_base_t& e);
virtual ~xact_base_t(); virtual ~xact_base_t();

View file

@ -119,6 +119,7 @@ pkginclude_HEADERS = \
src/query.h \ src/query.h \
src/format.h \ src/format.h \
src/option.h \ src/option.h \
src/series.h \
\ \
src/item.h \ src/item.h \
src/post.h \ src/post.h \

View file

@ -66,7 +66,7 @@ AC_ARG_ENABLE(doxygen,
AM_CONDITIONAL(USE_DOXYGEN, test x$doxygen = xtrue) AM_CONDITIONAL(USE_DOXYGEN, test x$doxygen = xtrue)
AC_ARG_ENABLE(cache, AC_ARG_ENABLE(cache,
[ --enable-cache Enable use of the --cache option], [ --enable-cache Enable use of the --cache option],
[case "${enableval}" in [case "${enableval}" in
yes) cache=true ;; yes) cache=true ;;
no) cache=false ;; no) cache=false ;;
@ -76,7 +76,7 @@ AC_ARG_ENABLE(cache,
AM_CONDITIONAL(USE_CACHE_OPTION, test x$cache = xtrue) AM_CONDITIONAL(USE_CACHE_OPTION, test x$cache = xtrue)
AC_ARG_ENABLE(python, AC_ARG_ENABLE(python,
[ --enable-python Turn on Python support (experimental)], [ --enable-python Turn on Python support (experimental)],
[case "${enableval}" in [case "${enableval}" in
yes) python=true ;; yes) python=true ;;
no) python=false ;; no) python=false ;;