more options fixes

This commit is contained in:
John Wiegley 2004-08-13 17:02:25 -04:00
parent 8a70bbed52
commit 6944e5950a
6 changed files with 93 additions and 89 deletions

View file

@ -52,43 +52,41 @@ bool journal_t::remove_entry(entry_t * entry)
return true; return true;
} }
entry_t * journal_t::derive_entry(int argc, char **argv) const entry_t * journal_t::derive_entry(strings_list::iterator i,
strings_list::iterator end) const
{ {
entry_t * added = new entry_t; entry_t * added = new entry_t;
entry_t * matching = NULL; entry_t * matching = NULL;
int index = 0;
assert(index < argc); if (! parse_date((*i).c_str(), &added->date)) {
std::cerr << "Error: Bad entry date: " << *i << std::endl;
if (! parse_date(argv[index++], &added->date)) {
std::cerr << "Error: Bad entry date: " << argv[index - 1]
<< std::endl;
return false; return false;
} }
++i;
if (index == argc) { if (i == end) {
std::cerr << "Error: Too few arguments to 'entry'." << std::endl; std::cerr << "Error: Too few arguments to 'entry'." << std::endl;
return false; return false;
} }
mask_t regexp(argv[index++]); mask_t regexp(*i++);
for (entries_list::const_reverse_iterator i = entries.rbegin(); for (entries_list::const_reverse_iterator j = entries.rbegin();
i != entries.rend(); j != entries.rend();
i++) j++)
if (regexp.match((*i)->payee)) { if (regexp.match((*j)->payee)) {
matching = *i; matching = *j;
break; break;
} }
added->payee = matching ? matching->payee : regexp.pattern; added->payee = matching ? matching->payee : regexp.pattern;
if (index == argc) { if (i == end) {
std::cerr << "Error: Too few arguments to 'entry'." << std::endl; std::cerr << "Error: Too few arguments to 'entry'." << std::endl;
return false; return false;
} }
if (argv[index][0] == '-' || std::isdigit(argv[index][0])) { if ((*i)[0] == '-' || std::isdigit((*i)[0])) {
if (! matching) { if (! matching) {
std::cerr << "Error: Missing account name for non-matching entry." std::cerr << "Error: Missing account name for non-matching entry."
<< std::endl; << std::endl;
@ -98,7 +96,7 @@ entry_t * journal_t::derive_entry(int argc, char **argv) const
transaction_t * m_xact, * xact, * first; transaction_t * m_xact, * xact, * first;
m_xact = matching->transactions.front(); m_xact = matching->transactions.front();
amount_t amt(argv[index++]); amount_t amt(*i++);
first = xact = new transaction_t(added, m_xact->account, amt, amt); first = xact = new transaction_t(added, m_xact->account, amt, amt);
if (xact->amount.commodity->symbol.empty()) { if (xact->amount.commodity->symbol.empty()) {
@ -113,12 +111,12 @@ entry_t * journal_t::derive_entry(int argc, char **argv) const
- first->amount, - first->amount); - first->amount, - first->amount);
added->add_transaction(xact); added->add_transaction(xact);
if ((index + 1) < argc && std::string(argv[index]) == "-from") if (std::string(*i++) == "-from" && i != end)
if (account_t * acct = find_account(argv[++index])) if (account_t * acct = find_account(*i))
added->transactions.back()->account = acct; added->transactions.back()->account = acct;
} else { } else {
while (index < argc && std::string(argv[index]) != "-from") { while (std::string(*i) != "-from") {
mask_t acct_regex(argv[index++]); mask_t acct_regex(*i++);
account_t * acct = NULL; account_t * acct = NULL;
commodity_t * cmdty = NULL; commodity_t * cmdty = NULL;
@ -145,12 +143,12 @@ entry_t * journal_t::derive_entry(int argc, char **argv) const
return false; return false;
} }
if (index == argc) { if (i == end) {
std::cerr << "Error: Too few arguments to 'entry'." << std::endl; std::cerr << "Error: Too few arguments to 'entry'." << std::endl;
return false; return false;
} }
amount_t amt(argv[index]++); amount_t amt(*i++);
transaction_t * xact = new transaction_t(added, acct, amt, amt); transaction_t * xact = new transaction_t(added, acct, amt, amt);
if (! xact->amount.commodity) if (! xact->amount.commodity)
@ -159,8 +157,8 @@ entry_t * journal_t::derive_entry(int argc, char **argv) const
added->add_transaction(xact); added->add_transaction(xact);
} }
if ((index + 1) < argc && std::string(argv[index]) == "-from") { if (std::string(*i++) == "-from" && i != end) {
if (account_t * acct = find_account(argv[++index])) { if (account_t * acct = find_account(*i++)) {
transaction_t * xact = new transaction_t(NULL, acct); transaction_t * xact = new transaction_t(NULL, acct);
added->add_transaction(xact); added->add_transaction(xact);
} }

View file

@ -165,7 +165,8 @@ inline std::ostream& operator<<(std::ostream& out, const account_t& acct) {
} }
typedef std::list<entry_t *> entries_list; typedef std::list<entry_t *> entries_list;
typedef std::list<std::string> strings_list;
class journal_t class journal_t
{ {
@ -208,7 +209,8 @@ class journal_t
bool add_entry(entry_t * entry); bool add_entry(entry_t * entry);
bool remove_entry(entry_t * entry); bool remove_entry(entry_t * entry);
entry_t * derive_entry(int argc, char **argv) const; entry_t * derive_entry(strings_list::iterator begin,
strings_list::iterator end) const;
}; };
int parse_journal_file(char * p, journal_t * journal); int parse_journal_file(char * p, journal_t * journal);

68
main.cc
View file

@ -109,6 +109,7 @@ namespace {
bool use_cache = false; bool use_cache = false;
} }
// jww (2004-08-13): fix this
static std::string ledger_cache_file() static std::string ledger_cache_file()
{ {
std::string cache_file; std::string cache_file;
@ -175,12 +176,12 @@ static void show_help(std::ostream& out)
} }
DEF_OPT_HANDLERS();
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// //
// Basic options // Basic options
DEF_OPT_HANDLERS();
OPT_BEGIN(help, "h", false) { OPT_BEGIN(help, "h", false) {
show_help(std::cout); show_help(std::cout);
std::exit(0); std::exit(0);
@ -191,10 +192,10 @@ OPT_BEGIN(version, "v", false) {
std::exit(0); std::exit(0);
} OPT_END(version); } OPT_END(version);
OPT_BEGIN(init_file, "i:", true) { OPT_BEGIN(init, "i:", true) {
std::ifstream stream(optarg); std::ifstream stream(optarg);
parse_textual_journal(stream, journal.get(), journal->master); parse_textual_journal(stream, journal.get(), journal->master);
} OPT_END(init_file); } OPT_END(init);
OPT_BEGIN(file, "f:", true) { OPT_BEGIN(file, "f:", true) {
files.push_back(optarg); files.push_back(optarg);
@ -428,22 +429,14 @@ int main(int argc, char * argv[], char * envp[])
{ {
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
if (char * p = std::getenv("DEBUG_FILE")) { if (char * p = std::getenv("DEBUG_FILE")) {
debug_stream = new std::ofstream(p); debug_stream = new std::ofstream(p);
free_debug_stream = true; free_debug_stream = true;
} }
#endif #endif
// Initialize some variables based on environment variable settings
// jww (2004-08-13): fix these
if (char * p = std::getenv("PRICE_HIST"))
price_db = p;
if (char * p = std::getenv("PRICE_EXP"))
pricing_leeway = std::atol(p) * 60;
// A ledger data file must be specified // A ledger data file must be specified
// jww (2004-08-13): use LEDGER_FILE
use_cache = std::getenv("LEDGER") != NULL; use_cache = std::getenv("LEDGER") != NULL;
if (use_cache) { if (use_cache) {
@ -475,19 +468,23 @@ int main(int argc, char * argv[], char * envp[])
// Parse the command-line options // Parse the command-line options
std::vector<char *> args; std::list<std::string> args;
process_arguments(args, argc, argv); process_arguments(argc, argv, false, args);
if (args.empty()) { if (args.empty()) {
show_help(std::cerr); show_help(std::cerr);
return 1; return 1;
} }
argc = args.size(); std::list<std::string>::iterator arg = args.begin();
int index = 0;
// Process options from the environment // Process options from the environment
process_environment(envp); process_environment(envp, "LEDGER_");
if (char * p = std::getenv("PRICE_HIST"))
process_option("price-db", p);
if (char * p = std::getenv("PRICE_EXP"))
process_option("price-exp", p);
// Read the ledger file, unless we already read it from the cache // Read the ledger file, unless we already read it from the cache
@ -534,7 +531,7 @@ int main(int argc, char * argv[], char * envp[])
// Read the command word, and then check and simplify it // Read the command word, and then check and simplify it
std::string command = args[index++]; std::string command = *arg++;
if (command == "balance" || command == "bal" || command == "b") if (command == "balance" || command == "bal" || command == "b")
command = "b"; command = "b";
@ -556,32 +553,25 @@ int main(int argc, char * argv[], char * envp[])
std::auto_ptr<entry_t> new_entry; std::auto_ptr<entry_t> new_entry;
if (command == "e") { if (command == "e") {
new_entry.reset(journal->derive_entry(argc - index, &args[index])); new_entry.reset(journal->derive_entry(arg, args.end()));
} else { } else {
// Treat the remaining command-line arguments as regular // Treat the remaining command-line arguments as regular
// expressions, used for refining report results. // expressions, used for refining report results.
int start = index; std::list<std::string>::iterator i = args.begin();
for (; index < argc; index++) for (; i != args.end(); i++)
if (std::strcmp(args[index], "--") == 0) { if (*i == "--")
index++;
break; break;
}
if (start < index) { std::string pred = regexps_to_predicate(arg, i);
std::list<std::string> regexps(&args[start], &args[index]); if (! pred.empty()) {
std::string pred = regexps_to_predicate(regexps.begin(), regexps.end()); if (! predicate.empty())
if (! pred.empty()) { predicate += "&";
if (! predicate.empty()) predicate += pred;
predicate += "&";
predicate += pred;
}
} }
if (index < argc) { if (i != args.end()) {
std::list<std::string> regexps(&args[index], &args[argc]); std::string pred = regexps_to_predicate(i, args.end(), false);
std::string pred = regexps_to_predicate(regexps.begin(), regexps.end(),
false);
if (! pred.empty()) { if (! pred.empty()) {
if (! predicate.empty()) if (! predicate.empty())
predicate += "&"; predicate += "&";
@ -608,7 +598,7 @@ int main(int argc, char * argv[], char * envp[])
} }
} }
// Compile the sort criteria // Compile the sorting criteria
if (! sort_string.empty()) { if (! sort_string.empty()) {
try { try {

View file

@ -31,18 +31,6 @@ option_handler::option_handler(const std::string& label,
options.push_back(opt); options.push_back(opt);
} }
bool process_option(const std::string& opt, const char * arg)
{
option_handler_map::iterator handler = option_handler::handlers.find(opt);
if (handler != option_handler::handlers.end() &&
(! (*handler).second->handled || (*handler).second->multiple)) {
(*handler).second->handle_option(arg);
(*handler).second->handled = true;
return true;
}
return false;
}
static inline void process_option(const option_t& opt, static inline void process_option(const option_t& opt,
const char * arg = NULL) { const char * arg = NULL) {
if (! opt.handler->handled || opt.handler->multiple) { if (! opt.handler->handled || opt.handler->multiple) {
@ -51,18 +39,41 @@ static inline void process_option(const option_t& opt,
} }
} }
void process_arguments(std::vector<char *>& args, int argc, char ** argv) bool process_option(const std::string& opt, const char * arg)
{
option_handler_map::iterator handler = option_handler::handlers.find(opt);
if (handler != option_handler::handlers.end()) {
if (! (*handler).second->handled || (*handler).second->multiple) {
(*handler).second->handle_option(arg);
(*handler).second->handled = true;
}
return true;
}
return false;
}
void process_arguments(int argc, char ** argv, const bool anywhere,
std::list<std::string>& args)
{ {
int index = 1; int index = 1;
for (char ** i = argv + 1; index < argc; i++, index++) { for (char ** i = argv + 1; index < argc; i++, index++) {
if ((*i)[0] != '-') { if ((*i)[0] != '-') {
args.push_back(*i); if (anywhere) {
continue; args.push_back(*i);
continue;
} else {
for (; index < argc; i++, index++)
args.push_back(*i);
break;
}
} }
// --long-option // --long-option
again: again:
if ((*i)[1] == '-') { if ((*i)[1] == '-') {
if ((*i)[2] == '\0')
break;
for (std::vector<option_t>::iterator j for (std::vector<option_t>::iterator j
= option_handler::options.begin(); = option_handler::options.begin();
j != option_handler::options.end(); j != option_handler::options.end();
@ -114,10 +125,10 @@ void process_arguments(std::vector<char *>& args, int argc, char ** argv)
} }
} }
void process_environment(char ** envp) void process_environment(char ** envp, const std::string& tag)
{ {
for (char ** p = envp; *p; p++) for (char ** p = envp; *p; p++)
if (std::strncmp(*p, "LEDGER_", 7) == 0) { if (std::strncmp(*p, tag.c_str(), 7) == 0) {
std::string opt; std::string opt;
char * q; char * q;
for (q = *p + 7; *q && *q != '='; q++) for (q = *p + 7; *q && *q != '='; q++)

View file

@ -2,6 +2,7 @@
#define _OPTION_H #define _OPTION_H
#include <map> #include <map>
#include <list>
#include <vector> #include <vector>
#include <string> #include <string>
@ -34,8 +35,9 @@ struct option_handler {
}; };
bool process_option(const std::string& opt, const char * arg = NULL); bool process_option(const std::string& opt, const char * arg = NULL);
void process_arguments(std::vector<char *>& args, int argc, char ** argv); void process_arguments(int argc, char ** argv, const bool anywhere,
void process_environment(char ** envp); std::list<std::string>& args);
void process_environment(char ** envp, const std::string& tag);
#define DEF_OPT_HANDLERS() \ #define DEF_OPT_HANDLERS() \
std::vector<option_t> option_handler::options; \ std::vector<option_t> option_handler::options; \

View file

@ -477,7 +477,8 @@ unsigned int parse_textual_journal(std::istream& in, journal_t * journal,
in >> opt; in >> opt;
in.getline(line, MAX_LINE); in.getline(line, MAX_LINE);
linenum++; linenum++;
process_option(opt, line + 1); char * p = skip_ws(line);
process_option(opt, *p == '\n' ? NULL : p);
break; break;
} }