aboutsummaryrefslogtreecommitdiff
path: root/engines/agos/script_pn.cpp
diff options
context:
space:
mode:
authorMax Horn2009-07-18 15:12:54 +0000
committerMax Horn2009-07-18 15:12:54 +0000
commit2250ff1df68bcd37f37ca2d37f5768ff1037219b (patch)
tree4cdc78289f6aae6babe9f34d30af07d572cfe50c /engines/agos/script_pn.cpp
parent24e18ae2154e7affb87368f09d5a4ebf78d2430e (diff)
downloadscummvm-rg350-2250ff1df68bcd37f37ca2d37f5768ff1037219b.tar.gz
scummvm-rg350-2250ff1df68bcd37f37ca2d37f5768ff1037219b.tar.bz2
scummvm-rg350-2250ff1df68bcd37f37ca2d37f5768ff1037219b.zip
AGOS: Get rid of one setjmp in PN code (needs testing)
svn-id: r42592
Diffstat (limited to 'engines/agos/script_pn.cpp')
-rw-r--r--engines/agos/script_pn.cpp117
1 files changed, 54 insertions, 63 deletions
diff --git a/engines/agos/script_pn.cpp b/engines/agos/script_pn.cpp
index 4f9aab2965..116f1e1975 100644
--- a/engines/agos/script_pn.cpp
+++ b/engines/agos/script_pn.cpp
@@ -324,8 +324,8 @@ void AGOSEngine_PN::opn_opcode24() {
// 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 @@ void AGOSEngine_PN::opn_opcode25() {
// 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_opcode27() {
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_opcode39() {
}
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::doaction() {
}
int AGOSEngine_PN::doline(int needsave) {
- int x;
- jmp_buf *old_jmpbuf = NULL;
- jmp_buf *mybuf;
+ assert(!_stackbase == !needsave);
- 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);
- }
+ int x;
+ int myTag = ++_tagOfActiveDoline; // Obtain a unique tag for this doline invocation
+ _dolineReturnVal = 0;
- 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 @@ int AGOSEngine_PN::doline(int needsave) {
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 @@ void AGOSEngine_PN::addstack(int type) {
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 @@ void AGOSEngine_PN::dumpstack() {
_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");