# HG changeset patch # User John W. Eaton # Date 1292396727 18000 # Node ID 944b7e20fc5a880004d0c7dbdd0eef1af6fd3d6e # Parent b2191ebea12fba01e5a6694d8d483d73c640d49b improve handling of exceptions for startup files diff --git a/liboctave/ChangeLog b/liboctave/ChangeLog --- a/liboctave/ChangeLog +++ b/liboctave/ChangeLog @@ -1,3 +1,21 @@ +2010-12-15 John W. Eaton + + * cmd-hist.cc (command_history::do_clean_up_and_save, + command_history::do_truncate_file, + command_history::do_append, command_history::do_write, + gnu_history::do_clean_up_and_save, gnu_history::do_truncate_file, + gnu_history::do_append, gnu_history::do_write, + gnu_history::do_read_range): + Don't do anything if not initialized. + + * cmd-hist.cc, cmd-hist.h (command_history::initialize, + command_history::is_initialized): New static functions. + (command_history::do_initialize, + command_history::do_is_initialized): New member functions. + + * cmd-hist.h (command_history::initialized): New data member. + (comand_history::command_history): Initialize it. + 2010-12-14 John W. Eaton * lo-mappers.h (xcopysign (double)): Call copysign, not copysignf. diff --git a/liboctave/cmd-hist.cc b/liboctave/cmd-hist.cc --- a/liboctave/cmd-hist.cc +++ b/liboctave/cmd-hist.cc @@ -253,60 +253,66 @@ void gnu_history::do_write (const std::string& f_arg) { - std::string f = f_arg; - - if (f.empty ()) - f = xfile; - - if (! f.empty ()) + if (initialized) { - int status = ::octave_write_history (f.c_str ()); + std::string f = f_arg; + + if (f.empty ()) + f = xfile; - if (status != 0) - error (status); + if (! f.empty ()) + { + int status = ::octave_write_history (f.c_str ()); + + if (status != 0) + error (status); + } + else + error ("gnu_history::write: missing file name"); } - else - error ("gnu_history::write: missing file name"); } void gnu_history::do_append (const std::string& f_arg) { - if (lines_this_session) + if (initialized) { - if (lines_this_session < do_where ()) + if (lines_this_session) { - // Create file if it doesn't already exist. - - std::string f = f_arg; + if (lines_this_session < do_where ()) + { + // Create file if it doesn't already exist. - if (f.empty ()) - f = xfile; + std::string f = f_arg; - if (! f.empty ()) - { - file_stat fs (f); + if (f.empty ()) + f = xfile; - if (! fs) + if (! f.empty ()) { - int tem; + file_stat fs (f); - tem = gnulib::open (f.c_str (), O_CREAT, 0666); - gnulib::close (tem); - } + if (! fs) + { + int tem; - int status - = ::octave_append_history (lines_this_session, f.c_str ()); + tem = gnulib::open (f.c_str (), O_CREAT, 0666); + gnulib::close (tem); + } - if (status != 0) - error (status); - else - lines_in_file += lines_this_session; + int status + = ::octave_append_history (lines_this_session, f.c_str ()); - lines_this_session = 0; + if (status != 0) + error (status); + else + lines_in_file += lines_this_session; + + lines_this_session = 0; + } + else + error ("gnu_history::append: missing file name"); } - else - error ("gnu_history::append: missing file name"); } } } @@ -314,15 +320,18 @@ void gnu_history::do_truncate_file (const std::string& f_arg, int n) { - std::string f = f_arg; - - if (f.empty ()) - f = xfile; + if (initialized) + { + std::string f = f_arg; - if (! f.empty ()) - ::octave_history_truncate_file (f.c_str (), n); - else - error ("gnu_history::truncate_file: missing file name"); + if (f.empty ()) + f = xfile; + + if (! f.empty ()) + ::octave_history_truncate_file (f.c_str (), n); + else + error ("gnu_history::truncate_file: missing file name"); + } } string_vector @@ -358,22 +367,25 @@ void gnu_history::do_clean_up_and_save (const std::string& f_arg, int n) { - std::string f = f_arg; - - if (f.empty ()) - f = xfile; - - if (! f.empty ()) + if (initialized) { - if (n < 0) - n = xsize; + std::string f = f_arg; - stifle (n); + if (f.empty ()) + f = xfile; - do_write (f.c_str ()); + if (! f.empty ()) + { + if (n < 0) + n = xsize; + + stifle (n); + + do_write (f.c_str ()); + } + else + error ("gnu_history::clean_up_and_save: missing file name"); } - else - error ("gnu_history::clean_up_and_save: missing file name"); } #endif @@ -408,6 +420,22 @@ } void +command_history::initialize (bool read_history_file, + const std::string& f_arg, int sz) +{ + if (instance_ok ()) + instance->do_initialize (read_history_file, f_arg, sz); +} + +bool +command_history::is_initialized (void) +{ + // We just want to check the status of an existing instance, not + // create one. + return instance && instance->do_is_initialized (); +} + +void command_history::set_file (const std::string& f_arg) { if (instance_ok ()) @@ -614,6 +642,25 @@ } void +command_history::do_initialize (bool read_history_file, + const std::string& f_arg, int sz) +{ + command_history::set_file (f_arg); + command_history::set_size (sz); + + if (read_history_file) + command_history::read (false); + + initialized = true; +} + +bool +command_history::do_is_initialized (void) const +{ + return initialized; +} + +void command_history::do_set_file (const std::string& f) { xfile = f; @@ -734,31 +781,37 @@ void command_history::do_write (const std::string& f_arg) { - std::string f = f_arg; + if (initialized) + { + std::string f = f_arg; - if (f.empty ()) - f = xfile; + if (f.empty ()) + f = xfile; - if (f.empty ()) - error ("command_history::write: missing file name"); + if (f.empty ()) + error ("command_history::write: missing file name"); + } } void command_history::do_append (const std::string& f_arg) { - if (lines_this_session) + if (initialized) { - if (lines_this_session < do_where ()) + if (lines_this_session) { - // Create file if it doesn't already exist. + if (lines_this_session < do_where ()) + { + // Create file if it doesn't already exist. - std::string f = f_arg; + std::string f = f_arg; - if (f.empty ()) - f = xfile; + if (f.empty ()) + f = xfile; - if (f.empty ()) - error ("command_history::append: missing file name"); + if (f.empty ()) + error ("command_history::append: missing file name"); + } } } } @@ -766,13 +819,16 @@ void command_history::do_truncate_file (const std::string& f_arg, int) { - std::string f = f_arg; + if (initialized) + { + std::string f = f_arg; - if (f.empty ()) - f = xfile; + if (f.empty ()) + f = xfile; - if (f.empty ()) - error ("command_history::truncate_file: missing file name"); + if (f.empty ()) + error ("command_history::truncate_file: missing file name"); + } } string_vector @@ -795,13 +851,16 @@ void command_history::do_clean_up_and_save (const std::string& f_arg, int) { - std::string f = f_arg; + if (initialized) + { + std::string f = f_arg; - if (f.empty ()) - f = xfile; + if (f.empty ()) + f = xfile; - if (f.empty ()) - error ("command_history::clean_up_and_save: missing file name"); + if (f.empty ()) + error ("command_history::clean_up_and_save: missing file name"); + } } void diff --git a/liboctave/cmd-hist.h b/liboctave/cmd-hist.h --- a/liboctave/cmd-hist.h +++ b/liboctave/cmd-hist.h @@ -34,13 +34,17 @@ protected: command_history (void) - : ignoring_additions (false), lines_in_file (0), + : initialized (false), ignoring_additions (false), lines_in_file (0), lines_this_session (0), xfile (), xsize (-1) { } public: virtual ~command_history (void) { } + static void initialize (bool, const std::string&, int); + + static bool is_initialized (void); + static void set_file (const std::string&); static std::string file (void); @@ -128,6 +132,10 @@ virtual std::string do_file (void); + virtual void do_initialize (bool, const std::string&, int); + + virtual bool do_is_initialized (void) const; + virtual void do_set_size (int); virtual int do_size (void); @@ -182,6 +190,10 @@ void error (const std::string&); + // TRUE means we have initialized the history file name and number of + // lines to save. + bool initialized; + // TRUE means we are ignoring new additions. bool ignoring_additions; diff --git a/src/ChangeLog b/src/ChangeLog --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,13 @@ +2010-12-15 John W. Eaton + + * oct-hist.cc (initialize_history): Call command_history::initialize. + + * octave.cc (gripe_safe_source_exception): New function. + (safe_source_file): New function. + (execute_startup_files): Call safe_source_file instead of source_file. + (execute_command_line_file): Likewise. Don't handle exceptions here. + (execute_eval_option_code): Also catch octave_execution exception. + 2010-12-15 John W. Eaton * lex.h (lexical_feedback::defining_func): Now int instead of bool. diff --git a/src/oct-hist.cc b/src/oct-hist.cc --- a/src/oct-hist.cc +++ b/src/oct-hist.cc @@ -520,11 +520,7 @@ void initialize_history (bool read_history_file) { - command_history::set_file (Vhistory_file); - command_history::set_size (Vhistory_size); - - if (read_history_file) - command_history::read (false); + command_history::initialize (read_history_file, Vhistory_file, Vhistory_size); } void diff --git a/src/octave.cc b/src/octave.cc --- a/src/octave.cc +++ b/src/octave.cc @@ -275,6 +275,51 @@ F__version_info__ (args, 0); } +static void +gripe_safe_source_exception (const std::string& file, const std::string& msg) +{ + std::cerr << "error: " << msg << "\n" + << "error: execution of " << file << " failed\n" + << "error: trying to make my way to a command prompt" + << std::endl; +} + +// Execute commands from a file and catch potential exceptions in a +// consistent way. This function should be called anywhere we might +// parse and execute commands from a file before before we have entered +// the main loop in toplev.cc. + +static void +safe_source_file (const std::string& file_name, + const std::string& context = std::string (), + bool verbose = false, bool require_file = true, + const std::string& warn_for = std::string ()) +{ + try + { + source_file (file_name, context, verbose, require_file, warn_for); + } + catch (octave_interrupt_exception) + { + recover_from_exception (); + octave_stdout << "\n"; + if (quitting_gracefully) + clean_up_and_exit (exit_status); + } + catch (octave_execution_exception) + { + recover_from_exception (); + gripe_safe_source_exception (file_name, "unhandled execution exception"); + } + catch (std::bad_alloc) + { + recover_from_exception (); + gripe_safe_source_exception + (file_name, + "memory exhausted or requested size too large for range of Octave's index type"); + } +} + // Initialize by reading startup files. static void @@ -299,9 +344,10 @@ // (if it exists), then from the file // $(prefix)/share/octave/$(version)/m/octaverc (if it exists). - source_file (Vlocal_site_defaults_file, context, verbose, require_file); + safe_source_file (Vlocal_site_defaults_file, context, verbose, + require_file); - source_file (Vsite_defaults_file, context, verbose, require_file); + safe_source_file (Vsite_defaults_file, context, verbose, require_file); } if (read_init_files) @@ -325,7 +371,7 @@ if (! home_rc.empty ()) { - source_file (home_rc, context, verbose, require_file); + safe_source_file (home_rc, context, verbose, require_file); // Names alone are not enough. @@ -347,7 +393,7 @@ if (local_rc.empty ()) local_rc = octave_env::make_absolute (initfile); - source_file (local_rc, context, verbose, require_file); + safe_source_file (local_rc, context, verbose, require_file); } } } @@ -386,6 +432,12 @@ if (quitting_gracefully) clean_up_and_exit (exit_status); } + catch (octave_execution_exception) + { + recover_from_exception (); + std::cerr << "error: unhandled execution exception -- eval failed" + << std::endl; + } catch (std::bad_alloc) { std::cerr << "error: memory exhausted or requested size too large for range of Octave's index type -- eval failed" @@ -438,26 +490,11 @@ octave_program_name = tmp; - try - { - std::string context; - bool verbose = false; - bool require_file = true; + std::string context; + bool verbose = false; + bool require_file = true; - source_file (fname, context, verbose, require_file, "octave"); - } - catch (octave_interrupt_exception) - { - recover_from_exception (); - octave_stdout << "\n"; - if (quitting_gracefully) - clean_up_and_exit (exit_status); - } - catch (std::bad_alloc) - { - std::cerr << "error: memory exhausted or requested size too large for range of Octave's index type -- execution of " - << fname << " failed" << std::endl; - } + safe_source_file (fname, context, verbose, require_file, "octave"); } // Usage message with extra help.