diff options
-rw-r--r-- | Makefile | 6 | ||||
-rw-r--r-- | amount.cc | 38 | ||||
-rw-r--r-- | config.cc | 2 | ||||
-rw-r--r-- | format.cc | 59 | ||||
-rw-r--r-- | option.cc | 21 | ||||
-rw-r--r-- | textual.cc | 5 | ||||
-rw-r--r-- | valexpr.cc | 71 | ||||
-rw-r--r-- | valexpr.h | 2 |
8 files changed, 86 insertions, 118 deletions
@@ -42,12 +42,6 @@ all: make.deps ledger docs: ledger.info ledger.pdf -install: - make clean - make DFLAGS="-O3 -fomit-frame-pointer" - cp ledger $(HOME)/bin - strip $(HOME)/bin/ledger - libledger.a: $(OBJS) ar rv $@ $? ranlib $@ @@ -1,6 +1,5 @@ -#include "amount.h" - -#include <list> +#include "ledger.h" +#include "util.h" #include "gmp.h" @@ -585,43 +584,30 @@ static inline char peek_next_nonws(std::istream& in) void parse_quantity(std::istream& in, std::string& value) { + static char buf[256]; char c = peek_next_nonws(in); - while (std::isdigit(c) || c == '-' || c == '.' || c == ',') { - in.get(c); - if (in.eof()) - break; - value += c; - c = in.peek(); - } + READ_INTO(in, buf, 256, c, + std::isdigit(c) || c == '-' || c == '.' || c == ','); + value = buf; } void parse_commodity(std::istream& in, std::string& symbol) { + static char buf[256]; + char c = peek_next_nonws(in); if (c == '"') { in.get(c); - c = in.peek(); - while (! in.eof() && c != '"') { - in.get(c); - if (c == '\\') - in.get(c); - symbol += c; - c = in.peek(); - } - + READ_INTO(in, buf, 256, c, c != '"'); if (c == '"') in.get(c); else assert(0); } else { - while (! std::isspace(c) && ! std::isdigit(c) && c != '-' && c != '.') { - in.get(c); - if (in.eof()) - break; - symbol += c; - c = in.peek(); - } + READ_INTO(in, buf, 256, c, ! std::isspace(c) && ! std::isdigit(c) && + c != '-' && c != '.'); } + symbol = buf; } void amount_t::parse(std::istream& in) @@ -20,8 +20,6 @@ config_t::config_t() { if (const char * p = std::getenv("HOME")) init_file = cache_file = price_db = p; - else - init_file = cache_file = price_db = ""; init_file += "/.ledgerrc"; cache_file += "/.ledger"; @@ -47,7 +47,9 @@ element_t * format_t::parse_elements(const std::string& fmt) { element_t * result = NULL; element_t * current = NULL; - std::string str; + + static char buf[1024]; + char * q = buf; for (const char * p = fmt.c_str(); *p; p++) { if (*p == '%') { @@ -58,10 +60,10 @@ element_t * format_t::parse_elements(const std::string& fmt) current = current->next; } - if (! str.empty()) { + if (q != buf) { current->type = element_t::STRING; - current->chars = str; - str = ""; + current->chars = std::string(buf, q); + q = buf; current->next = new element_t; current = current->next; @@ -73,22 +75,23 @@ element_t * format_t::parse_elements(const std::string& fmt) ++p; } - std::string num; - while (*p && std::isdigit(*p)) - num += *p++; - if (! num.empty()) - current->min_width = std::atol(num.c_str()); + int num = 0; + while (*p && std::isdigit(*p)) { + num *= 10; + num += *p++ - '0'; + } + current->min_width = num; if (*p == '.') { ++p; - num = ""; - while (*p && std::isdigit(*p)) - num += *p++; - if (! num.empty()) { - current->max_width = std::atol(num.c_str()); - if (current->min_width == 0) - current->min_width = current->max_width; + num = 0; + while (*p && std::isdigit(*p)) { + num *= 10; + num += *p++ - '0'; } + current->max_width = num; + if (current->min_width == 0) + current->min_width = current->max_width; } switch (*p) { @@ -97,29 +100,31 @@ element_t * format_t::parse_elements(const std::string& fmt) current->chars = "%"; break; - case '(': + case '(': { ++p; - num = ""; + const char * b = p; while (*p && *p != ')') - num += *p++; + p++; if (*p != ')') throw format_error("Missing ')'"); current->type = element_t::VALUE_EXPR; - current->val_expr = parse_value_expr(num); + current->val_expr = parse_value_expr(std::string(b, p)); break; + } - case '[': + case '[': { ++p; - num = ""; + const char * b = p; while (*p && *p != ']') - num += *p++; + p++; if (*p != ']') throw format_error("Missing ']'"); current->type = element_t::DATE_STRING; - current->chars = num; + current->chars = std::string(b, p); break; + } case 'D': current->type = element_t::DATE_STRING; @@ -137,11 +142,11 @@ element_t * format_t::parse_elements(const std::string& fmt) case '_': current->type = element_t::SPACER; break; } } else { - str += *p; + *q++ = *p; } } - if (! str.empty()) { + if (q != buf) { if (! result) { current = result = new element_t; } else { @@ -149,7 +154,7 @@ element_t * format_t::parse_elements(const std::string& fmt) current = current->next; } current->type = element_t::STRING; - current->chars = str; + current->chars = std::string(buf, q); } return result; @@ -1,4 +1,5 @@ #include "option.h" +#include "util.h" #include <iostream> #include <cstdarg> @@ -9,11 +10,16 @@ option_handler::option_handler(const std::string& label, { option_t opt; + static char buf[128]; + char * p = buf; for (const char * q = label.c_str(); *q; q++) if (*q == '_') - opt.long_opt += '-'; + *p++ = '-'; else - opt.long_opt += *q; + *p++ = *q; + assert(p < buf + 127); + *p = '\0'; + opt.long_opt = buf; handlers.insert(option_handler_pair(opt.long_opt, this)); @@ -130,15 +136,18 @@ void process_environment(char ** envp, const std::string& tag) { for (char ** p = envp; *p; p++) if (std::strncmp(*p, tag.c_str(), 7) == 0) { - std::string opt; char * q; + static char buf[128]; + char * r = buf; for (q = *p + 7; *q && *q != '='; q++) if (*q == '_') - opt += '-'; + *r++ += '-'; else - opt += std::tolower(*q); + *r++ += std::tolower(*q); + assert(r < buf + 127); + *r = '\0'; if (*q == '=') - process_option(opt, q + 1); + process_option(buf, q + 1); } } @@ -385,13 +385,12 @@ unsigned int parse_textual_journal(std::istream& in, journal_t * journal, in >> c; in >> date; in >> time; + date += " "; + date += time; in.getline(line, MAX_LINE); linenum++; - date += " "; - date += time; - struct std::tm when; if (strptime(date.c_str(), "%Y/%m/%d %H:%M:%S", &when)) { entry_t * curr = new entry_t; @@ -1,6 +1,8 @@ #include "valexpr.h" #include "error.h" #include "datetime.h" +#include "debug.h" +#include "util.h" #include <vector> @@ -344,32 +346,20 @@ value_expr_t * parse_value_term(std::istream& in) char c = peek_next_nonws(in); if (std::isdigit(c) || c == '.' || c == '{') { - std::string ident; - + static char buf[2048]; if (c == '{') { in.get(c); - c = in.peek(); - while (! in.eof() && c != '}') { - in.get(c); - ident += c; - c = in.peek(); - } + READ_INTO(in, buf, 2048, c, c != '}'); if (c == '}') in.get(c); else throw value_expr_error("Missing '}'"); } else { - while (! in.eof() && std::isdigit(c) || c == '.') { - in.get(c); - ident += c; - c = in.peek(); - } + READ_INTO(in, buf, 2048, c, std::isdigit(c) || c == '.'); } - if (! ident.empty()) { - node = new value_expr_t(value_expr_t::CONSTANT_A); - node->constant_a.parse(ident); - } + node = new value_expr_t(value_expr_t::CONSTANT_A); + node->constant_a.parse(buf); return node; } @@ -443,7 +433,6 @@ value_expr_t * parse_value_term(std::istream& in) // Other case '/': { - std::string ident; bool payee_mask = false; c = peek_next_nonws(in); @@ -453,22 +442,15 @@ value_expr_t * parse_value_term(std::istream& in) c = in.peek(); } - while (! in.eof() && c != '/') { - in.get(c); - if (c == '\\') - in.get(c); - ident += c; - c = in.peek(); - } - - if (c == '/') { - in.get(c); - node = new value_expr_t(payee_mask ? - value_expr_t::F_PAYEE_MASK : value_expr_t::F_ACCOUNT_MASK); - node->mask = new mask_t(ident); - } else { + static char buf[4096]; + READ_INTO(in, buf, 4096, c, c != '/'); + if (c != '/') throw value_expr_error("Missing closing '/'"); - } + + in.get(c); + node = new value_expr_t(payee_mask ? value_expr_t::F_PAYEE_MASK : + value_expr_t::F_ACCOUNT_MASK); + node->mask = new mask_t(buf); break; } @@ -481,22 +463,15 @@ value_expr_t * parse_value_term(std::istream& in) break; case '[': { - std::string ident; - - c = in.peek(); - while (! in.eof() && c != ']') { - in.get(c); - ident += c; - c = in.peek(); - } - if (c == ']') { - in.get(c); - node = new value_expr_t(value_expr_t::CONSTANT_T); - if (! parse_date(ident.c_str(), &node->constant_t)) - throw value_expr_error("Failed to parse date"); - } else { + static char buf[1024]; + READ_INTO(in, buf, 1024, c, c != ']'); + if (c != ']') throw value_expr_error("Missing ']'"); - } + + in.get(c); + node = new value_expr_t(value_expr_t::CONSTANT_T); + if (! parse_date(buf, &node->constant_t)) + throw value_expr_error("Failed to parse date"); break; } @@ -133,9 +133,11 @@ class item_predicate predicate = NULL; if (! _predicate.empty()) { try { +#ifdef DEBUG_ENABLED DEBUG_CLASS("valexpr.predicate.parse"); DEBUG_PRINT_("parsing: '" << _predicate << "'"); +#endif predicate = parse_value_expr(_predicate); #ifdef DEBUG_ENABLED |