Get rid of setjmp/longjmp for error handling in favor of exceptions.

Fatalerror now maps to throwing an exception. Requires a full
recompile.
This commit is contained in:
Aaron Giles 2010-01-04 07:05:53 +00:00
parent 7e88358737
commit 200b21dff7
4 changed files with 167 additions and 120 deletions

View File

@ -20,6 +20,7 @@
#include "romload.h"
#include "sound/samples.h"
#include <new>
#include <ctype.h>
#ifdef MESS
@ -111,13 +112,15 @@ static const options_entry cli_options[] =
int cli_execute(int argc, char **argv, const options_entry *osd_options)
{
core_options *options;
core_options *options = NULL;
astring *gamename = astring_alloc();
astring *exename = astring_alloc();
const char *gamename_option;
const game_driver *driver;
int result;
int result = MAMERR_FATALERROR;
try
{
/* initialize the options manager and add the CLI-specific options */
options = mame_options_init(osd_options);
options_add_entries(options, cli_options);
@ -168,9 +171,29 @@ int cli_execute(int argc, char **argv, const options_entry *osd_options)
/* run the game */
result = mame_execute(options);
}
catch (emu_fatalerror &fatal)
{
fprintf(stderr, "%s\n", fatal.string());
if (fatal.exitcode() != 0)
result = fatal.exitcode();
}
catch (emu_exception &exception)
{
fprintf(stderr, "Caught unhandled emulator exception\n");
}
catch (std::bad_alloc &)
{
fprintf(stderr, "Out of memory!\n");
}
catch (...)
{
fprintf(stderr, "Caught unhandled exception\n");
}
error:
/* free our options and exit */
if (options != NULL)
options_free(options);
astring_free(gamename);
astring_free(exename);

View File

@ -133,11 +133,11 @@ int config_load_settings(running_machine *machine)
astring_free(fname);
if (filerr != FILERR_NONE)
fatalerror("Could not load controller file %s.cfg", controller);
throw emu_fatalerror("Could not load controller file %s.cfg", controller);
/* load the XML */
if (!config_load_xml(machine, file, CONFIG_TYPE_CONTROLLER))
fatalerror("Could not load controller file %s.cfg", controller);
throw emu_fatalerror("Could not load controller file %s.cfg", controller);
mame_fclose(file);
}

View File

@ -19,7 +19,6 @@
mame_execute() [mame.c]
- calls mame_validitychecks() [validity.c] to perform validity checks on all compiled drivers
- calls setjmp to prepare for deep error handling
- begins resource tracking (level 1)
- calls create_machine [mame.c] to initialize the running_machine structure
- calls init_machine() [mame.c]
@ -87,8 +86,8 @@
#include "streams.h"
#include "debug/debugcon.h"
#include <new>
#include <stdarg.h>
#include <setjmp.h>
#include <time.h>
@ -153,10 +152,6 @@ struct _mame_private
region_info * regionlist;
tagmap * regionmap;
/* error recovery and exiting */
jmp_buf fatal_error_jmpbuf;
int fatal_error_jmpbuf_valid;
/* random number seed */
UINT32 rand_seed;
@ -298,10 +293,8 @@ int mame_execute(core_options *options)
init_resource_tracking();
/* use setjmp/longjmp for deep error recovery */
mame->fatal_error_jmpbuf_valid = TRUE;
error = setjmp(mame->fatal_error_jmpbuf);
if (error == 0)
/* use try/catch for deep error recovery */
try
{
int settingsloaded;
@ -372,7 +365,23 @@ int mame_execute(core_options *options)
nvram_save(machine);
config_save_settings(machine);
}
mame->fatal_error_jmpbuf_valid = FALSE;
catch (emu_fatalerror &fatal)
{
mame_printf_error("%s\n", fatal.string());
error = MAMERR_FATALERROR;
if (fatal.exitcode() != 0)
error = fatal.exitcode();
}
catch (emu_exception &exception)
{
mame_printf_error("Caught unhandled emulator exception\n");
error = MAMERR_FATALERROR;
}
catch (std::bad_alloc &)
{
mame_printf_error("Out of memory!\n");
error = MAMERR_FATALERROR;
}
/* call all exit callbacks registered */
for (cb = mame->exit_callback_list; cb; cb = cb->next)
@ -1119,56 +1128,6 @@ void mame_printf_log(const char *format, ...)
MISCELLANEOUS
***************************************************************************/
/*-------------------------------------------------
fatalerror - print a message and escape back
to the OSD layer
-------------------------------------------------*/
DECL_NORETURN static void fatalerror_common(running_machine *machine, int exitcode, const char *buffer) ATTR_NORETURN;
static void fatalerror_common(running_machine *machine, int exitcode, const char *buffer)
{
/* output and return */
mame_printf_error("%s\n", giant_string_buffer);
/* break into the debugger if attached */
osd_break_into_debugger(giant_string_buffer);
/* longjmp back if we can; otherwise, exit */
if (machine != NULL && machine->mame_data != NULL && machine->mame_data->fatal_error_jmpbuf_valid)
longjmp(machine->mame_data->fatal_error_jmpbuf, exitcode);
else
exit(exitcode);
}
void CLIB_DECL fatalerror(const char *text, ...)
{
running_machine *machine = global_machine;
va_list arg;
/* dump to the buffer; assume no one writes >2k lines this way */
va_start(arg, text);
vsnprintf(giant_string_buffer, GIANT_STRING_BUFFER_SIZE, text, arg);
va_end(arg);
fatalerror_common(machine, MAMERR_FATALERROR, giant_string_buffer);
}
void CLIB_DECL fatalerror_exitcode(running_machine *machine, int exitcode, const char *text, ...)
{
va_list arg;
/* dump to the buffer; assume no one writes >2k lines this way */
va_start(arg, text);
vsnprintf(giant_string_buffer, GIANT_STRING_BUFFER_SIZE, text, arg);
va_end(arg);
fatalerror_common(machine, exitcode, giant_string_buffer);
}
/*-------------------------------------------------
popmessage - pop up a user-visible message
-------------------------------------------------*/

View File

@ -17,6 +17,8 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <exception>
#include "osdcomm.h"
#include "bitmap.h"
#include "coreutil.h"
@ -318,13 +320,76 @@ inline void operator--(type &value, int) { value = (type)((int)value - 1); }
/***************************************************************************
EXCEPTION CLASSES
***************************************************************************/
// emu_exception is the base class for all emu-related exceptions
class emu_exception : public std::exception
{
};
// emu_fatalerror is a generic fatal exception that provides an error string
class emu_fatalerror : public emu_exception
{
public:
emu_fatalerror(const char *format, ...)
: m_exitcode(0)
{
va_list ap;
va_start(ap, format);
sprintf(m_text, format, ap);
va_end(ap);
osd_break_into_debugger(m_text);
}
emu_fatalerror(const char *format, va_list ap)
: m_exitcode(0)
{
vsprintf(m_text, format, ap);
osd_break_into_debugger(m_text);
}
emu_fatalerror(int _exitcode, const char *format, va_list ap)
: m_exitcode(_exitcode)
{
vsprintf(m_text, format, ap);
osd_break_into_debugger(m_text);
}
const char *string() const { return m_text; }
int exitcode() const { return m_exitcode; }
private:
char m_text[1024];
int m_exitcode;
};
/***************************************************************************
FUNCTION PROTOTYPES
***************************************************************************/
/* Used by assert(), so definition here instead of mame.h */
DECL_NORETURN void CLIB_DECL fatalerror(const char *text, ...) ATTR_PRINTF(1,2) ATTR_NORETURN;
DECL_NORETURN void CLIB_DECL fatalerror_exitcode(running_machine *machine, int exitcode, const char *text, ...) ATTR_PRINTF(3,4) ATTR_NORETURN;
DECL_NORETURN void fatalerror(const char *format, ...) ATTR_PRINTF(1,2) ATTR_NORETURN;
DECL_NORETURN void fatalerror_exitcode(running_machine *machine, int exitcode, const char *format, ...) ATTR_PRINTF(3,4) ATTR_NORETURN;
inline void fatalerror(const char *format, ...)
{
va_list ap;
va_start(ap, format);
throw emu_fatalerror(format, ap);
va_end(ap);
}
inline void fatalerror_exitcode(running_machine *machine, int exitcode, const char *format, ...)
{
va_list ap;
va_start(ap, format);
throw emu_fatalerror(exitcode, format, ap);
va_end(ap);
}
@ -333,7 +398,7 @@ DECL_NORETURN void CLIB_DECL fatalerror_exitcode(running_machine *machine, int e
***************************************************************************/
/* population count */
INLINE int popcount(UINT32 val)
inline int popcount(UINT32 val)
{
int count;
@ -344,7 +409,7 @@ INLINE int popcount(UINT32 val)
/* convert a series of 32 bits into a float */
INLINE float u2f(UINT32 v)
inline float u2f(UINT32 v)
{
union {
float ff;
@ -356,7 +421,7 @@ INLINE float u2f(UINT32 v)
/* convert a float into a series of 32 bits */
INLINE UINT32 f2u(float f)
inline UINT32 f2u(float f)
{
union {
float ff;
@ -368,7 +433,7 @@ INLINE UINT32 f2u(float f)
/* convert a series of 64 bits into a double */
INLINE double u2d(UINT64 v)
inline double u2d(UINT64 v)
{
union {
double dd;
@ -380,7 +445,7 @@ INLINE double u2d(UINT64 v)
/* convert a double into a series of 64 bits */
INLINE UINT64 d2u(double d)
inline UINT64 d2u(double d)
{
union {
double dd;