# # # patch "monotone.cc" # from [dc002c1cf57bd83c95abc9deb703faa373ed52eb] # to [30b9b579faa66edf99d8158a2a86bc31cc397e5a] # # patch "sanity.cc" # from [ca4bd80fa83a478d324ec37adb6468b9a884401d] # to [9239c106c34e6fc9d81f414f686041b099f39a67] # # patch "sanity.hh" # from [e4a9495b8a3e2f7b715ee409cdc3727af161597f] # to [9b631056da3997a94b2310e7f10d65c219fa5312] # # patch "ui.cc" # from [62f1f7056425bf6bbd3beb02ee742eee4fd58adb] # to [6faee43c3da0f450bd0a41707e96afbe954c5095] # # patch "ui.hh" # from [9a3acd06bf677e16f092cfd96c414a27cefe1c30] # to [2ad61177a522bbc9fb7dae6d6c90b79e6a3ff639] # ============================================================ --- monotone.cc dc002c1cf57bd83c95abc9deb703faa373ed52eb +++ monotone.cc 30b9b579faa66edf99d8158a2a86bc31cc397e5a @@ -10,7 +10,6 @@ #include "base.hh" #include -#include #include #include #include @@ -33,8 +32,6 @@ #include "platform.hh" #include "work.hh" -using std::cout; -using std::cerr; using std::string; using std::ios_base; using std::ostringstream; @@ -74,15 +71,6 @@ using std::ios_base; // will be dumped out. if the fatal condition is only caught in the lower- // level handlers in main.cc, at least we'll get a friendly error message. -// Wrapper class which ensures proper setup and teardown of the global ui -// object. (We do not want to use global con/destructors for this, as they -// execute outside the protection of main.cc's signal handlers.) -struct ui_library -{ - ui_library() { ui.initialize(); } - ~ui_library() { ui.deinitialize(); } -}; - // define the global objects needed by botan_pipe_cache.hh pipe_cache_cleanup * global_pipe_cleanup_object; Botan::Pipe * unfiltered_pipe; @@ -131,21 +119,11 @@ commands::command_id read_options(option return cmd; } -string -get_usage_str(options::options_type const & optset, options & opts) -{ - vector names; - vector descriptions; - unsigned int maxnamelen; - - optset.instantiate(&opts).get_usage_strings(names, descriptions, maxnamelen); - return format_usage_strings(names, descriptions, maxnamelen); -} - void mtn_terminate_handler() { - ui.fatal(F("std::terminate() - exception thrown while handling another exception")); + ui.fatal(F("std::terminate() - " + "exception thrown while handling another exception")); exit(3); } @@ -153,7 +131,7 @@ cpp_main(int argc, char ** argv) cpp_main(int argc, char ** argv) { // go-go gadget i18n - setlocale(LC_ALL, ""); + char const * localename = setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, get_locale_dir().c_str()); textdomain(PACKAGE); @@ -170,7 +148,7 @@ cpp_main(int argc, char ** argv) // Set up the global sanity object. No destructor is needed and // therefore no wrapper object is needed either. This has the // side effect of making the 'prog_name' global usable. - global_sanity.initialize(argc, argv, setlocale(LC_ALL, 0)); + global_sanity.initialize(argc, argv, localename); // Set up secure memory allocation etc Botan::LibraryInitializer acquire_botan("thread_safe=0 selftest=0 " @@ -312,44 +290,8 @@ cpp_main(int argc, char ** argv) } catch (usage & u) { - // we send --help output to stdout, so that "mtn --help | less" works - // but we send error-triggered usage information to stderr, so that if - // you screw up in a script, you don't just get usage information sent - // merrily down your pipes. - std::ostream & usage_stream = (app.opts.help ? cout : cerr); - - string visibleid; - if (!u.which.empty()) - visibleid = join_words(vector< utf8 >(u.which.begin() + 1, - u.which.end()))(); - - usage_stream << F("Usage: %s [OPTION...] command [ARG...]") % - prog_name << "\n\n"; - - if (u.which.empty()) - usage_stream << get_usage_str(options::opts::globals(), app.opts); - - // Make sure to hide documentation that's not part of - // the current command. - options::options_type cmd_options = - commands::command_options(u.which); - if (!cmd_options.empty()) - { - usage_stream - << F("Options specific to '%s %s' " - "(run '%s help' to see global options):") - % prog_name % visibleid % prog_name - << "\n\n"; - usage_stream << get_usage_str(cmd_options, app.opts); - } - - commands::explain_usage(u.which, - app.opts.show_hidden_commands, - usage_stream); - if (app.opts.help) - return 0; - else - return 2; + ui.inform_usage(u, app.opts); + return app.opts.help ? 0 : 2; } } catch (option::option_error const & inf) ============================================================ --- sanity.cc ca4bd80fa83a478d324ec37adb6468b9a884401d +++ sanity.cc 9239c106c34e6fc9d81f414f686041b099f39a67 @@ -10,10 +10,9 @@ #include "base.hh" #include #include -#include #include -#include "vector.hh" #include +#include "vector.hh" #include #include @@ -37,9 +36,8 @@ using boost::format; using boost::format; -extern string const & prog_name; -static string real_prog_name; -string const & prog_name = real_prog_name; +// set by sanity::initialize +std::string const * prog_name_ptr; string origin::type_to_string(origin::type t) @@ -71,6 +69,7 @@ struct sanity::impl bool quiet; bool reallyquiet; boost::circular_buffer logbuf; + std::string real_prog_name; std::string filename; std::string gasp_dump; bool already_dumping; @@ -123,14 +122,18 @@ sanity::initialize(int argc, char ** arg PERM_MM(string(lc_all)); L(FL("set locale: LC_ALL=%s") % lc_all); - // find base name of executable and save in the prog_name global note that + // find base name of executable and save in the prog_name global. note that // this does not bother with conversion to utf8. - real_prog_name = argv[0]; - if (real_prog_name.rfind(".exe") == prog_name.size() - 4) - real_prog_name = real_prog_name.substr(0, prog_name.size() - 4); - string::size_type last_slash = real_prog_name.find_last_of("/\\"); - if (last_slash != string::npos) - real_prog_name.erase(0, last_slash+1); + { + string av0 = argv[0]; + if (av0.rfind(".exe") == av0.size() - 4) + av0.erase(av0.size() - 4); + string::size_type last_slash = av0.find_last_of("/\\"); + if (last_slash != string::npos) + av0.erase(0, last_slash+1); + imp->real_prog_name = av0; + prog_name_ptr = &imp->real_prog_name; + } } void @@ -443,14 +446,14 @@ void } void -print_var(std::string const & value, char const * var, - char const * file, int const line, char const * func) +sanity::print_var(std::string const & value, char const * var, + char const * file, int const line, char const * func) { - std::cout << (FL("----- begin '%s' (in %s, at %s:%d)\n") - % var % func % file % line) - << value - << (FL("\n----- end '%s' (in %s, at %s:%d)\n\n") - % var % func % file % line); + inform_message((FL("----- begin '%s' (in %s, at %s:%d)") + % var % func % file % line).str()); + inform_message(value); + inform_message((FL("----- end '%s' (in %s, at %s:%d)\n\n") + % var % func % file % line).str()); } void MusingBase::gasp_head(string & out) const ============================================================ --- sanity.hh e4a9495b8a3e2f7b715ee409cdc3727af161597f +++ sanity.hh 9b631056da3997a94b2310e7f10d65c219fa5312 @@ -98,6 +98,13 @@ struct sanity { void push_musing(MusingI const *musing); void pop_musing(MusingI const *musing); + // debugging aid, see DUMP() below + void print_var(std::string const & value, + char const * var, + char const * file, + int const line, + char const * func); + private: std::string do_format(format_base const & fmt, char const * file, int line); @@ -111,7 +118,9 @@ extern sanity & global_sanity; }; extern sanity & global_sanity; -extern std::string const & prog_name; +// we think this is less ugly than any available tricks with references +extern std::string const * prog_name_ptr; +#define prog_name (*prog_name_ptr) typedef std::runtime_error oops; @@ -470,19 +479,13 @@ Musing::gasp(std::string & out) const // debugging utility to dump out vars like MM but without requiring a crash -extern void print_var(std::string const & value, - char const * var, - char const * file, - int const line, - char const * func); - template void dump(T const & t, char const *var, char const * file, int const line, char const * func) { std::string value; dump(t, value); - print_var(value, var, file, line, func); + global_sanity.print_var(value, var, file, line, func); }; #define DUMP(foo) dump(foo, #foo, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION) ============================================================ --- ui.cc 62f1f7056425bf6bbd3beb02ee742eee4fd58adb +++ ui.cc 6faee43c3da0f450bd0a41707e96afbe954c5095 @@ -20,6 +20,7 @@ #include "charset.hh" #include "simplestring_xform.hh" #include "constants.hh" +#include "commands.hh" #include #include @@ -432,8 +433,6 @@ void tick_write_dot::clear_line() // global, and we don't want global constructors/destructors doing // any real work. see monotone.cc for how this is handled. -user_interface::user_interface() : imp(0) {} - void user_interface::initialize() { imp = new user_interface::impl; @@ -449,9 +448,6 @@ void user_interface::initialize() set_tick_write_dot(); } -user_interface::~user_interface() -{} - void user_interface::deinitialize() { I(imp); @@ -770,7 +766,7 @@ format_text(i18n_format const & text, si } // Format a block of options and their descriptions. -string +static string format_usage_strings(vector const & names, vector const & descriptions, unsigned int namelen) @@ -812,7 +808,54 @@ format_usage_strings(vector cons return result; } +static string +get_usage_str(options::options_type const & optset, options & opts) +{ + vector names; + vector descriptions; + unsigned int maxnamelen; + optset.instantiate(&opts).get_usage_strings(names, descriptions, maxnamelen); + return format_usage_strings(names, descriptions, maxnamelen); +} + +void +user_interface::inform_usage(usage const & u, options & opts) +{ + // we send --help output to stdout, so that "mtn --help | less" works + // but we send error-triggered usage information to stderr, so that if + // you screw up in a script, you don't just get usage information sent + // merrily down your pipes. + std::ostream & usage_stream = (opts.help ? cout : clog); + + string visibleid; + if (!u.which.empty()) + visibleid = join_words(vector< utf8 >(u.which.begin() + 1, + u.which.end()))(); + + usage_stream << F("Usage: %s [OPTION...] command [ARG...]") % + prog_name << "\n\n"; + + if (u.which.empty()) + usage_stream << get_usage_str(options::opts::globals(), opts); + + // Make sure to hide documentation that's not part of + // the current command. + options::options_type cmd_options = + commands::command_options(u.which); + if (!cmd_options.empty()) + { + usage_stream + << F("Options specific to '%s %s' " + "(run '%s help' to see global options):") + % prog_name % visibleid % prog_name + << "\n\n"; + usage_stream << get_usage_str(cmd_options, opts); + } + + commands::explain_usage(u.which, opts.show_hidden_commands, usage_stream); +} + // Local Variables: // mode: C++ // fill-column: 76 ============================================================ --- ui.hh 9a3acd06bf677e16f092cfd96c414a27cefe1c30 +++ ui.hh 2ad61177a522bbc9fb7dae6d6c90b79e6a3ff639 @@ -18,6 +18,8 @@ class system_path; struct i18n_format; class system_path; +struct usage; +struct options; struct ticker { @@ -47,8 +49,6 @@ public: struct user_interface { public: - user_interface(); - ~user_interface(); void initialize(); void deinitialize(); void warn(std::string const & warning); @@ -59,6 +59,7 @@ public: void fatal_db(format_base const & fmt) { fatal_db(fmt.str()); } void inform(std::string const & line); void inform(format_base const & fmt) { inform(fmt.str()); } + void inform_usage(usage const & u, options & opts); void fatal_exception(std::exception const & ex); void fatal_exception(); void set_tick_trailer(std::string const & trailer); @@ -84,6 +85,15 @@ extern struct user_interface ui; extern struct user_interface ui; +// Wrapper class which ensures proper setup and teardown of the global ui +// object. (We do not want to use global con/destructors for this, as they +// execute outside the protection of main.cc's signal handlers.) +struct ui_library +{ + ui_library() { ui.initialize(); } + ~ui_library() { ui.deinitialize(); } +}; + // like platform.hh's "terminal_width", but always returns a sensible value // (even if there is no terminal) unsigned int guess_terminal_width(); @@ -93,11 +103,6 @@ std::string format_text(i18n_format cons std::string format_text(i18n_format const & text, size_t const col = 0, size_t curcol = 0); -std::string -format_usage_strings(std::vector const & names, - std::vector const & descriptions, - unsigned int namelen); - #endif // __UI_HH__ // Local Variables: