More attempted error handling

This was SVN commit r769.
This commit is contained in:
Ykkrosh 2004-07-17 17:09:33 +00:00
parent 1d44976b35
commit 1e40ed1543
17 changed files with 340 additions and 149 deletions

View file

@ -31,13 +31,15 @@ print $out <<'.';
// elsewhere - trust the compiler to handle them identically
.
for (sort keys %groups) {
my ($base, $name) = split /~/;
for (sort { $a->[1] cmp $b->[1] } map [$_, do{(my $c=$_)=~s/~/_/;$c} ], keys %groups) {
my ($base, $name) = split /~/, $_->[0];
print $out "class ${base}_$name : public $base {};\n";
}
for (sort keys %types) {
my ($base, $name) = split /~/;
print $out "\n";
for (sort { $a->[1] cmp $b->[1] } map [$_, do{(my $c=$_)=~s/~/_/;$c} ], keys %types) {
my ($base, $name) = split /~/, $_->[0];
print $out "class ${base}_$name : public $base { public: ${base}_$name(); };\n";
}
@ -47,7 +49,7 @@ print $out "\n// The relevant bits of this file:\n";
for (sort keys %types) {
my ($base, $name) = split /~/;
print $out "${base}_${name}::${base}_${name}() { magic=0x50534552; code=$types{$_}; }\n";
print $out "${base}_${name}::${base}_${name}() { magic=0x45725221; code=$types{$_}; }\n";
}
print $out <<".";

View file

@ -150,7 +150,7 @@ bool CObjectEntry::Load(const char* filename)
{
XeroFile.Load(filename);
}
catch (...)
catch (PSERROR_Xeromyces)
{
return false;
}

View file

@ -353,8 +353,6 @@ void CGUI::DrawSprite(const CStr& SpriteName,
if (SpriteName == CStr())
return;
const char * buf = SpriteName;
bool DoClipping = (Clipping != CRect());
CGUISprite Sprite;
@ -904,8 +902,8 @@ void CGUI::LoadXMLFile(const string &Filename)
{
XeroFile.Load(Filename.c_str());
}
catch (PSERROR_Xeromyces& err) {
UNUSED(err);
catch (PSERROR_Xeromyces)
{
// Fail silently
return;
}
@ -916,31 +914,40 @@ void CGUI::LoadXMLFile(const string &Filename)
// data we'll be expecting
std::string root_name = XeroFile.getElementString(node.getNodeName());
if (root_name == "objects")
try
{
Xeromyces_ReadRootObjects(node, &XeroFile);
// Re-cache all values so these gets cached too.
//UpdateResolution();
if (root_name == "objects")
{
Xeromyces_ReadRootObjects(node, &XeroFile);
// Re-cache all values so these gets cached too.
//UpdateResolution();
}
else
if (root_name == "sprites")
{
Xeromyces_ReadRootSprites(node, &XeroFile);
}
else
if (root_name == "styles")
{
Xeromyces_ReadRootStyles(node, &XeroFile);
}
else
if (root_name == "setup")
{
Xeromyces_ReadRootSetup(node, &XeroFile);
}
else
{
// TODO Gee: Output in log
}
}
else
if (root_name == "sprites")
catch (PSERROR_GUI)
{
Xeromyces_ReadRootSprites(node, &XeroFile);
}
else
if (root_name == "styles")
{
Xeromyces_ReadRootStyles(node, &XeroFile);
}
else
if (root_name == "setup")
{
Xeromyces_ReadRootSetup(node, &XeroFile);
}
else
{
// TODO Gee: Output in log
LOG(ERROR, "Errors loading GUI file %s", Filename.c_str());
return;
}
// Now report if any other errors occured
@ -1104,7 +1111,7 @@ void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObjec
continue;
// Ignore "type" and "style", we've already checked it
if (attr.Name == attr_type || attr.Name == attr_style )
if (attr.Name == attr_type || attr.Name == attr_style)
continue;
// Also the name needs some special attention
@ -1118,6 +1125,44 @@ void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObjec
if (attr.Name == attr_z)
ManuallySetZ = true;
// Generate "stretched:filename" sprites.
//
// Check whether it's actually one of the many sprite... parameters.
if (pFile->getAttributeString(attr.Name).substr(0, 6) == "sprite")
{
// Check whether it's a special stretched one
std::string SpriteName = CStr8(attr.Value);
if (SpriteName.substr(0, 10) == "stretched:" &&
m_Sprites.find(SpriteName) == m_Sprites.end() )
{
CGUISprite sprite;
SGUIImage image;
CStr DefaultSize ("0 0 100% 100%");
image.m_TextureSize = CClientArea(DefaultSize);
image.m_Size = CClientArea(DefaultSize);
std::string TexFilename = "art/textures/ui/";
TexFilename += SpriteName.substr(10);
image.m_TextureName = TexFilename;
Handle tex = tex_load(TexFilename.c_str());
if (tex <= 0)
{
LOG(ERROR, "Error opening texture '%s': %lld", TexFilename.c_str(), tex);
throw PSERROR_GUI_TextureLoadFailed();
}
image.m_Texture = tex;
// TODO: more error handling
tex_upload(tex);
sprite.AddImage(image);
m_Sprites[SpriteName] = sprite;
}
}
// Try setting the value
try
{
@ -1192,20 +1237,24 @@ void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObjec
{
Handle h = vfs_open(file);
if (h <= 0)
// TODO: Error handling
assert(! "File open failed");
else
{
void* data;
size_t len;
int err = vfs_map(h, 0, data, len);
assert(err == 0);
code = (char*)data;
vfs_unmap(h);
vfs_close(h);
LOG(ERROR, "Error opening action file '%s': %lld", file, h);
throw PSERROR_GUI_JSOpenFailed();
}
void* data;
size_t len;
int err = vfs_map(h, 0, data, len);
if (err)
{
LOG(ERROR, "Error mapping action file '%s': %lld", file, err);
throw PSERROR_GUI_JSOpenFailed();
}
code = (char*)data;
vfs_unmap(h);
vfs_close(h);
}
// Read the inline code (concatenating to the file code, if both are specified)
@ -1274,21 +1323,25 @@ void CGUI::Xeromyces_ReadScript(XMBElement Element, CXeromyces* pFile)
{
Handle h = vfs_open(file);
if (h <= 0)
// TODO: Error handling
assert(! "File open failed");
else
{
void* data;
size_t len;
int err = vfs_map(h, 0, data, len);
assert(err == 0);
jsval result;
JS_EvaluateScript(g_ScriptingHost.getContext(), (JSObject*)m_ScriptObject, (const char*)data, (int)len, file, 1, &result);
vfs_unmap(h);
vfs_close(h);
LOG(ERROR, "Error opening script file '%s': %lld", file, h);
throw PSERROR_GUI_JSOpenFailed();
}
void* data;
size_t len;
int err = vfs_map(h, 0, data, len);
if (err)
{
LOG(ERROR, "Error mapping script file '%s': %lld", file, err);
throw PSERROR_GUI_JSOpenFailed();
}
jsval result;
JS_EvaluateScript(g_ScriptingHost.getContext(), (JSObject*)m_ScriptObject, (const char*)data, (int)len, file, 1, &result);
vfs_unmap(h);
vfs_close(h);
}
// Execute inline scripts
@ -1376,8 +1429,8 @@ void CGUI::Xeromyces_ReadImage(XMBElement Element, CXeromyces* pFile, CGUISprite
Handle tex = tex_load(TexFilename.c_str());
if (tex <= 0)
{
// TODO: Error
assert(! "Failed to load texture");
LOG(ERROR, "Error opening texture '%s': %lld", TexFilename.c_str(), tex);
throw PSERROR_GUI_TextureLoadFailed();
}
image.m_Texture = tex;
tex_upload(tex);

View file

@ -17,6 +17,10 @@ gee@pyro.nu
#ifndef CGUI_H
#define CGUI_H
ERROR_GROUP(PSERROR, GUI);
ERROR_TYPE(PSERROR_GUI, JSOpenFailed);
ERROR_TYPE(PSERROR_GUI, TextureLoadFailed);
//--------------------------------------------------------
// Includes / Compiler directives
//--------------------------------------------------------

View file

@ -1,4 +1,4 @@
// $Id: JSInterface_IGUIObject.cpp,v 1.5 2004/07/12 15:52:53 philip Exp $
// $Id: JSInterface_IGUIObject.cpp,v 1.6 2004/07/17 17:05:10 philip Exp $
#include "precompiled.h"
@ -71,8 +71,8 @@ JSBool JSI_IGUIObject::getProperty(JSContext* cx, JSObject* obj, jsval id, jsval
EGUISettingType Type;
if (e->GetSettingType(propName, Type) != PS_OK)
{
// Possibly a function, but they should have been individually
// handled above, so complain about it
// Potentially a function, but they should have been
// individually handled above, so complain about it
JS_ReportError(cx, "Invalid GUIObject property '%s'", propName.c_str());
return JS_FALSE;
}
@ -128,6 +128,7 @@ JSBool JSI_IGUIObject::getProperty(JSContext* cx, JSObject* obj, jsval id, jsval
CClientArea area;
GUI<CClientArea>::GetSetting(e, propName, area);
JSObject* obj = JS_NewObject(cx, &JSI_GUISize::JSI_class, NULL, NULL);
#define P(x, y, z) jsval z = INT_TO_JSVAL(area.x.y); JS_SetProperty(cx, obj, #z, &z)
P(pixel, left, left);
P(pixel, top, top);
@ -138,6 +139,7 @@ JSBool JSI_IGUIObject::getProperty(JSContext* cx, JSObject* obj, jsval id, jsval
P(percent, right, rright);
P(percent, bottom, rbottom);
#undef P
*vp = OBJECT_TO_JSVAL(obj);
break;
}

View file

@ -81,12 +81,17 @@ static void DumpMiniDump(HANDLE hFile, PEXCEPTION_POINTERS excpInfo);
static HANDLE hProcess;
static uintptr_t mod_base;
static wchar_t buf[64000]; /* buffer for stack trace */
const int bufsize = 64000;
static wchar_t buf[bufsize]; /* buffer for stack trace */
static wchar_t* pos; /* current pos in buf */
static void out(wchar_t* fmt, ...)
{
// Don't overflow the buffer
if (pos-buf+1000 > bufsize)
return;
va_list args;
va_start(args, fmt);
pos += vswprintf(pos, 1000, fmt, args);
@ -209,6 +214,8 @@ static void print_var(u32 type_idx, uint level, u64 addr)
out(L"{ ");
}
u32 totalelements = elements;
next_element:
/* zero extend to 64 bit (little endian) */
@ -244,8 +251,13 @@ next_element:
addr += len; /* add stride */
elements--;
if(elements == 0)
/* don't display too many elements of huge arrays */
if (totalelements-elements > 32)
out(L" ... }");
else if(elements == 0)
out(L" }");
else
{
out(L", ");
@ -264,15 +276,31 @@ static void dump_sym(u32 type_idx, uint level, u64 addr)
WCHAR* type_name;
if(_SymGetTypeInfo(hProcess, mod_base, type_idx, TI_GET_SYMNAME, &type_name))
{
/* HACK: ignore things that look like member functions */
/* ignore things that look like member functions, because
there's no point in outputting them */
if (wcsstr(type_name, L"::"))
{
LocalFree(type_name);
return;
}
/* indent */
for(uint i = 0; i < level+2; i++)
out(L" ");
out(L"%ls ", type_name);
/* exclude some specific variable types, because
they just fill the stack trace with rubbish */
if (!wcscmp(type_name, L"JSType")
|| !wcscmp(type_name, L"JSVersion")
)
{
LocalFree(type_name);
out(L"\r\n");
return;
}
LocalFree(type_name);
}
@ -378,7 +406,7 @@ static void walk_stack(int skip, wchar_t* out_buf, CONTEXT* override_context = N
bool type_avail = _SymFromAddr != 0;
pos = out_buf;
out(L"\r\nCall stack:\r\n");
out(L"\r\nCall stack:\r\n\r\n");
if(!type_avail)
out(L"warning: older dbghelp.dll loaded; no type information available.\r\n");
@ -623,28 +651,53 @@ static void set_exception_handler()
// the crash log more useful, and takes the responsibility of
// suiciding away from main.cpp.
void abort_timer(); // from wtime.cpp
int debug_main_exception_filter(unsigned int code, struct _EXCEPTION_POINTERS *ep)
{
// If something crashes after we've already crashed (i.e. when shutting
// down everything), don't bother logging it, because the first crash
// is the most important one to fix.
static bool already_crashed = false;
if (already_crashed)
{
return EXCEPTION_EXECUTE_HANDLER;
}
already_crashed = true;
// The timer thread sometimes dies from EXCEPTION_PRIV_INSTRUCTION
// when debugging this exception handler code (which gets quite
// annoying), so kill it before it gets a chance.
__try
{
abort_timer();
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
}
const wchar_t* error = NULL;
// C++ exceptions put a pointer to the exception object
// into ExceptionInformation[1] -- so see if it looks like
// a PSERROR*, and use the relevant message if it is.
try
__try
{
if (ep->ExceptionRecord->NumberParameters == 3)
{
PSERROR* err = (PSERROR*) ep->ExceptionRecord->ExceptionInformation[1];
if (err->magic == 0x50534552)
if (err->magic == 0x45725221)
{
int code = err->code;
error = GetErrorString(code);
}
}
}
catch (...) {
__except (EXCEPTION_EXECUTE_HANDLER)
{
// Presumably it wasn't a PSERROR and resulted in
// accessing some invalid pointers.
// accessing invalid memory locations.
error = NULL;
}
// Try getting nice names for other types of error:
@ -666,7 +719,7 @@ int debug_main_exception_filter(unsigned int code, struct _EXCEPTION_POINTERS *e
case EXCEPTION_FLT_UNDERFLOW: error = L"Float Underflow"; break;
case EXCEPTION_INT_DIVIDE_BY_ZERO: error = L"Integer Divide By Zero"; break;
case EXCEPTION_INT_OVERFLOW: error = L"Integer Overflow"; break;
case EXCEPTION_PRIV_INSTRUCTION: error = L"Private Instruction"; break;
case EXCEPTION_PRIV_INSTRUCTION: error = L"Privileged Instruction"; break;
case EXCEPTION_IN_PAGE_ERROR: error = L"In Page Error"; break;
case EXCEPTION_ILLEGAL_INSTRUCTION: error = L"Illegal Instruction"; break;
case EXCEPTION_NONCONTINUABLE_EXCEPTION:error = L"Noncontinuable Exception"; break;
@ -697,12 +750,25 @@ int debug_main_exception_filter(unsigned int code, struct _EXCEPTION_POINTERS *e
wdisplay_msg(L"0 A.D. failure", message);
debug_write_crashlog("crashlog.txt", errortext, ep->ContextRecord);
__try
{
debug_write_crashlog("crashlog.txt", errortext, ep->ContextRecord);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
wdisplay_msg(L"0 A.D. failure", L"Error generating crash log.");
}
HANDLE hFile = CreateFile("crashlog.dmp", GENERIC_WRITE, FILE_SHARE_WRITE, 0, CREATE_ALWAYS, 0, 0);
DumpMiniDump(hFile, ep);
CloseHandle(hFile);
__try
{
HANDLE hFile = CreateFile("crashlog.dmp", GENERIC_WRITE, FILE_SHARE_WRITE, 0, CREATE_ALWAYS, 0, 0);
DumpMiniDump(hFile, ep);
CloseHandle(hFile);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
wdisplay_msg(L"0 A.D. failure", L"Error generating crash dump.");
}
// Disable memory-leak reporting, because it's going to
// leak like an upside-down bucket when it crashes.
@ -783,7 +849,7 @@ static void DumpMiniDump(HANDLE hFile, PEXCEPTION_POINTERS excpInfo)
// }
}
// From sysdep.h
// Imported from sysdep.cpp
extern wchar_t MicroBuffer[];
extern int MicroBuffer_off;
@ -808,7 +874,7 @@ int debug_write_crashlog(const char* file, wchar_t* header, void* context)
}
fwrite(buf, pos-buf, 2, f);
const wchar_t* footer = L"\r\n\r\nLast known activity:\r\n\r\n";
const wchar_t* footer = L"\r\n====================================\r\n\r\nLast known activity:\r\n\r\n";
fwrite(footer, wcslen(footer), sizeof(wchar_t), f);
fwrite(MicroBuffer, MicroBuffer_off, sizeof(wchar_t), f);
fclose(f);

View file

@ -669,9 +669,21 @@ static int wtime_init()
static int wtime_shutdown()
{
static bool already_shutdown = false;
if (already_shutdown)
return -1;
already_shutdown = true;
return hrt_shutdown();
}
// Called by the crash code to kill the thread,
// because it disrupts debugging.
void abort_timer()
{
wtime_shutdown();
}
void wtime_reset_impl()
{
hrt_override_impl(HRT_DEFAULT, HRT_NONE);

View file

@ -98,7 +98,7 @@ JSBool JSI_Vector3D::setProperty( JSContext* cx, JSObject* obj, jsval id, jsval*
case component_z: vectorData->Z = (float)g_ScriptingHost.ValueToDouble( *vp ); break;
}
}
catch (...)
catch (PSERROR_Scripting_ConversionFailed)
{
JS_ReportError(cx, "Invalid parameter value for Vector3D");
return( JS_FALSE );
@ -126,7 +126,7 @@ JSBool JSI_Vector3D::construct( JSContext* cx, JSObject* obj, uintN argc, jsval*
JS_SetPrivate( cx, obj, new Vector3D_Info( x, y, z ) );
return( JS_TRUE );
}
catch (...)
catch (PSERROR_Scripting_ConversionFailed)
{
// Invalid input (i.e. can't be coerced into doubles) - fail
JS_ReportError( cx, "Invalid parameters to Vector3D constructor" );

View file

@ -5,20 +5,76 @@
// Slightly hacky section to redeclare things that are declared
// elsewhere - trust the compiler to handle them identically
class PSERROR_GUI : public PSERROR {};
class PSERROR_Scripting : public PSERROR {};
class PSERROR_Scripting_DefineType : public PSERROR_Scripting {};
class PSERROR_Scripting_LoadFile : public PSERROR_Scripting {};
class PSERROR_Xeromyces : public PSERROR {};
class PSERROR_GUI_JSOpenFailed : public PSERROR_GUI { public: PSERROR_GUI_JSOpenFailed(); };
class PSERROR_GUI_TextureLoadFailed : public PSERROR_GUI { public: PSERROR_GUI_TextureLoadFailed(); };
class PSERROR_Scripting_CallFunctionFailed : public PSERROR_Scripting { public: PSERROR_Scripting_CallFunctionFailed(); };
class PSERROR_Scripting_ContextCreationFailed : public PSERROR_Scripting { public: PSERROR_Scripting_ContextCreationFailed(); };
class PSERROR_Scripting_ConversionFailed : public PSERROR_Scripting { public: PSERROR_Scripting_ConversionFailed(); };
class PSERROR_Scripting_CreateObjectFailed : public PSERROR_Scripting { public: PSERROR_Scripting_CreateObjectFailed(); };
class PSERROR_Scripting_DefineConstantFailed : public PSERROR_Scripting { public: PSERROR_Scripting_DefineConstantFailed(); };
class PSERROR_Scripting_DefineType_AlreadyExists : public PSERROR_Scripting_DefineType { public: PSERROR_Scripting_DefineType_AlreadyExists(); };
class PSERROR_Scripting_DefineType_CreationFailed : public PSERROR_Scripting_DefineType { public: PSERROR_Scripting_DefineType_CreationFailed(); };
class PSERROR_Scripting_GlobalObjectCreationFailed : public PSERROR_Scripting { public: PSERROR_Scripting_GlobalObjectCreationFailed(); };
class PSERROR_Scripting_LoadFile_EvalErrors : public PSERROR_Scripting_LoadFile { public: PSERROR_Scripting_LoadFile_EvalErrors(); };
class PSERROR_Scripting_LoadFile_OpenFailed : public PSERROR_Scripting_LoadFile { public: PSERROR_Scripting_LoadFile_OpenFailed(); };
class PSERROR_Scripting_NativeFunctionSetupFailed : public PSERROR_Scripting { public: PSERROR_Scripting_NativeFunctionSetupFailed(); };
class PSERROR_Scripting_RegisterFunctionFailed : public PSERROR_Scripting { public: PSERROR_Scripting_RegisterFunctionFailed(); };
class PSERROR_Scripting_RuntimeCreationFailed : public PSERROR_Scripting { public: PSERROR_Scripting_RuntimeCreationFailed(); };
class PSERROR_Scripting_StandardClassSetupFailed : public PSERROR_Scripting { public: PSERROR_Scripting_StandardClassSetupFailed(); };
class PSERROR_Scripting_TypeDoesNotExist : public PSERROR_Scripting { public: PSERROR_Scripting_TypeDoesNotExist(); };
class PSERROR_Xeromyces_XMLOpenFailed : public PSERROR_Xeromyces { public: PSERROR_Xeromyces_XMLOpenFailed(); };
class PSERROR_Xeromyces_XMLParseError : public PSERROR_Xeromyces { public: PSERROR_Xeromyces_XMLParseError(); };
// The relevant bits of this file:
PSERROR_Xeromyces_XMLOpenFailed::PSERROR_Xeromyces_XMLOpenFailed() { magic=0x50534552; code=0; }
PSERROR_Xeromyces_XMLParseError::PSERROR_Xeromyces_XMLParseError() { magic=0x50534552; code=1; }
PSERROR_GUI_JSOpenFailed::PSERROR_GUI_JSOpenFailed() { magic=0x45725221; code=0; }
PSERROR_GUI_TextureLoadFailed::PSERROR_GUI_TextureLoadFailed() { magic=0x45725221; code=1; }
PSERROR_Scripting_DefineType_AlreadyExists::PSERROR_Scripting_DefineType_AlreadyExists() { magic=0x45725221; code=2; }
PSERROR_Scripting_DefineType_CreationFailed::PSERROR_Scripting_DefineType_CreationFailed() { magic=0x45725221; code=3; }
PSERROR_Scripting_LoadFile_EvalErrors::PSERROR_Scripting_LoadFile_EvalErrors() { magic=0x45725221; code=4; }
PSERROR_Scripting_LoadFile_OpenFailed::PSERROR_Scripting_LoadFile_OpenFailed() { magic=0x45725221; code=5; }
PSERROR_Scripting_CallFunctionFailed::PSERROR_Scripting_CallFunctionFailed() { magic=0x45725221; code=6; }
PSERROR_Scripting_ContextCreationFailed::PSERROR_Scripting_ContextCreationFailed() { magic=0x45725221; code=7; }
PSERROR_Scripting_ConversionFailed::PSERROR_Scripting_ConversionFailed() { magic=0x45725221; code=8; }
PSERROR_Scripting_CreateObjectFailed::PSERROR_Scripting_CreateObjectFailed() { magic=0x45725221; code=9; }
PSERROR_Scripting_DefineConstantFailed::PSERROR_Scripting_DefineConstantFailed() { magic=0x45725221; code=10; }
PSERROR_Scripting_GlobalObjectCreationFailed::PSERROR_Scripting_GlobalObjectCreationFailed() { magic=0x45725221; code=11; }
PSERROR_Scripting_NativeFunctionSetupFailed::PSERROR_Scripting_NativeFunctionSetupFailed() { magic=0x45725221; code=12; }
PSERROR_Scripting_RegisterFunctionFailed::PSERROR_Scripting_RegisterFunctionFailed() { magic=0x45725221; code=13; }
PSERROR_Scripting_RuntimeCreationFailed::PSERROR_Scripting_RuntimeCreationFailed() { magic=0x45725221; code=14; }
PSERROR_Scripting_StandardClassSetupFailed::PSERROR_Scripting_StandardClassSetupFailed() { magic=0x45725221; code=15; }
PSERROR_Scripting_TypeDoesNotExist::PSERROR_Scripting_TypeDoesNotExist() { magic=0x45725221; code=16; }
PSERROR_Xeromyces_XMLOpenFailed::PSERROR_Xeromyces_XMLOpenFailed() { magic=0x45725221; code=17; }
PSERROR_Xeromyces_XMLParseError::PSERROR_Xeromyces_XMLParseError() { magic=0x45725221; code=18; }
const wchar_t* GetErrorString(int code)
{
switch (code)
{
case 0: return L"Xeromyces_XMLOpenFailed"; break;
case 1: return L"Xeromyces_XMLParseError"; break;
case 0: return L"GUI_JSOpenFailed"; break;
case 1: return L"GUI_TextureLoadFailed"; break;
case 2: return L"Scripting_DefineType_AlreadyExists"; break;
case 3: return L"Scripting_DefineType_CreationFailed"; break;
case 4: return L"Scripting_LoadFile_EvalErrors"; break;
case 5: return L"Scripting_LoadFile_OpenFailed"; break;
case 6: return L"Scripting_CallFunctionFailed"; break;
case 7: return L"Scripting_ContextCreationFailed"; break;
case 8: return L"Scripting_ConversionFailed"; break;
case 9: return L"Scripting_CreateObjectFailed"; break;
case 10: return L"Scripting_DefineConstantFailed"; break;
case 11: return L"Scripting_GlobalObjectCreationFailed"; break;
case 12: return L"Scripting_NativeFunctionSetupFailed"; break;
case 13: return L"Scripting_RegisterFunctionFailed"; break;
case 14: return L"Scripting_RuntimeCreationFailed"; break;
case 15: return L"Scripting_StandardClassSetupFailed"; break;
case 16: return L"Scripting_TypeDoesNotExist"; break;
case 17: return L"Xeromyces_XMLOpenFailed"; break;
case 18: return L"Xeromyces_XMLParseError"; break;
}
return L"Unrecognised error";
}

View file

@ -6,8 +6,9 @@
class PSERROR
{
public:
int magic; // = 0x50534552, so the exception handler can recognise that it's a PSERROR
int code;
int magic; // = 0x45725221, so the exception handler can recognise
// that it's a PSERROR and not some other random object.
int code; // unique (but arbitrary) code, for translation tables etc
};
#define ERROR_GROUP(a,b) class a##_##b : public a {}

View file

@ -1,4 +1,4 @@
/* $Id: Xeromyces.h,v 1.3 2004/07/15 19:08:28 philip Exp $
/* $Id: Xeromyces.h,v 1.4 2004/07/17 17:06:21 philip Exp $
Xeromyces file-loading interface.
Automatically creates and caches relatively
@ -25,13 +25,12 @@ public:
~CXeromyces();
// Load from an XML file (with invisible XMB caching).
// Throws a const char* if stuff breaks.
// Throws a PSERROR_Xeromyces upon failure.
void Load(const char* filename);
// Call once when shutting down the program.
// Call once when shutting down the program, to unload Xerces.
static void Terminate();
private:
bool ReadXMBFile(const char* filename, bool CheckCRC, unsigned long CRC);

View file

@ -85,7 +85,7 @@ JSBool getEntityByHandle( JSContext* context, JSObject* globalObject, unsigned i
{
handle = g_ScriptingHost.ValueToInt( argv[0] );
}
catch( ... )
catch( PSERROR_Scripting_ConversionFailed )
{
*rval = JSVAL_NULL;
return( JS_TRUE );
@ -110,7 +110,7 @@ JSBool getEntityTemplate( JSContext* context, JSObject* globalObject, unsigned i
{
templateName = g_ScriptingHost.ValueToString( argv[0] );
}
catch( ... )
catch( PSERROR_Scripting_ConversionFailed )
{
*rval = JSVAL_NULL;
return( JS_TRUE );

View file

@ -41,36 +41,26 @@ ScriptingHost::ScriptingHost() : m_RunTime(NULL), m_Context(NULL), m_GlobalObjec
{
m_RunTime = JS_NewRuntime(RUNTIME_MEMORY_ALLOWANCE);
if (m_RunTime == NULL)
{
throw (std::string("ScriptingHost: Failed to create JavaScript runtime"));
}
if (m_RunTime == NULL)
throw PSERROR_Scripting_RuntimeCreationFailed();
m_Context = JS_NewContext(m_RunTime, STACK_CHUNK_SIZE);
if (m_Context == NULL)
{
throw (std::string("ScriptingHost: Failed to create JavaScript context"));
}
if (m_Context == NULL)
throw PSERROR_Scripting_ContextCreationFailed();
JS_SetErrorReporter(m_Context, ScriptingHost::ErrorReporter);
m_GlobalObject = JS_NewObject(m_Context, &GlobalClass, NULL, NULL);
if (m_GlobalObject == NULL)
{
throw (std::string("ScriptingHost: Failed to create global object"));
}
throw PSERROR_Scripting_GlobalObjectCreationFailed();
if (JS_InitStandardClasses(m_Context, m_GlobalObject) == JSVAL_FALSE)
{
throw (std::string("ScriptingHost: Failed to init standard classes"));
}
throw PSERROR_Scripting_StandardClassSetupFailed();
if (JS_DefineFunctions(m_Context, m_GlobalObject, ScriptFunctionTable) == JS_FALSE)
{
throw (std::string("ScriptingHost: Failed to setup native functions"));
}
throw PSERROR_Scripting_NativeFunctionSetupFailed();
std::cout << "Scripting environment initialized" << std::endl;
}
@ -103,9 +93,7 @@ void ScriptingHost::LoadScriptFromDisk(const std::string & fileName)
std::ifstream scriptFile(fileName.c_str());
if (scriptFile.is_open() == false)
{
throw (std::string("Could not open file: ") + fileName);
}
throw PSERROR_Scripting_LoadFile_OpenFailed();
while (scriptFile.eof() == false)
{
@ -118,9 +106,7 @@ void ScriptingHost::LoadScriptFromDisk(const std::string & fileName)
JSBool ok = JS_EvaluateScript(m_Context, m_GlobalObject, script.c_str(), (unsigned int)script.length(), fileName.c_str(), 0, &rval);
if (ok == JS_FALSE)
{
throw (std::string("Error loading script from disk: ") + fileName);
}
throw PSERROR_Scripting_LoadFile_EvalErrors();
}
jsval ScriptingHost::CallFunction(const std::string & functionName, jsval * params, int numParams)
@ -130,9 +116,7 @@ jsval ScriptingHost::CallFunction(const std::string & functionName, jsval * para
JSBool ok = JS_CallFunctionName(m_Context, m_GlobalObject, functionName.c_str(), numParams, params, &result);
if (ok == JS_FALSE)
{
throw (std::string("Failure whilst calling script funtion: ") + functionName);
}
throw PSERROR_Scripting_CallFunctionFailed();
return result;
}
@ -153,9 +137,7 @@ void ScriptingHost::RegisterFunction(const std::string & functionName, JSNative
JSFunction * func = JS_DefineFunction(m_Context, m_GlobalObject, functionName.c_str(), function, numArgs, 0);
if (func == NULL)
{
throw (std::string("Could not register function ") + functionName);
}
throw PSERROR_Scripting_RegisterFunctionFailed();
}
void ScriptingHost::DefineConstant(const std::string & name, int value)
@ -167,9 +149,7 @@ void ScriptingHost::DefineConstant(const std::string & name, int value)
NULL, NULL, JSPROP_READONLY);
if (ok == JS_FALSE)
{
throw (std::string("Could not create constant"));
}
throw PSERROR_Scripting_DefineConstantFailed();
}
void ScriptingHost::DefineConstant(const std::string & name, double value)
@ -190,9 +170,7 @@ void ScriptingHost::DefineConstant(const std::string & name, double value)
JSBool ok = JS_DefineConstDoubles(m_Context, m_GlobalObject, spec);
if (ok == JS_FALSE)
{
throw (std::string("Could not create constant"));
}
throw PSERROR_Scripting_DefineConstantFailed();
}
void ScriptingHost::DefineCustomObjectType(JSClass *clasp, JSNative constructor, uintN minArgs, JSPropertySpec *ps, JSFunctionSpec *fs, JSPropertySpec *static_ps, JSFunctionSpec *static_fs)
@ -202,7 +180,7 @@ void ScriptingHost::DefineCustomObjectType(JSClass *clasp, JSNative constructor,
if (m_CustomObjectTypes.find(typeName) != m_CustomObjectTypes.end())
{
// This type already exists
throw std::string("Type already exists");
throw PSERROR_Scripting_DefineType_AlreadyExists();
}
JSObject * obj = JS_InitClass( m_Context, m_GlobalObject, 0,
@ -222,7 +200,7 @@ void ScriptingHost::DefineCustomObjectType(JSClass *clasp, JSNative constructor,
}
else
{
throw std::string("Type creation failed");
throw PSERROR_Scripting_DefineType_CreationFailed();
}
}
@ -231,9 +209,7 @@ JSObject * ScriptingHost::CreateCustomObject(const std::string & typeName)
std::map < std::string, CustomType > ::iterator it = m_CustomObjectTypes.find(typeName);
if (it == m_CustomObjectTypes.end())
{
throw std::string("Tried to create a type that doesn't exist");
}
throw PSERROR_Scripting_TypeDoesNotExist();
return JS_ConstructObject(m_Context, (*it).second.m_Class, (*it).second.m_Object, NULL);
@ -270,9 +246,7 @@ int ScriptingHost::ValueToInt(const jsval value)
JSBool ok = JS_ValueToInt32(m_Context, value, &i);
if (ok == JS_FALSE)
{
throw (std::string("Convert to int failed"));
}
throw PSERROR_Scripting_ConversionFailed();
return i;
}
@ -284,9 +258,7 @@ bool ScriptingHost::ValueToBool(const jsval value)
JSBool ok = JS_ValueToBoolean(m_Context, value, &b);
if (ok == JS_FALSE)
{
throw (std::string("Convert to bool failed"));
}
throw PSERROR_Scripting_ConversionFailed();
return b == JS_TRUE;
}
@ -295,7 +267,11 @@ std::string ScriptingHost::ValueToString(const jsval value)
{
JSString * string = JS_ValueToString(m_Context, value);
return std::string(JS_GetStringBytes(string));
char * bytes = JS_GetStringBytes(string);
if (bytes == NULL)
throw PSERROR_Scripting_ConversionFailed();
return std::string(bytes);
}
double ScriptingHost::ValueToDouble(const jsval value)
@ -305,9 +281,7 @@ double ScriptingHost::ValueToDouble(const jsval value)
JSBool ok = JS_ValueToNumber(m_Context, value, &d);
if (ok == JS_FALSE || !finite( d ) )
{
throw (std::string("Convert to double failed"));
}
throw PSERROR_Scripting_ConversionFailed();
return d;
}

View file

@ -12,6 +12,28 @@
# endif
#endif
ERROR_GROUP(PSERROR, Scripting);
ERROR_TYPE(PSERROR_Scripting, RuntimeCreationFailed);
ERROR_TYPE(PSERROR_Scripting, ContextCreationFailed);
ERROR_TYPE(PSERROR_Scripting, GlobalObjectCreationFailed);
ERROR_TYPE(PSERROR_Scripting, StandardClassSetupFailed);
ERROR_TYPE(PSERROR_Scripting, NativeFunctionSetupFailed);
ERROR_GROUP(PSERROR_Scripting, LoadFile);
ERROR_TYPE(PSERROR_Scripting_LoadFile, OpenFailed);
ERROR_TYPE(PSERROR_Scripting_LoadFile, EvalErrors);
ERROR_TYPE(PSERROR_Scripting, ConversionFailed);
ERROR_TYPE(PSERROR_Scripting, CallFunctionFailed);
ERROR_TYPE(PSERROR_Scripting, RegisterFunctionFailed);
ERROR_TYPE(PSERROR_Scripting, DefineConstantFailed);
ERROR_TYPE(PSERROR_Scripting, CreateObjectFailed);
ERROR_TYPE(PSERROR_Scripting, TypeDoesNotExist);
ERROR_GROUP(PSERROR_Scripting, DefineType);
ERROR_TYPE(PSERROR_Scripting_DefineType, AlreadyExists);
ERROR_TYPE(PSERROR_Scripting_DefineType, CreationFailed);
#include <jsapi.h>
#include <string>

View file

@ -33,8 +33,8 @@ bool CBaseEntity::loadXML( CStr filename )
{
XeroFile.Load(filename);
}
catch (...)
{
catch (PSERROR_Xeromyces) {
// Fail
return false;
}

View file

@ -54,7 +54,7 @@ void CProperty_i32::set( jsval value )
{
*modifier = (float)g_ScriptingHost.ValueToInt( value );
}
catch( ... )
catch( PSERROR_Scripting_ConversionFailed )
{
*modifier = 0;
}
@ -116,7 +116,7 @@ void CProperty_float::set( const jsval value )
{
*modifier = (float)g_ScriptingHost.ValueToDouble( value );
}
catch( ... )
catch( PSERROR_Scripting_ConversionFailed )
{
*modifier = 0.0f;
}
@ -218,7 +218,7 @@ void CProperty_CStr::set( jsval value )
{
*modifier = g_ScriptingHost.ValueToString( value );
}
catch( ... )
catch( PSERROR_Scripting_ConversionFailed )
{
*modifier = CStr();
m_String.clear();

View file

@ -79,7 +79,7 @@ JSBool JSI_Entity::construct( JSContext* cx, JSObject* obj, unsigned int argc, j
{
templateName = g_ScriptingHost.ValueToString( argv[0] );
}
catch( ... )
catch( PSERROR_Scripting_ConversionFailed )
{
*rval = JSVAL_NULL;
return( JS_TRUE );
@ -100,7 +100,7 @@ JSBool JSI_Entity::construct( JSContext* cx, JSObject* obj, unsigned int argc, j
{
orientation = (float)g_ScriptingHost.ValueToDouble( argv[2] );
}
catch( ... )
catch( PSERROR_Scripting_ConversionFailed )
{
orientation = 0.0f;
}