*** empty log message ***
This commit is contained in:
parent
30f79b0761
commit
2964dd15b2
9 changed files with 174 additions and 48 deletions
23
NEWS
23
NEWS
|
|
@ -21,10 +21,22 @@
|
||||||
C 1.00 Gb = 1024 Mb
|
C 1.00 Gb = 1024 Mb
|
||||||
C 1.00 Tb = 1024 Gb
|
C 1.00 Tb = 1024 Gb
|
||||||
|
|
||||||
- Added --ansi reporting option, which shows negative values as red
|
- Added --ansi reporting option, which shows negative values in the
|
||||||
using ANSI terminal codes; --ansi-invert makes non-negative values
|
running total column of the register report as red, using ANSI
|
||||||
red (which makes more sense for income and budget reports, for
|
terminal codes; --ansi-invert makes non-negative values red (which
|
||||||
example).
|
makes more sense for the income and budget reports).
|
||||||
|
|
||||||
|
The --ansi functionality is triggered by the format modifier "!",
|
||||||
|
for example the register reports uses the following for the total
|
||||||
|
(last) column:
|
||||||
|
|
||||||
|
%!12.80T
|
||||||
|
|
||||||
|
At the moment neither the balance report nor any of the other
|
||||||
|
reports make use of the ! modifier, and so will not change color
|
||||||
|
even if --ansi is used. However, you can modify these report format
|
||||||
|
strings yourself in ~/.ledgerrc if you wish to see red coloring of
|
||||||
|
negative sums in other places.
|
||||||
|
|
||||||
- Added --only predicate, which occurs during transaction processing
|
- Added --only predicate, which occurs during transaction processing
|
||||||
between --limit and --display. Here is a summary of how the three
|
between --limit and --display. Here is a summary of how the three
|
||||||
|
|
@ -183,6 +195,9 @@
|
||||||
|
|
||||||
- Added a new "csv" command, for outputting results in CSV format.
|
- Added a new "csv" command, for outputting results in CSV format.
|
||||||
|
|
||||||
|
- Ledger now expands ~ in file pathnames specified in environment
|
||||||
|
variables, initialization files and journal files.
|
||||||
|
|
||||||
- Effective dates may now be specified for entries:
|
- Effective dates may now be specified for entries:
|
||||||
|
|
||||||
2004/10/03=2004/09/30 Credit card company
|
2004/10/03=2004/09/30 Credit card company
|
||||||
|
|
|
||||||
109
config.cc
109
config.cc
|
|
@ -15,6 +15,14 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_REALPATH
|
||||||
|
extern "C" char *realpath(const char *, char resolved_path[]);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAVE_GETPWUID) || defined(HAVE_GETPWNAM)
|
||||||
|
#include <pwd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace ledger {
|
namespace ledger {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
@ -50,6 +58,71 @@ namespace {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string expand_path(const std::string& path)
|
||||||
|
{
|
||||||
|
if (path.length() == 0 || path[0] != '~')
|
||||||
|
return path;
|
||||||
|
|
||||||
|
const char * pfx = NULL;
|
||||||
|
std::string::size_type pos = path.find_first_of('/');
|
||||||
|
|
||||||
|
if (path.length() == 1 || pos == 1) {
|
||||||
|
pfx = std::getenv("HOME");
|
||||||
|
#ifdef HAVE_GETPWUID
|
||||||
|
if (! pfx) {
|
||||||
|
// Punt. We're trying to expand ~/, but HOME isn't set
|
||||||
|
struct passwd * pw = getpwuid(getuid());
|
||||||
|
if (pw)
|
||||||
|
pfx = pw->pw_dir;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#ifdef HAVE_GETPWNAM
|
||||||
|
else {
|
||||||
|
std::string user(path, 1, pos == std::string::npos ?
|
||||||
|
std::string::npos : pos - 1);
|
||||||
|
struct passwd * pw = getpwnam(user.c_str());
|
||||||
|
if (pw)
|
||||||
|
pfx = pw->pw_dir;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// if we failed to find an expansion, return the path unchanged.
|
||||||
|
|
||||||
|
if (! pfx)
|
||||||
|
return path;
|
||||||
|
|
||||||
|
std::string result(pfx);
|
||||||
|
|
||||||
|
if (pos == std::string::npos)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
if (result.length() == 0 || result[result.length() - 1] != '/')
|
||||||
|
result += '/';
|
||||||
|
|
||||||
|
result += path.substr(pos + 1);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string resolve_path(const std::string& path)
|
||||||
|
{
|
||||||
|
std::string resolved;;
|
||||||
|
if (path[0] == '~')
|
||||||
|
resolved = expand_path(path);
|
||||||
|
else
|
||||||
|
resolved = path;
|
||||||
|
|
||||||
|
#ifdef HAVE_REALPATH
|
||||||
|
char buf[PATH_MAX];
|
||||||
|
::realpath(resolved.c_str(), buf);
|
||||||
|
return std::string(buf);
|
||||||
|
#else
|
||||||
|
return resolved;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void config_t::reset()
|
void config_t::reset()
|
||||||
{
|
{
|
||||||
ledger::amount_expr.reset(new value_expr("a"));
|
ledger::amount_expr.reset(new value_expr("a"));
|
||||||
|
|
@ -58,10 +131,10 @@ void config_t::reset()
|
||||||
pricing_leeway = 24 * 3600;
|
pricing_leeway = 24 * 3600;
|
||||||
budget_flags = BUDGET_NO_BUDGET;
|
budget_flags = BUDGET_NO_BUDGET;
|
||||||
balance_format = "%20T %2_%-a\n";
|
balance_format = "%20T %2_%-a\n";
|
||||||
register_format = ("%D %-.20P %-.22A %12.67t %12.80T\n%/"
|
register_format = ("%D %-.20P %-.22A %12.67t %!12.80T\n%/"
|
||||||
"%32|%-.22A %12.67t %12.80T\n");
|
"%32|%-.22A %12.67t %!12.80T\n");
|
||||||
wide_register_format = ("%D %-.35P %-.38A %22.108t %22.132T\n%/"
|
wide_register_format = ("%D %-.35P %-.38A %22.108t %!22.132T\n%/"
|
||||||
"%48|%-.38A %22.108t %22.132T\n");
|
"%48|%-.38A %22.108t %!22.132T\n");
|
||||||
csv_register_format = "\"%D\",\"%P\",\"%A\",\"%t\",\"%T\"\n";
|
csv_register_format = "\"%D\",\"%P\",\"%A\",\"%t\",\"%T\"\n";
|
||||||
plot_amount_format = "%D %(S(t))\n";
|
plot_amount_format = "%D %(S(t))\n";
|
||||||
plot_total_format = "%D %(S(T))\n";
|
plot_total_format = "%D %(S(T))\n";
|
||||||
|
|
@ -727,19 +800,29 @@ OPT_BEGIN(version, "v") {
|
||||||
} OPT_END(version);
|
} OPT_END(version);
|
||||||
|
|
||||||
OPT_BEGIN(init_file, "i:") {
|
OPT_BEGIN(init_file, "i:") {
|
||||||
config->init_file = optarg;
|
std::string path = resolve_path(optarg);
|
||||||
|
if (access(path.c_str(), R_OK) != -1)
|
||||||
|
config->init_file = path;
|
||||||
|
else
|
||||||
|
throw new error(std::string("The init file '") + path +
|
||||||
|
"' does not exist or is not readable");
|
||||||
} OPT_END(init_file);
|
} OPT_END(init_file);
|
||||||
|
|
||||||
OPT_BEGIN(file, "f:") {
|
OPT_BEGIN(file, "f:") {
|
||||||
if (std::string(optarg) == "-" || access(optarg, R_OK) != -1)
|
if (std::string(optarg) == "-") {
|
||||||
config->data_file = optarg;
|
config->data_file = optarg;
|
||||||
|
} else {
|
||||||
|
std::string path = resolve_path(optarg);
|
||||||
|
if (access(path.c_str(), R_OK) != -1)
|
||||||
|
config->data_file = path;
|
||||||
else
|
else
|
||||||
throw new error(std::string("The ledger file '") + optarg +
|
throw new error(std::string("The ledger file '") + path +
|
||||||
"' does not exist or is not readable");
|
"' does not exist or is not readable");
|
||||||
|
}
|
||||||
} OPT_END(file);
|
} OPT_END(file);
|
||||||
|
|
||||||
OPT_BEGIN(cache, ":") {
|
OPT_BEGIN(cache, ":") {
|
||||||
config->cache_file = optarg;
|
config->cache_file = resolve_path(optarg);
|
||||||
} OPT_END(cache);
|
} OPT_END(cache);
|
||||||
|
|
||||||
OPT_BEGIN(no_cache, "") {
|
OPT_BEGIN(no_cache, "") {
|
||||||
|
|
@ -747,8 +830,14 @@ OPT_BEGIN(no_cache, "") {
|
||||||
} OPT_END(no_cache);
|
} OPT_END(no_cache);
|
||||||
|
|
||||||
OPT_BEGIN(output, "o:") {
|
OPT_BEGIN(output, "o:") {
|
||||||
if (std::string(optarg) != "-")
|
if (std::string(optarg) != "-") {
|
||||||
config->output_file = optarg;
|
std::string path = resolve_path(optarg);
|
||||||
|
if (access(path.c_str(), W_OK) != -1)
|
||||||
|
config->output_file = path;
|
||||||
|
else
|
||||||
|
throw new error(std::string("The output file '") + path +
|
||||||
|
"' is not writable");
|
||||||
|
}
|
||||||
} OPT_END(output);
|
} OPT_END(output);
|
||||||
|
|
||||||
OPT_BEGIN(account, "a:") {
|
OPT_BEGIN(account, "a:") {
|
||||||
|
|
|
||||||
2
config.h
2
config.h
|
|
@ -117,6 +117,8 @@ void option_help(std::ostream& out);
|
||||||
|
|
||||||
#define OPT_END(tag)
|
#define OPT_END(tag)
|
||||||
|
|
||||||
|
std::string resolve_path(const std::string& path);
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void trace(const std::string& cat, const std::string& str);
|
void trace(const std::string& cat, const std::string& str);
|
||||||
|
|
|
||||||
|
|
@ -274,7 +274,7 @@ AC_STRUCT_TM
|
||||||
# Checks for library functions.
|
# Checks for library functions.
|
||||||
#AC_FUNC_ERROR_AT_LINE
|
#AC_FUNC_ERROR_AT_LINE
|
||||||
AC_HEADER_STDC
|
AC_HEADER_STDC
|
||||||
AC_CHECK_FUNCS([access mktime realpath stat strftime strptime])
|
AC_CHECK_FUNCS([access mktime realpath stat strftime strptime getpwuid getpwnam])
|
||||||
|
|
||||||
AC_CONFIG_FILES([Makefile])
|
AC_CONFIG_FILES([Makefile])
|
||||||
AC_OUTPUT
|
AC_OUTPUT
|
||||||
|
|
|
||||||
23
format.cc
23
format.cc
|
|
@ -118,8 +118,15 @@ element_t * format_t::parse_elements(const std::string& fmt)
|
||||||
}
|
}
|
||||||
|
|
||||||
++p;
|
++p;
|
||||||
if (*p == '-') {
|
while (*p == '!' || *p == '-') {
|
||||||
current->align_left = true;
|
switch (*p) {
|
||||||
|
case '-':
|
||||||
|
current->flags |= ELEMENT_ALIGN_LEFT;
|
||||||
|
break;
|
||||||
|
case '!':
|
||||||
|
current->flags |= ELEMENT_HIGHLIGHT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -273,7 +280,7 @@ namespace {
|
||||||
out.width(0);
|
out.width(0);
|
||||||
out << "\e[31m";
|
out << "\e[31m";
|
||||||
|
|
||||||
if (elem->align_left)
|
if (elem->flags & ELEMENT_ALIGN_LEFT)
|
||||||
out << std::left;
|
out << std::left;
|
||||||
else
|
else
|
||||||
out << std::right;
|
out << std::right;
|
||||||
|
|
@ -294,7 +301,7 @@ void format_t::format(std::ostream& out_str, const details_t& details) const
|
||||||
std::string name;
|
std::string name;
|
||||||
bool ignore_max_width = false;
|
bool ignore_max_width = false;
|
||||||
|
|
||||||
if (elem->align_left)
|
if (elem->flags & ELEMENT_ALIGN_LEFT)
|
||||||
out << std::left;
|
out << std::left;
|
||||||
else
|
else
|
||||||
out << std::right;
|
out << std::right;
|
||||||
|
|
@ -347,7 +354,7 @@ void format_t::format(std::ostream& out_str, const details_t& details) const
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case value_t::INTEGER:
|
case value_t::INTEGER:
|
||||||
if (ansi_codes) {
|
if (ansi_codes && elem->flags & ELEMENT_HIGHLIGHT) {
|
||||||
if (ansi_invert) {
|
if (ansi_invert) {
|
||||||
if (*((long *) value.data) > 0)
|
if (*((long *) value.data) > 0)
|
||||||
mark_red(out, elem);
|
mark_red(out, elem);
|
||||||
|
|
@ -364,7 +371,7 @@ void format_t::format(std::ostream& out_str, const details_t& details) const
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case value_t::AMOUNT:
|
case value_t::AMOUNT:
|
||||||
if (ansi_codes) {
|
if (ansi_codes && elem->flags & ELEMENT_HIGHLIGHT) {
|
||||||
if (ansi_invert) {
|
if (ansi_invert) {
|
||||||
if (*((amount_t *) value.data) > 0)
|
if (*((amount_t *) value.data) > 0)
|
||||||
mark_red(out, elem);
|
mark_red(out, elem);
|
||||||
|
|
@ -384,7 +391,7 @@ void format_t::format(std::ostream& out_str, const details_t& details) const
|
||||||
if (! bal)
|
if (! bal)
|
||||||
bal = &((balance_pair_t *) value.data)->quantity;
|
bal = &((balance_pair_t *) value.data)->quantity;
|
||||||
|
|
||||||
if (ansi_codes) {
|
if (ansi_codes && elem->flags & ELEMENT_HIGHLIGHT) {
|
||||||
if (ansi_invert) {
|
if (ansi_invert) {
|
||||||
if (*bal > 0)
|
if (*bal > 0)
|
||||||
mark_red(out, elem);
|
mark_red(out, elem);
|
||||||
|
|
@ -404,7 +411,7 @@ void format_t::format(std::ostream& out_str, const details_t& details) const
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ansi_codes)
|
if (ansi_codes && elem->flags & ELEMENT_HIGHLIGHT)
|
||||||
mark_plain(out);
|
mark_plain(out);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
15
format.h
15
format.h
|
|
@ -13,6 +13,9 @@ std::string truncated(const std::string& str, unsigned int width,
|
||||||
std::string partial_account_name(const account_t& account,
|
std::string partial_account_name(const account_t& account,
|
||||||
const unsigned int start_depth);
|
const unsigned int start_depth);
|
||||||
|
|
||||||
|
#define ELEMENT_ALIGN_LEFT 0x01
|
||||||
|
#define ELEMENT_HIGHLIGHT 0x02
|
||||||
|
|
||||||
struct element_t
|
struct element_t
|
||||||
{
|
{
|
||||||
enum kind_t {
|
enum kind_t {
|
||||||
|
|
@ -45,18 +48,18 @@ struct element_t
|
||||||
DEPTH_SPACER
|
DEPTH_SPACER
|
||||||
};
|
};
|
||||||
|
|
||||||
bool align_left;
|
|
||||||
unsigned int min_width;
|
|
||||||
unsigned int max_width;
|
|
||||||
|
|
||||||
kind_t type;
|
kind_t type;
|
||||||
|
unsigned char flags;
|
||||||
std::string chars;
|
std::string chars;
|
||||||
|
unsigned char min_width;
|
||||||
|
unsigned char max_width;
|
||||||
value_expr * val_expr;
|
value_expr * val_expr;
|
||||||
|
|
||||||
struct element_t * next;
|
struct element_t * next;
|
||||||
|
|
||||||
element_t() : align_left(false), min_width(0), max_width(0),
|
element_t() : type(STRING), flags(false),
|
||||||
type(STRING), val_expr(NULL), next(NULL) {
|
min_width(0), max_width(0),
|
||||||
|
val_expr(NULL), next(NULL) {
|
||||||
DEBUG_PRINT("ledger.memory.ctors", "ctor element_t");
|
DEBUG_PRINT("ledger.memory.ctors", "ctor element_t");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
11
textual.cc
11
textual.cc
|
|
@ -21,7 +21,7 @@
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
#if defined(__GNUG__) && __GNUG__ < 3
|
#ifdef HAVE_REALPATH
|
||||||
extern "C" char *realpath(const char *, char resolved_path[]);
|
extern "C" char *realpath(const char *, char resolved_path[]);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -737,13 +737,15 @@ unsigned int textual_parser_t::parse(std::istream& in,
|
||||||
push_var<unsigned int> save_linenum(linenum);
|
push_var<unsigned int> save_linenum(linenum);
|
||||||
|
|
||||||
path = p;
|
path = p;
|
||||||
if (path[0] != '/' && path[0] != '\\') {
|
if (path[0] != '/' && path[0] != '\\' && path[0] != '~') {
|
||||||
std::string::size_type pos = save_path.prev.rfind('/');
|
std::string::size_type pos = save_path.prev.rfind('/');
|
||||||
if (pos == std::string::npos)
|
if (pos == std::string::npos)
|
||||||
pos = save_path.prev.rfind('\\');
|
pos = save_path.prev.rfind('\\');
|
||||||
if (pos != std::string::npos)
|
if (pos != std::string::npos)
|
||||||
path = std::string(save_path.prev, 0, pos + 1) + path;
|
path = std::string(save_path.prev, 0, pos + 1) + path;
|
||||||
}
|
}
|
||||||
|
path = resolve_path(path);
|
||||||
|
|
||||||
DEBUG_PRINT("ledger.textual.include", "line " << linenum << ": " <<
|
DEBUG_PRINT("ledger.textual.include", "line " << linenum << ": " <<
|
||||||
"Including path '" << path << "'");
|
"Including path '" << path << "'");
|
||||||
|
|
||||||
|
|
@ -783,7 +785,7 @@ unsigned int textual_parser_t::parse(std::istream& in,
|
||||||
else if (word == "def") {
|
else if (word == "def") {
|
||||||
if (! global_scope.get())
|
if (! global_scope.get())
|
||||||
init_value_expr();
|
init_value_expr();
|
||||||
value_auto_ptr expr(parse_boolean_expr(p, global_scope.get()));
|
parse_value_definition(p);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -856,10 +858,11 @@ void write_textual_journal(journal_t& journal, std::string path,
|
||||||
{
|
{
|
||||||
unsigned long index = 0;
|
unsigned long index = 0;
|
||||||
std::string found;
|
std::string found;
|
||||||
|
|
||||||
|
#ifdef HAVE_REALPATH
|
||||||
char buf1[PATH_MAX];
|
char buf1[PATH_MAX];
|
||||||
char buf2[PATH_MAX];
|
char buf2[PATH_MAX];
|
||||||
|
|
||||||
#ifdef HAVE_REALPATH
|
|
||||||
::realpath(path.c_str(), buf1);
|
::realpath(path.c_str(), buf1);
|
||||||
for (strings_list::iterator i = journal.sources.begin();
|
for (strings_list::iterator i = journal.sources.begin();
|
||||||
i != journal.sources.end();
|
i != journal.sources.end();
|
||||||
|
|
|
||||||
19
valexpr.cc
19
valexpr.cc
|
|
@ -1375,10 +1375,11 @@ void init_value_expr()
|
||||||
node->left->constant_i = 2;
|
node->left->constant_i = 2;
|
||||||
node->set_right(new value_expr_t(value_expr_t::F_VALUE));
|
node->set_right(new value_expr_t(value_expr_t::F_VALUE));
|
||||||
globals->define("P", node);
|
globals->define("P", node);
|
||||||
value_auto_ptr val(parse_boolean_expr("value=P(t,m)", globals));
|
|
||||||
value_auto_ptr tval(parse_boolean_expr("total_value=P(T,m)", globals));
|
parse_value_definition("value=P(t,m)", globals);
|
||||||
value_auto_ptr valof(parse_boolean_expr("valueof(x)=P(x,m)", globals));
|
parse_value_definition("total_value=P(T,m)", globals);
|
||||||
value_auto_ptr dvalof(parse_boolean_expr("datedvalueof(x,y)=P(x,y)", globals));
|
parse_value_definition("valueof(x)=P(x,m)", globals);
|
||||||
|
parse_value_definition("datedvalueof(x,y)=P(x,y)", globals);
|
||||||
|
|
||||||
node = new value_expr_t(value_expr_t::O_DEF);
|
node = new value_expr_t(value_expr_t::O_DEF);
|
||||||
node->set_left(new value_expr_t(value_expr_t::CONSTANT_I));
|
node->set_left(new value_expr_t(value_expr_t::CONSTANT_I));
|
||||||
|
|
@ -1416,9 +1417,9 @@ void init_value_expr()
|
||||||
node->set_right(new value_expr_t(value_expr_t::F_DAY));
|
node->set_right(new value_expr_t(value_expr_t::F_DAY));
|
||||||
globals->define("dayof", node);
|
globals->define("dayof", node);
|
||||||
|
|
||||||
value_auto_ptr year(parse_boolean_expr("year=yearof(d)", globals));
|
parse_value_definition("year=yearof(d)", globals);
|
||||||
value_auto_ptr month(parse_boolean_expr("month=monthof(d)", globals));
|
parse_value_definition("month=monthof(d)", globals);
|
||||||
value_auto_ptr day(parse_boolean_expr("day=dayof(d)", globals));
|
parse_value_definition("day=dayof(d)", globals);
|
||||||
|
|
||||||
// Macros
|
// Macros
|
||||||
node = parse_value_expr("P(a,d)");
|
node = parse_value_expr("P(a,d)");
|
||||||
|
|
@ -1437,8 +1438,8 @@ void init_value_expr()
|
||||||
globals->define("G", node);
|
globals->define("G", node);
|
||||||
globals->define("total_gain", node);
|
globals->define("total_gain", node);
|
||||||
|
|
||||||
value_auto_ptr minx(parse_boolean_expr("min(x,y)=x<y?x:y", globals));
|
parse_value_definition("min(x,y)=x<y?x:y", globals);
|
||||||
value_auto_ptr maxx(parse_boolean_expr("max(x,y)=x>y?x:y", globals));
|
parse_value_definition("max(x,y)=x>y?x:y", globals);
|
||||||
}
|
}
|
||||||
|
|
||||||
value_expr_t * parse_value_expr(std::istream& in, scope_t * scope,
|
value_expr_t * parse_value_expr(std::istream& in, scope_t * scope,
|
||||||
|
|
|
||||||
|
|
@ -460,6 +460,12 @@ inline value_t compute_total(const details_t& details = details_t()) {
|
||||||
return total_expr->compute(details);
|
return total_expr->compute(details);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void parse_value_definition(const std::string& str,
|
||||||
|
scope_t * scope = NULL) {
|
||||||
|
value_auto_ptr expr
|
||||||
|
(parse_boolean_expr(str, scope ? scope : global_scope.get()));
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue