[Scummvm-cvs-logs] SF.net SVN: scummvm:[42592] scummvm/trunk/engines/agos

fingolfin at users.sourceforge.net fingolfin at users.sourceforge.net
Sat Jul 18 17:12:56 CEST 2009


Revision: 42592
          http://scummvm.svn.sourceforge.net/scummvm/?rev=42592&view=rev
Author:   fingolfin
Date:     2009-07-18 15:12:54 +0000 (Sat, 18 Jul 2009)

Log Message:
-----------
AGOS: Get rid of one setjmp in PN code (needs testing)

Modified Paths:
--------------
    scummvm/trunk/engines/agos/agos.h
    scummvm/trunk/engines/agos/pn.cpp
    scummvm/trunk/engines/agos/script_pn.cpp

Modified: scummvm/trunk/engines/agos/agos.h
===================================================================
--- scummvm/trunk/engines/agos/agos.h	2009-07-18 15:11:19 UTC (rev 42591)
+++ scummvm/trunk/engines/agos/agos.h	2009-07-18 15:12:54 UTC (rev 42592)
@@ -1265,21 +1265,7 @@
 
 #ifdef ENABLE_PN
 class AGOSEngine_PN : public AGOSEngine {
-	struct StackFrame {
-		StackFrame *nextframe;
-		int16 flag[6];
-		int16 param[8];
-		int16 classnum;
-		uint8 *linpos;
-		uint8 *lbase;
-		int16 ll;
-		int16 linenum;
-		int16 process;
-		jmp_buf *savearea;
-		StackFrame() { memset(this, 0, sizeof(*this)); }
-	};
 
-
 	virtual Common::Error go();
 	void demoSeq();
 	void introSeq();
@@ -1358,8 +1344,30 @@
 	void opn_opcode62();
 	void opn_opcode63();
 
+protected:
+	struct StackFrame {
+		StackFrame *nextframe;
+		int16 flag[6];
+		int16 param[8];
+		int16 classnum;
+		uint8 *linpos;
+		uint8 *lbase;
+		int16 ll;
+		int16 linenum;
+		int16 process;
+		int tagOfParentDoline;	///< tag of the doline "instance" to which this StackFrame belongs
+		StackFrame() { memset(this, 0, sizeof(*this)); }
+	};
+
+
 	StackFrame *_stackbase;
 
+	int _tagOfActiveDoline;	///< tag of the active doline "instance"
+	int _dolineReturnVal;
+
+	jmp_buf _loadfail;
+
+
 	byte *_dataBase, *_textBase;
 	uint32 _dataBaseSize, _textBaseSize;
 
@@ -1404,8 +1412,6 @@
 	int _linembr;
 	uint8 *_linebase;
 	uint8 *_workptr;
-	jmp_buf *_cjmpbuff;
-	jmp_buf _loadfail;
 
 	uint16 getptr(uint32 pos);
 	uint32 getlong(uint32 pos);
@@ -1429,7 +1435,6 @@
 
 	void addstack(int type);
 	void dumpstack();
-	void junkstack();
 	void popstack(int type);
 	void funccpy(int *store);
 	void funcentry(int *storestore, int procn);

Modified: scummvm/trunk/engines/agos/pn.cpp
===================================================================
--- scummvm/trunk/engines/agos/pn.cpp	2009-07-18 15:11:19 UTC (rev 42591)
+++ scummvm/trunk/engines/agos/pn.cpp	2009-07-18 15:12:54 UTC (rev 42592)
@@ -35,6 +35,10 @@
 AGOSEngine_PN::AGOSEngine_PN(OSystem *system)
 	: AGOSEngine(system) {
 
+	_stackbase = 0;
+	_tagOfActiveDoline = 0;
+	_dolineReturnVal = 0;
+
 	_dataBase = 0;
 	_dataBaseSize = 0;
 	_textBase = 0;
@@ -70,7 +74,7 @@
 	_objects = 0;
 	_objectCountS = 0;
 
-        _bp = 0;
+	_bp = 0;
 	_xofs = 0;
 	_havinit = 0;
 	_seed = 0;
@@ -84,16 +88,12 @@
 
 	_linebase = 0;
 	_workptr = 0;
-
-	_cjmpbuff = NULL;
 }
 
 AGOSEngine_PN::~AGOSEngine_PN() {
 	free(_dataBase);
 	free(_textBase);
 
-	free(_cjmpbuff);
-	free(_stackbase);
 }
 
 const byte egaPalette[48] = {

Modified: scummvm/trunk/engines/agos/script_pn.cpp
===================================================================
--- scummvm/trunk/engines/agos/script_pn.cpp	2009-07-18 15:11:19 UTC (rev 42591)
+++ scummvm/trunk/engines/agos/script_pn.cpp	2009-07-18 15:12:54 UTC (rev 42592)
@@ -324,8 +324,8 @@
 	// That value then is returned to actCallD, which once again
 	// returns it. In the end, this amounts to a setScriptReturn(true)
 	// (but possibly in a different level than the current one).
-	longjmp(*(_stackbase->savearea), 2);
-	setScriptReturn(false);
+	_dolineReturnVal = 2;
+	_tagOfActiveDoline = _stackbase->tagOfParentDoline;
 }
 
 void AGOSEngine_PN::opn_opcode25() {
@@ -334,13 +334,13 @@
 	// That value then is returned to actCallD, which once again
 	// returns it. In the end, this amounts to a setScriptReturn(false)
 	// (but possibly in a different level than the current one).
-	longjmp(*(_stackbase->savearea), 1);
-	setScriptReturn(false);
+	_dolineReturnVal = 1;
+	_tagOfActiveDoline = _stackbase->tagOfParentDoline;
 }
 
 void AGOSEngine_PN::opn_opcode26() {
 	while ((_stackbase != NULL) && (_stackbase->classnum != kJmpClassNum))
-		junkstack();
+		dumpstack();
 	dumpstack();
 	setScriptReturn(true);
 }
@@ -353,16 +353,16 @@
 
 void AGOSEngine_PN::opn_opcode28() {
 	addstack(varval());
-	_stackbase->savearea = _cjmpbuff;
+	_stackbase->tagOfParentDoline = _tagOfActiveDoline;
 	setScriptReturn(false);
 }
 
 void AGOSEngine_PN::opn_opcode29() {
 	popstack(varval());
-	// Jump back to the last doline indicated by the top stackfram.
+	// Jump back to the last doline indicated by the top stackframe.
 	// The -1 tells it to simply go on with its business.
-	longjmp(*(_stackbase->savearea), -1);
-	setScriptReturn(false);
+	_dolineReturnVal = -1;
+	_tagOfActiveDoline = _stackbase->tagOfParentDoline;
 }
 
 void AGOSEngine_PN::opn_opcode30() {
@@ -520,19 +520,32 @@
 }
 
 void AGOSEngine_PN::opn_opcode40() {
-	setScriptReturn(doaction() | doaction());
+	int a = doaction();
+	if (_dolineReturnVal != 0)
+		return;
+	int b = doaction();
+	setScriptReturn(a | b);
 }
 
 void AGOSEngine_PN::opn_opcode41() {
-	setScriptReturn(doaction() & doaction());
+	int a = doaction();
+	if (_dolineReturnVal != 0)
+		return;
+	int b = doaction();
+	setScriptReturn(a & b);
 }
 
 void AGOSEngine_PN::opn_opcode42() {
-	setScriptReturn(doaction() ^ doaction());
+	int a = doaction();
+	if (_dolineReturnVal != 0)
+		return;
+	int b = doaction();
+	setScriptReturn(a ^ b);
 }
 
 void AGOSEngine_PN::opn_opcode43() {
-	setScriptReturn(!(doaction()));
+	int a = doaction();
+	setScriptReturn(!a);
 }
 
 void AGOSEngine_PN::opn_opcode44() {
@@ -874,41 +887,14 @@
 }
 
 int AGOSEngine_PN::doline(int needsave) {
+	assert(!_stackbase == !needsave);
+
 	int x;
-	jmp_buf *old_jmpbuf = NULL;
-	jmp_buf *mybuf;
+	int myTag = ++_tagOfActiveDoline;	// Obtain a unique tag for this doline invocation
+	_dolineReturnVal = 0;
 
-	mybuf = (jmp_buf *)malloc(sizeof(jmp_buf));
-	if (mybuf == NULL)
-		error("doline: Out of memory - stack overflow");
-
-	x = setjmp(*mybuf);
-	// Looking at the longjmp calls below, x can be -1, 1 or 2
-	// (and of course 0 when it returns directly, as always).
-	if (x > 0) {
-		dumpstack();
-		// Restore the active jmpbuf to its previous value,
-		// then return the longjmp value (will be 2-1=1 or 1-1=0).
-		_cjmpbuff = old_jmpbuf;
-		free((char *)mybuf);
-		return (x - 1);
-	}
-
-	if (x == -1) {
-		// Make this doline instance the active one (again).
-		// This is used to "return" over possibly multiple
-		// layers of nested script invocations.
-		// Kind of like throwing an exception.
-		_cjmpbuff = mybuf;
-		goto carryon;
-	}
-	
-	// Remember the previous active jmpbuf (gets restored 
-	// above when a longjmp with a positive param occurs).
-	old_jmpbuf = _cjmpbuff;
-	_cjmpbuff = mybuf;
 	if (needsave)
-		_stackbase->savearea = mybuf;
+		_stackbase->tagOfParentDoline = myTag;
 
 	do {
 		_linct = ((*_linebase) & 127) - 1;
@@ -919,9 +905,25 @@
 				goto skipln;
 		}
 
-carryon:
 		do {
 			x = doaction();
+
+			if (_dolineReturnVal != 0) {
+				if (_tagOfActiveDoline != myTag)
+					return 0;
+
+				x = _dolineReturnVal;
+				_dolineReturnVal = 0;
+
+				if (x > 0) {
+					dumpstack();
+					// Restore the active jmpbuf to its previous value,
+					// then return the longjmp value (will be 2-1=1 or 1-1=0).
+					_tagOfActiveDoline = myTag - 1;
+					return (x - 1);
+				}
+			}
+
 		} while (x && !shouldQuit());
 
 skipln:
@@ -1063,7 +1065,7 @@
 	StackFrame *a;
 	int i;
 
-	a = (StackFrame *)malloc(sizeof(StackFrame));
+	a = (StackFrame *)calloc(1, sizeof(StackFrame));
 	if (a == NULL)
 		error("addstack: Out of memory - stack overflow");
 
@@ -1093,24 +1095,13 @@
 	_stackbase = a;
 }
 
-void AGOSEngine_PN::junkstack() {
-	StackFrame *a;
-
-	if (_stackbase == NULL)
-		error("junkstack: Stack underflow or unknown longjmp");
-
-	a = _stackbase->nextframe;
-	if (_stackbase->classnum == kJmpClassNum)
-		free((char *)_stackbase->savearea);
-	free((char *)_stackbase);
-	_stackbase = a;
-}
-
 void AGOSEngine_PN::popstack(int type) {
-	int i;
+	int i = 0;
 
-	while ((_stackbase != NULL) && (_stackbase->classnum != type))
-		junkstack();
+	while ((_stackbase != NULL) && (_stackbase->classnum != type)) {
+		dumpstack();
+		++i;
+	}
 
 	if (_stackbase == NULL)
 		error("popstack: Stack underflow or unknown longjmp");


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list