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

12
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,
@ -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

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

@ -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

@ -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

@ -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;
} }
@ -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

@ -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

@ -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())
@ -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_))
@ -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

@ -76,7 +76,7 @@ public:
: 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);
@ -365,6 +380,7 @@ 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();
@ -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

@ -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;
@ -105,7 +107,7 @@ public:
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

@ -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

@ -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,7 +84,8 @@ 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)

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)

View file

@ -209,6 +209,8 @@ 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)

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

@ -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':
@ -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

@ -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

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

@ -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>

View file

@ -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

@ -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

@ -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;
@ -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

@ -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 ;;