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

68
main.cc
View file

@ -109,6 +109,7 @@ namespace {
bool use_cache = false;
}
// jww (2004-08-13): fix this
static std::string ledger_cache_file()
{
std::string cache_file;
@ -175,12 +176,12 @@ static void show_help(std::ostream& out)
}
DEF_OPT_HANDLERS();
//////////////////////////////////////////////////////////////////////
//
// Basic options
DEF_OPT_HANDLERS();
OPT_BEGIN(help, "h", false) {
show_help(std::cout);
std::exit(0);
@ -191,10 +192,10 @@ OPT_BEGIN(version, "v", false) {
std::exit(0);
} OPT_END(version);
OPT_BEGIN(init_file, "i:", true) {
OPT_BEGIN(init, "i:", true) {
std::ifstream stream(optarg);
parse_textual_journal(stream, journal.get(), journal->master);
} OPT_END(init_file);
} OPT_END(init);
OPT_BEGIN(file, "f:", true) {
files.push_back(optarg);
@ -428,22 +429,14 @@ int main(int argc, char * argv[], char * envp[])
{
#ifdef DEBUG_ENABLED
if (char * p = std::getenv("DEBUG_FILE")) {
debug_stream = new std::ofstream(p);
debug_stream = new std::ofstream(p);
free_debug_stream = true;
}
#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
// jww (2004-08-13): use LEDGER_FILE
use_cache = std::getenv("LEDGER") != NULL;
if (use_cache) {
@ -475,19 +468,23 @@ int main(int argc, char * argv[], char * envp[])
// Parse the command-line options
std::vector<char *> args;
process_arguments(args, argc, argv);
std::list<std::string> args;
process_arguments(argc, argv, false, args);
if (args.empty()) {
show_help(std::cerr);
return 1;
}
argc = args.size();
int index = 0;
std::list<std::string>::iterator arg = args.begin();
// 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
@ -534,7 +531,7 @@ int main(int argc, char * argv[], char * envp[])
// 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")
command = "b";
@ -556,32 +553,25 @@ int main(int argc, char * argv[], char * envp[])
std::auto_ptr<entry_t> new_entry;
if (command == "e") {
new_entry.reset(journal->derive_entry(argc - index, &args[index]));
new_entry.reset(journal->derive_entry(arg, args.end()));
} else {
// Treat the remaining command-line arguments as regular
// expressions, used for refining report results.
int start = index;
for (; index < argc; index++)
if (std::strcmp(args[index], "--") == 0) {
index++;
std::list<std::string>::iterator i = args.begin();
for (; i != args.end(); i++)
if (*i == "--")
break;
}
if (start < index) {
std::list<std::string> regexps(&args[start], &args[index]);
std::string pred = regexps_to_predicate(regexps.begin(), regexps.end());
if (! pred.empty()) {
if (! predicate.empty())
predicate += "&";
predicate += pred;
}
std::string pred = regexps_to_predicate(arg, i);
if (! pred.empty()) {
if (! predicate.empty())
predicate += "&";
predicate += pred;
}
if (index < argc) {
std::list<std::string> regexps(&args[index], &args[argc]);
std::string pred = regexps_to_predicate(regexps.begin(), regexps.end(),
false);
if (i != args.end()) {
std::string pred = regexps_to_predicate(i, args.end(), false);
if (! pred.empty()) {
if (! predicate.empty())
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()) {
try {

View file

@ -31,18 +31,6 @@ option_handler::option_handler(const std::string& label,
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,
const char * arg = NULL) {
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;
for (char ** i = argv + 1; index < argc; i++, index++) {
if ((*i)[0] != '-') {
args.push_back(*i);
continue;
if (anywhere) {
args.push_back(*i);
continue;
} else {
for (; index < argc; i++, index++)
args.push_back(*i);
break;
}
}
// --long-option
again:
again:
if ((*i)[1] == '-') {
if ((*i)[2] == '\0')
break;
for (std::vector<option_t>::iterator j
= option_handler::options.begin();
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++)
if (std::strncmp(*p, "LEDGER_", 7) == 0) {
if (std::strncmp(*p, tag.c_str(), 7) == 0) {
std::string opt;
char * q;
for (q = *p + 7; *q && *q != '='; q++)

View file

@ -2,6 +2,7 @@
#define _OPTION_H
#include <map>
#include <list>
#include <vector>
#include <string>
@ -34,8 +35,9 @@ struct option_handler {
};
bool process_option(const std::string& opt, const char * arg = NULL);
void process_arguments(std::vector<char *>& args, int argc, char ** argv);
void process_environment(char ** envp);
void process_arguments(int argc, char ** argv, const bool anywhere,
std::list<std::string>& args);
void process_environment(char ** envp, const std::string& tag);
#define DEF_OPT_HANDLERS() \
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.getline(line, MAX_LINE);
linenum++;
process_option(opt, line + 1);
char * p = skip_ws(line);
process_option(opt, *p == '\n' ? NULL : p);
break;
}