Parcourir la source

Add new function "atexithandler" to register a function to be called at scripting exit.
Also added function to retrieve already registered functions to atexithandler and errorhandler.
Modified the behavior for (INT_MIN/-1) to throw an exception instead of set result to zero.

mingodad il y a 13 ans
Parent
commit
f889b29cc5
5 fichiers modifiés avec 64 ajouts et 7 suppressions
  1. 4 1
      include/squirrel.h
  2. 21 0
      squirrel/sqapi.cpp
  3. 20 1
      squirrel/sqbaselib.cpp
  4. 16 4
      squirrel/sqvm.cpp
  5. 3 1
      squirrel/sqvm.h

+ 4 - 1
include/squirrel.h

@@ -334,7 +334,10 @@ typedef struct tagSQFunctionInfo {
 /*vm*/
 SQUIRREL_API HSQUIRRELVM sq_open(SQInteger initialstacksize);
 SQUIRREL_API HSQUIRRELVM sq_newthread(HSQUIRRELVM friendvm, SQInteger initialstacksize);
-SQUIRREL_API void sq_seterrorhandler(HSQUIRRELVM v);
+SQUIRREL_API void sq_seterrorhandler(HSQUIRRELVM v);
+SQUIRREL_API SQRESULT sq_geterrorhandler(HSQUIRRELVM v);
+SQUIRREL_API void sq_setatexithandler(HSQUIRRELVM v);
+SQUIRREL_API SQRESULT sq_getatexithandler(HSQUIRRELVM v);
 SQUIRREL_API void sq_close(HSQUIRRELVM v);
 SQUIRREL_API void sq_setforeignptr(HSQUIRRELVM v,SQUserPointer p);
 SQUIRREL_API SQUserPointer sq_getforeignptr(HSQUIRRELVM v);

+ 21 - 0
squirrel/sqapi.cpp

@@ -95,6 +95,27 @@ void sq_seterrorhandler(HSQUIRRELVM v)
 	}
 }
 
+SQRESULT sq_geterrorhandler(HSQUIRRELVM v)
+{
+    v->Push(v->_errorhandler);
+	return 1;
+}
+
+void sq_setatexithandler(HSQUIRRELVM v)
+{
+	SQObject o = stack_get(v, -1);
+	if(sq_isclosure(o) || sq_isnativeclosure(o) || sq_isnull(o)) {
+		v->_atexithandler = o;
+		v->Pop();
+	}
+}
+
+SQRESULT sq_getatexithandler(HSQUIRRELVM v)
+{
+    v->Push(v->_atexithandler);
+	return 1;
+}
+
 void sq_setnativedebughook(HSQUIRRELVM v,SQDEBUGHOOK hook)
 {
 	v->_debughook_native = hook;

+ 20 - 1
squirrel/sqbaselib.cpp

@@ -93,6 +93,22 @@ static SQInteger base_seterrorhandler(HSQUIRRELVM v)
 	return 0;
 }
 
+static SQInteger base_geterrorhandler(HSQUIRRELVM v)
+{
+	return sq_geterrorhandler(v);
+}
+
+static SQInteger base_setatexithandler(HSQUIRRELVM v)
+{
+	sq_setatexithandler(v);
+	return 0;
+}
+
+static SQInteger base_getatexithandler(HSQUIRRELVM v)
+{
+	return sq_getatexithandler(v);
+}
+
 static SQInteger base_setdebughook(HSQUIRRELVM v)
 {
 	sq_setdebughook(v);
@@ -318,7 +334,10 @@ static SQInteger base_str_from_chars (HSQUIRRELVM v) {
 
 static SQRegFunction base_funcs[]={
 	//generic
-	{_SC("seterrorhandler"),base_seterrorhandler,2, NULL},
+	{_SC("setatexithandler"),base_setatexithandler,2, _SC(".c")},
+	{_SC("getatexithandler"),base_getatexithandler,1, NULL},
+	{_SC("seterrorhandler"),base_seterrorhandler,2, _SC(".c")},
+	{_SC("geterrorhandler"),base_geterrorhandler,1, NULL},
 	{_SC("setdebughook"),base_setdebughook,2, NULL},
 	{_SC("enabledebuginfo"),base_enabledebuginfo,2, NULL},
 	{_SC("getstackinfos"),base_getstackinfos,2, _SC(".n")},

+ 16 - 4
squirrel/sqvm.cpp

@@ -55,7 +55,7 @@ bool SQVM::BW_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,con
 	switch(tmask) { \
 		case OT_INTEGER: { SQInteger i1 = _integer(o1); SQInteger i2 = _integer(o2);\
             if(i2 == 0) { Raise_Error(err); SQ_THROW(); } \
-            else if(i2 == -1 && i1 == INT_MIN) { trg = 0; break; }\
+            else if(i2 == -1 && i1 == INT_MIN) { Raise_Error(_SC("integer overflow")); SQ_THROW(); }\
             trg = i1 op i2; } break;\
 		case (OT_FLOAT|OT_INTEGER): \
 		case (OT_FLOAT): trg = tofloat(o1) op tofloat(o2); break;\
@@ -75,7 +75,7 @@ bool SQVM::ARITH_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,
 			case '-': res = i1 - i2; break;
 			case '/':
                     if(i2 == 0) { Raise_Error(_SC("division by zero")); return false; }
-                    else if(i2 == -1 && i1 == INT_MIN) { res = 0; break; }
+                    else if(i2 == -1 && i1 == INT_MIN) { Raise_Error(_SC("integer overflow")); return false; }
 					res = i1 / i2;
 					break;
 			case '*': res = i1 * i2; break;
@@ -123,7 +123,8 @@ SQVM::SQVM(SQSharedState *ss)
 	_nmetamethodscall = 0;
 	_lasterror.Null();
 	memset(&_lasterror_stackinfo, 0, sizeof(SQStackInfos));
-	_errorhandler.Null();
+	_errorhandler.Null();
+	_atexithandler.Null();
 	_debughook = false;
 	_debughook_native = NULL;
 	_debughook_closure.Null();
@@ -133,12 +134,14 @@ SQVM::SQVM(SQSharedState *ss)
 }
 
 void SQVM::Finalize()
-{
+{
+    CallAtExitHandler();
     _sharedstate->CallDelayedReleaseHooks(this);
 	if(_openouters) CloseOuters(&_stack._vals[0]);
 	_roottable.Null();
 	_lasterror.Null();
 	_errorhandler.Null();
+	_atexithandler.Null();
 	_debughook = false;
 	_debughook_native = NULL;
 	_debughook_closure.Null();
@@ -1117,6 +1120,15 @@ void SQVM::CallErrorHandler(SQObjectPtr &error)
 	}
 }
 
+void SQVM::CallAtExitHandler()
+{
+	if(type(_atexithandler) != OT_NULL) {
+		SQObjectPtr out;
+		Push(_roottable);
+		Call(_atexithandler, 1, _top-1, out,SQFalse);
+		Pop(1);
+	}
+}
 
 void SQVM::CallDebugHook(SQInteger type,SQInteger forcedline)
 {

+ 3 - 1
squirrel/sqvm.h

@@ -64,7 +64,8 @@ public:
 	SQRESULT Suspend();
 
 	void CallDebugHook(SQInteger type,SQInteger forcedline=0);
-	void CallErrorHandler(SQObjectPtr &e);
+	void CallErrorHandler(SQObjectPtr &e);
+	void CallAtExitHandler();
 	bool Get(const SQObjectPtr &self, const SQObjectPtr &key, SQObjectPtr &dest, bool raw, SQInteger selfidx);
 	SQInteger FallBackGet(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest);
 	bool InvokeDefaultDelegate(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest);
@@ -152,6 +153,7 @@ public:
 	SQObjectPtr _lasterror;
 	SQStackInfos _lasterror_stackinfo;
 	SQObjectPtr _errorhandler;
+	SQObjectPtr _atexithandler;
 
 	bool _debughook;
 	SQDEBUGHOOK _debughook_native;