diff options
Diffstat (limited to 'main.cc')
-rw-r--r-- | main.cc | 229 |
1 files changed, 97 insertions, 132 deletions
@@ -45,17 +45,6 @@ #include <fdstream.hpp> #endif -namespace ledger { - value_t register_command(expr::call_scope_t& args) - { - expr::var_t<std::ostream> ostream(args, "ostream"); - - *ostream << "This (will be) the register command.\n"; - - return true; - } -} - static int read_and_report(ledger::report_t& report, int argc, char * argv[], char * envp[]) { @@ -114,44 +103,58 @@ static int read_and_report(ledger::report_t& report, int argc, char * argv[], if (! session.use_cache) INFO("Binary cache mechanism will not be used"); - // Read the command word and create a command object based on it + // Configure the output stream - string verb = *arg++; +#ifdef HAVE_UNIX_PIPES + int status, pfd[2]; // Pipe file descriptors +#endif + std::ostream * out = &std::cout; - expr::function_t command; + if (report.output_file) { + out = new ofstream(*report.output_file); + } +#ifdef HAVE_UNIX_PIPES + else if (report.pager) { + status = pipe(pfd); + if (status == -1) + throw_(std::logic_error, "Failed to create pipe"); - if (verb == "register" || verb == "reg" || verb == "r") - command = register_command; -#if 0 - else if (verb == "balance" || verb == "bal" || verb == "b") - command = balance_command(); - else if (verb == "print" || verb == "p") - command = print_command(); - else if (verb == "equity") - command = equity_command(); - else if (verb == "entry") - command = entry_command(); - else if (verb == "dump") - command = dump_command(); - else if (verb == "output") - command = output_command(); - else if (verb == "prices") - command = prices_command(); - else if (verb == "pricesdb") - command = pricesdb_command(); - else if (verb == "csv") - command = csv_command(); - else if (verb == "emacs" || verb == "lisp") - command = emacs_command(); - else if (verb == "xml") - command = bind(xml_command, _1); - ; + status = fork(); + if (status < 0) { + throw_(std::logic_error, "Failed to fork child process"); + } + else if (status == 0) { // child + // Duplicate pipe's reading end into stdin + status = dup2(pfd[0], STDIN_FILENO); + if (status == -1) + perror("dup2"); + + // Close unuseful file descriptors: the pipe's writing and + // reading ends (the latter is not needed anymore, after the + // duplication). + close(pfd[1]); + close(pfd[0]); + + // Find command name: its the substring starting right of the + // rightmost '/' character in the pager pathname. See manpage + // for strrchr. + execlp(report.pager->native_file_string().c_str(), + basename(*report.pager).c_str(), (char *)0); + perror("execl"); + exit(1); + } + else { // parent + close(pfd[0]); + out = new boost::fdostream(pfd[1]); + } + } #endif - else if (verb == "expr") - ; - else if (verb == "xpath") - ; - else if (verb == "parse") { + + // Read the command word and create a command object based on it + + string verb = *arg++; + + if (verb == "parse") { value_expr expr(*arg); #if 0 @@ -184,17 +187,6 @@ static int read_and_report(ledger::report_t& report, int argc, char * argv[], return 0; } - else { - char buf[128]; - std::strcpy(buf, "command_"); - std::strcat(buf, verb.c_str()); - - if (expr::ptr_op_t def = report.lookup(buf)) - command = def->as_function(); - - if (! command) - throw_(std::logic_error, string("Unrecognized command '") + verb + "'"); - } // Parse the initialization file, which can only be textual; then // parse the journal data. @@ -221,55 +213,6 @@ static int read_and_report(ledger::report_t& report, int argc, char * argv[], TRACE_FINISH(entries, 1); TRACE_FINISH(parsing_total, 1); - // Configure the output stream - -#ifdef HAVE_UNIX_PIPES - int status, pfd[2]; // Pipe file descriptors -#endif - std::ostream * out = &std::cout; - - if (report.output_file) { - out = new ofstream(*report.output_file); - } -#ifdef HAVE_UNIX_PIPES - else if (report.pager) { - status = pipe(pfd); - if (status == -1) - throw_(std::logic_error, "Failed to create pipe"); - - status = fork(); - if (status < 0) { - throw_(std::logic_error, "Failed to fork child process"); - } - else if (status == 0) { // child - // Duplicate pipe's reading end into stdin - status = dup2(pfd[0], STDIN_FILENO); - if (status == -1) - perror("dup2"); - - // Close unuseful file descriptors: the pipe's writing and - // reading ends (the latter is not needed anymore, after the - // duplication). - close(pfd[1]); - close(pfd[0]); - - // Find command name: its the substring starting right of the - // rightmost '/' character in the pager pathname. See manpage - // for strrchr. - execlp(report.pager->native_file_string().c_str(), - basename(*report.pager).c_str(), (char *)0); - perror("execl"); - exit(1); - } - else { // parent - close(pfd[0]); - out = new boost::fdostream(pfd[1]); - } - } -#endif - - report.define("ostream", value_t(out)); - // Are we handling the expr commands? Do so now. if (verb == "expr") { @@ -294,11 +237,52 @@ static int read_and_report(ledger::report_t& report, int argc, char * argv[], return 0; } - // Apply transforms to the hierarchical document structure + // Read the command word and create a command object based on it - INFO_START(transforms, "Applied transforms"); - report.apply_transforms(*expr::global_scope); - INFO_FINISH(transforms); + if (verb == "register" || verb == "reg" || verb == "r") + report.transactions_report + (xact_handler_ptr(new format_transactions(*out, session.register_format))); + else if (verb == "balance" || verb == "bal" || verb == "b") + report.accounts_report + (acct_handler_ptr(new format_accounts(*out, session.balance_format, + report.display_predicate))); +#if 0 + else if (verb == "print" || verb == "p") + command = print_command(); + else if (verb == "equity") + command = equity_command(); + else if (verb == "entry") + command = entry_command(); + else if (verb == "dump") + command = dump_command(); + else if (verb == "output") + command = output_command(); + else if (verb == "prices") + command = prices_command(); + else if (verb == "pricesdb") + command = pricesdb_command(); + else if (verb == "csv") + command = csv_command(); + else if (verb == "emacs" || verb == "lisp") + command = emacs_command(); + else if (verb == "xml") + command = bind(xml_command, _1); + ; + else if (verb == "expr") + ; + else if (verb == "xpath") + ; + else { + char buf[128]; + std::strcpy(buf, "command_"); + std::strcat(buf, verb.c_str()); + + if (expr::ptr_op_t def = report.lookup(buf)) + command = def->as_function(); + + if (! command) + throw_(std::logic_error, string("Unrecognized command '") + verb + "'"); + } // Create an argument scope containing the report command's // arguments, and then invoke the command. @@ -313,31 +297,12 @@ static int read_and_report(ledger::report_t& report, int argc, char * argv[], command(command_args); INFO_FINISH(command); - - // Clean up memory, if we - - if (DO_VERIFY()) { - TRACE_START(cleanup, 1, "Cleaning up allocated memory"); - - clear_transaction_xdata xact_cleaner; - walk_entries(journal.entries, xact_cleaner); - - clear_account_xdata acct_cleaner; - walk_accounts(*journal.master, acct_cleaner); - - if (report.output_file) - checked_delete(out); - -#if 0 - for (std::list<item_handler<transaction_t> *>::iterator i - = formatter_ptrs.begin(); - i != formatter_ptrs.end(); - i++) - checked_delete(*i); #endif - TRACE_FINISH(cleanup, 1); - } + // Clean up memory, if it matters + + if (DO_VERIFY() && report.output_file) + checked_delete(out); // Write out the binary cache, if need be |