mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-11 04:06:12 +00:00
863 lines
17 KiB
C++
863 lines
17 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
*/
|
|
|
|
#include <string>
|
|
#include "glk/alan2/types.h"
|
|
#include "glk/alan2/exe.h"
|
|
#include "glk/alan2/inter.h"
|
|
#include "glk/alan2/glkio.h"
|
|
#include "glk/alan2/main.h"
|
|
#include "glk/alan2/parse.h"
|
|
#include "glk/alan2/stack.h"
|
|
#include "glk/alan2/sysdep.h"
|
|
|
|
namespace Glk {
|
|
namespace Alan2 {
|
|
|
|
/* PRIVATE DATA */
|
|
|
|
static int pc;
|
|
|
|
|
|
static void if_(Aword v) {
|
|
int lev = 1;
|
|
Aword i;
|
|
|
|
if (!v) {
|
|
/* Skip to next ELSE or ENDIF on same level */
|
|
while (TRUE) {
|
|
i = memory[pc++];
|
|
if (I_CLASS(i) == (Aword)C_STMOP)
|
|
switch (I_OP(i)) {
|
|
case I_ELSE:
|
|
if (lev == 1) return;
|
|
break;
|
|
case I_IF:
|
|
lev++;
|
|
break;
|
|
case I_ENDIF:
|
|
lev--;
|
|
if (lev == 0) return;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void else_() {
|
|
int lev = 1;
|
|
Aword i;
|
|
|
|
while (TRUE) {
|
|
/* Skip to ENDIF on the same level */
|
|
i = memory[pc++];
|
|
if (I_CLASS(i) == (Aword)C_STMOP)
|
|
switch (I_OP(i)) {
|
|
case I_ENDIF:
|
|
lev--;
|
|
if (lev == 0) return;
|
|
break;
|
|
case I_IF:
|
|
lev++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void depstart() {
|
|
/* A DEPSTART was executed so skip across the redundant DEPCASE to
|
|
start at the first expression */
|
|
pc++;
|
|
}
|
|
|
|
static void swap() {
|
|
Aptr v1 = pop();
|
|
Aptr v2 = pop();
|
|
|
|
push(v1);
|
|
push(v2);
|
|
}
|
|
|
|
static void depexec(Aword v) {
|
|
int lev = 1;
|
|
Aword i;
|
|
|
|
if (!v)
|
|
/* The expression was not true, skip to next CASE on the same
|
|
level which could be a DEPCASE or DEPELSE */
|
|
while (TRUE) {
|
|
i = memory[pc++];
|
|
if (I_CLASS(i) == (Aword)C_STMOP)
|
|
switch (I_OP(i)) {
|
|
case I_DEPSTART:
|
|
lev++;
|
|
break;
|
|
case I_DEPEND:
|
|
if (lev == 1) return;
|
|
lev--;
|
|
break;
|
|
case I_DEPCASE:
|
|
case I_DEPELSE:
|
|
if (lev == 1) return;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void depcase() {
|
|
int lev = 1;
|
|
Aword i;
|
|
|
|
/* Skip to end of DEPENDING block (next DEPEND on same level) because
|
|
we have just executed a DEPCASE/DEPELSE statement as a result of a DEPCASE
|
|
catching */
|
|
|
|
while (TRUE) {
|
|
i = memory[pc++];
|
|
if (I_CLASS(i) == (Aword)C_STMOP)
|
|
switch (I_OP(i)) {
|
|
case I_DEPSTART:
|
|
lev++;
|
|
break;
|
|
case I_DEPEND:
|
|
lev--;
|
|
if (lev == 0) return;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void interpret(Aaddr adr) {
|
|
Aaddr oldpc;
|
|
Aword i;
|
|
|
|
if (stpflg) printf("\n++++++++++++++++++++++++++++++++++++++++++++++++++");
|
|
|
|
oldpc = pc;
|
|
pc = adr;
|
|
while (TRUE) {
|
|
if (stpflg) printf("\n%4x: ", pc);
|
|
if (pc > memTop)
|
|
syserr("Interpreting outside program.");
|
|
|
|
i = memory[pc++];
|
|
|
|
switch (I_CLASS(i)) {
|
|
case C_CONST:
|
|
if (stpflg) printf("PUSH \t%5ld", I_OP(i));
|
|
push(I_OP(i));
|
|
break;
|
|
case C_CURVAR:
|
|
switch (I_OP(i)) {
|
|
case V_PARAM:
|
|
if (stpflg) printf("PARAM \t%5ld\t\t(%ld)", top(), params[top() - 1].code);
|
|
push(params[pop() - 1].code);
|
|
break;
|
|
case V_CURLOC:
|
|
if (stpflg) printf("CURLOC \t\t\t(%d)", cur.loc);
|
|
push(cur.loc);
|
|
break;
|
|
case V_CURACT:
|
|
if (stpflg) printf("CURACT \t\t\t(%d)", cur.act);
|
|
push(cur.act);
|
|
break;
|
|
case V_CURVRB:
|
|
if (stpflg) printf("CURVRB \t\t\t(%d)", cur.vrb);
|
|
push(cur.vrb);
|
|
break;
|
|
case V_SCORE:
|
|
if (stpflg) printf("CURSCORE \t\t\t(%d)", cur.score);
|
|
push(cur.score);
|
|
break;
|
|
default:
|
|
syserr("Unknown CURVAR instruction.");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case C_STMOP:
|
|
switch (I_OP(i)) {
|
|
case I_PRINT: {
|
|
Aptr fpos, len;
|
|
fpos = pop();
|
|
len = pop();
|
|
if (stpflg) {
|
|
printf("PRINT \t%5ld, %5ld\t\"", fpos, len);
|
|
col = 34; /* To format it better! */
|
|
}
|
|
print(fpos, len);
|
|
if (stpflg)
|
|
printf("\"");
|
|
break;
|
|
}
|
|
case I_SYSTEM: {
|
|
Aptr fpos, len;
|
|
fpos = pop();
|
|
len = pop();
|
|
if (stpflg) {
|
|
printf("SYSTEM \t%5ld, %5ld\t\"", fpos, len);
|
|
col = 34; /* To format it better! */
|
|
}
|
|
sys(fpos, len);
|
|
break;
|
|
}
|
|
case I_GETSTR: {
|
|
Aptr fpos, len;
|
|
fpos = pop();
|
|
len = pop();
|
|
if (stpflg)
|
|
printf("GETSTR\t%5ld, %5ld", fpos, len);
|
|
getstr(fpos, len);
|
|
if (stpflg)
|
|
printf("\t(%ld)", top());
|
|
break;
|
|
}
|
|
case I_QUIT: {
|
|
if (stpflg)
|
|
printf("QUIT");
|
|
quit();
|
|
break;
|
|
}
|
|
case I_LOOK: {
|
|
if (stpflg)
|
|
printf("LOOK");
|
|
look();
|
|
break;
|
|
}
|
|
case I_SAVE: {
|
|
if (stpflg)
|
|
printf("SAVE");
|
|
save();
|
|
break;
|
|
}
|
|
case I_RESTORE: {
|
|
if (stpflg)
|
|
printf("RESTORE");
|
|
restore();
|
|
break;
|
|
}
|
|
case I_RESTART: {
|
|
if (stpflg)
|
|
printf("RESTART");
|
|
restart();
|
|
break;
|
|
}
|
|
case I_LIST: {
|
|
Aptr cnt;
|
|
cnt = pop();
|
|
if (stpflg)
|
|
printf("LIST \t%5ld", cnt);
|
|
list(cnt);
|
|
break;
|
|
}
|
|
case I_EMPTY: {
|
|
Aptr cnt, whr;
|
|
cnt = pop();
|
|
whr = pop();
|
|
if (stpflg)
|
|
printf("EMPTY \t%5ld, %5ld", cnt, whr);
|
|
empty(cnt, whr);
|
|
break;
|
|
}
|
|
case I_SCORE: {
|
|
Aptr sc;
|
|
sc = pop();
|
|
if (stpflg)
|
|
printf("SCORE \t%5ld\t\t(%ld)", sc, scores[sc - 1]);
|
|
score(sc);
|
|
break;
|
|
}
|
|
case I_VISITS: {
|
|
Aptr v;
|
|
v = pop();
|
|
if (stpflg)
|
|
printf("VISITS \t%5ld", v);
|
|
visits(v);
|
|
break;
|
|
}
|
|
case I_SCHEDULE: {
|
|
Aptr evt, whr, aft;
|
|
evt = pop();
|
|
whr = pop();
|
|
aft = pop();
|
|
if (stpflg)
|
|
printf("SCHEDULE \t%5ld, %5ld, %5ld", evt, whr, aft);
|
|
schedule(evt, whr, aft);
|
|
break;
|
|
}
|
|
case I_CANCEL: {
|
|
Aptr evt;
|
|
evt = pop();
|
|
if (stpflg)
|
|
printf("CANCEL \t%5ld", evt);
|
|
cancl(evt);
|
|
break;
|
|
}
|
|
case I_MAKE: {
|
|
Aptr id, atr, val;
|
|
id = pop();
|
|
atr = pop();
|
|
val = pop();
|
|
if (stpflg) {
|
|
printf("MAKE \t%5ld, %5ld, ", id, atr);
|
|
if (val) printf("TRUE");
|
|
else printf("FALSE");
|
|
}
|
|
make(id, atr, val);
|
|
break;
|
|
}
|
|
case I_SET: {
|
|
Aptr id, atr, val;
|
|
id = pop();
|
|
atr = pop();
|
|
val = pop();
|
|
if (stpflg) {
|
|
printf("SET \t%5ld, %5ld, %5ld", id, atr, val);
|
|
}
|
|
set(id, atr, val);
|
|
break;
|
|
}
|
|
case I_STRSET: {
|
|
Aptr id, atr, str;
|
|
id = pop();
|
|
atr = pop();
|
|
str = pop();
|
|
if (stpflg) {
|
|
printf("STRSET\t%5ld, %5ld, %5ld", id, atr, str);
|
|
}
|
|
setstr(id, atr, str);
|
|
break;
|
|
}
|
|
case I_INCR: {
|
|
Aptr id, atr, step;
|
|
id = pop();
|
|
atr = pop();
|
|
step = pop();
|
|
if (stpflg) {
|
|
printf("INCR\t%5ld, %5ld, %5ld", id, atr, step);
|
|
}
|
|
incr(id, atr, step);
|
|
break;
|
|
}
|
|
case I_DECR: {
|
|
Aptr id, atr, step;
|
|
id = pop();
|
|
atr = pop();
|
|
step = pop();
|
|
if (stpflg) {
|
|
printf("DECR\t%5ld, %5ld, %5ld", id, atr, step);
|
|
}
|
|
decr(id, atr, step);
|
|
break;
|
|
}
|
|
case I_ATTRIBUTE: {
|
|
Aptr id, atr;
|
|
id = pop();
|
|
atr = pop();
|
|
if (stpflg)
|
|
printf("ATTRIBUTE %5ld, %5ld", id, atr);
|
|
push(attribute(id, atr));
|
|
if (stpflg)
|
|
printf("\t(%ld)", top());
|
|
break;
|
|
}
|
|
case I_STRATTR: {
|
|
Aptr id, atr;
|
|
id = pop();
|
|
atr = pop();
|
|
if (stpflg)
|
|
printf("STRATTR \t%5ld, %5ld", id, atr);
|
|
push(strattr(id, atr));
|
|
if (stpflg)
|
|
printf("\t(%ld)", top());
|
|
break;
|
|
}
|
|
case I_LOCATE: {
|
|
Aptr id, whr;
|
|
id = pop();
|
|
whr = pop();
|
|
if (stpflg)
|
|
printf("LOCATE \t%5ld, %5ld", id, whr);
|
|
locate(id, whr);
|
|
break;
|
|
}
|
|
case I_WHERE: {
|
|
Aptr id;
|
|
id = pop();
|
|
if (stpflg)
|
|
printf("WHERE \t%5ld", id);
|
|
push(where(id));
|
|
if (stpflg)
|
|
printf("\t\t(%ld)", top());
|
|
break;
|
|
}
|
|
case I_HERE: {
|
|
Aptr id;
|
|
id = pop();
|
|
if (stpflg)
|
|
printf("HERE \t%5ld", id);
|
|
push(isHere(id));
|
|
if (stpflg)
|
|
if (top()) printf("\t(TRUE)");
|
|
else printf("\t(FALSE)");
|
|
break;
|
|
}
|
|
case I_NEAR: {
|
|
Aptr id;
|
|
id = pop();
|
|
if (stpflg)
|
|
printf("NEAR \t%5ld", id);
|
|
push(isNear(id));
|
|
if (stpflg)
|
|
if (top()) printf("\t(TRUE)");
|
|
else printf("\t(FALSE)");
|
|
break;
|
|
}
|
|
case I_USE: {
|
|
Aptr act, scr;
|
|
act = pop();
|
|
scr = pop();
|
|
if (stpflg)
|
|
printf("USE \t%5ld, %5ld", act, scr);
|
|
use(act, scr);
|
|
break;
|
|
}
|
|
case I_IN: {
|
|
Aptr obj, cnt;
|
|
obj = pop();
|
|
cnt = pop();
|
|
if (stpflg)
|
|
printf("IN \t%5ld, %5ld ", obj, cnt);
|
|
push(in(obj, cnt));
|
|
if (stpflg)
|
|
if (top()) printf("\t(TRUE)");
|
|
else printf("\t(FALSE)");
|
|
break;
|
|
}
|
|
case I_DESCRIBE: {
|
|
Aptr id;
|
|
id = pop();
|
|
if (stpflg) {
|
|
printf("DESCRIBE \t%5ld\t", id);
|
|
col = 34; /* To format it better! */
|
|
}
|
|
describe(id);
|
|
break;
|
|
}
|
|
case I_SAY: {
|
|
Aptr id;
|
|
id = pop();
|
|
if (stpflg)
|
|
printf("SAY \t%5ld\t\t\"", id);
|
|
say(id);
|
|
if (stpflg)
|
|
printf("\"");
|
|
break;
|
|
}
|
|
case I_SAYINT: {
|
|
Aptr val;
|
|
val = pop();
|
|
if (stpflg)
|
|
printf("SAYINT\t%5ld\t\t\"", val);
|
|
sayint(val);
|
|
if (stpflg)
|
|
printf("\"");
|
|
break;
|
|
}
|
|
case I_SAYSTR: {
|
|
Aptr adr;
|
|
adr = pop();
|
|
if (stpflg)
|
|
printf("SAYSTR\t%5ld\t\t\"", adr);
|
|
saystr((char *)adr);
|
|
if (stpflg)
|
|
printf("\"");
|
|
break;
|
|
}
|
|
case I_IF: {
|
|
Aptr v;
|
|
v = pop();
|
|
if (stpflg) {
|
|
printf("IF \t");
|
|
if (v) printf(" TRUE");
|
|
else printf("FALSE");
|
|
}
|
|
if_(v);
|
|
break;
|
|
}
|
|
case I_ELSE: {
|
|
if (stpflg)
|
|
printf("ELSE");
|
|
else_();
|
|
break;
|
|
}
|
|
case I_ENDIF: {
|
|
if (stpflg)
|
|
printf("ENDIF");
|
|
break;
|
|
}
|
|
case I_AND: {
|
|
Aptr lh, rh;
|
|
if (header->vers[0] == 2 && header->vers[1] == 7) /* Check for 2.7 version */
|
|
swap();
|
|
rh = pop();
|
|
lh = pop();
|
|
if (stpflg) {
|
|
printf("AND \t");
|
|
if (lh) printf("TRUE, ");
|
|
else printf("FALSE, ");
|
|
if (rh) printf("TRUE");
|
|
else printf("FALSE");
|
|
}
|
|
push(lh && rh);
|
|
if (stpflg)
|
|
if (top()) printf("\t(TRUE)");
|
|
else printf("\t(FALSE)");
|
|
break;
|
|
}
|
|
case I_OR: {
|
|
Aptr lh, rh;
|
|
if (header->vers[0] == 2 && header->vers[1] == 7) /* Check for 2.7 version */
|
|
swap();
|
|
rh = pop();
|
|
lh = pop();
|
|
if (stpflg) {
|
|
printf("OR \t");
|
|
if (lh) printf("TRUE, ");
|
|
else printf("FALSE, ");
|
|
if (rh) printf("TRUE");
|
|
else printf("FALSE");
|
|
}
|
|
push(lh || rh);
|
|
if (stpflg)
|
|
if (top()) printf("\t(TRUE)");
|
|
else printf("\t(FALSE)");
|
|
break;
|
|
}
|
|
case I_NE: {
|
|
Aptr lh, rh;
|
|
if (header->vers[0] == 2 && header->vers[1] == 7) /* Check for 2.7 version */
|
|
swap();
|
|
rh = pop();
|
|
lh = pop();
|
|
if (stpflg)
|
|
printf("NE \t%5ld, %5ld", lh, rh);
|
|
push(lh != rh);
|
|
if (stpflg)
|
|
if (top()) printf("\t(TRUE)");
|
|
else printf("\t(FALSE)");
|
|
break;
|
|
}
|
|
case I_EQ: {
|
|
Aptr lh, rh;
|
|
if (header->vers[0] == 2 && header->vers[1] == 7) /* Check for 2.7 version */
|
|
swap();
|
|
rh = pop();
|
|
lh = pop();
|
|
if (stpflg)
|
|
printf("EQ \t%5ld, %5ld", lh, rh);
|
|
push(lh == rh);
|
|
if (stpflg)
|
|
if (top()) printf("\t(TRUE)");
|
|
else printf("\t(FALSE)");
|
|
break;
|
|
}
|
|
case I_STREQ: {
|
|
Aptr lh, rh;
|
|
if (header->vers[0] == 2 && header->vers[1] == 7) /* Check for 2.7 version */
|
|
swap();
|
|
rh = pop();
|
|
lh = pop();
|
|
if (stpflg)
|
|
printf("STREQ \t%5ld, %5ld", lh, rh);
|
|
push(streq((char *)lh, (char *)rh));
|
|
if (stpflg)
|
|
if (top()) printf("\t(TRUE)");
|
|
else printf("\t(FALSE)");
|
|
break;
|
|
}
|
|
case I_STREXACT: {
|
|
Aptr lh, rh;
|
|
if (header->vers[0] == 2 && header->vers[1] == 7) /* Check for 2.7 version */
|
|
swap();
|
|
rh = pop();
|
|
lh = pop();
|
|
if (stpflg)
|
|
printf("STREXACT \t%5ld, %5ld", lh, rh);
|
|
push(strcmp((char *)lh, (char *)rh) == 0);
|
|
if (stpflg)
|
|
if (top()) printf("\t(TRUE)");
|
|
else printf("\t(FALSE)");
|
|
free((void *)lh);
|
|
free((void *)rh);
|
|
break;
|
|
}
|
|
case I_LE: {
|
|
Aint lh, rh;
|
|
if (header->vers[0] == 2 && header->vers[1] == 7) /* Check for 2.7 version */
|
|
swap();
|
|
rh = pop();
|
|
lh = pop();
|
|
if (stpflg)
|
|
printf("LE \t%5ld, %5ld", lh, rh);
|
|
push(lh <= rh);
|
|
if (stpflg)
|
|
if (top()) printf("\t(TRUE)");
|
|
else printf("\t(FALSE)");
|
|
break;
|
|
}
|
|
case I_GE: {
|
|
Aint lh, rh;
|
|
if (header->vers[0] == 2 && header->vers[1] == 7) /* Check for 2.7 version */
|
|
swap();
|
|
rh = pop();
|
|
lh = pop();
|
|
if (stpflg)
|
|
printf("GE \t%5ld, %5ld", lh, rh);
|
|
push(lh >= rh);
|
|
if (stpflg)
|
|
if (top()) printf("\t(TRUE)");
|
|
else printf("\t(FALSE)");
|
|
break;
|
|
}
|
|
case I_LT: {
|
|
Aint lh, rh;
|
|
if (header->vers[0] == 2 && header->vers[1] == 7) /* Check for 2.7 version */
|
|
swap();
|
|
rh = pop();
|
|
lh = pop();
|
|
if (stpflg)
|
|
printf("LT \t%5ld, %5ld", lh, rh);
|
|
push((signed int)lh < (signed int)rh);
|
|
if (stpflg)
|
|
if (top()) printf("\t(TRUE)");
|
|
else printf("\t(FALSE)");
|
|
break;
|
|
}
|
|
case I_GT: {
|
|
Aint lh, rh;
|
|
if (header->vers[0] == 2 && header->vers[1] == 7) /* Check for 2.7 version */
|
|
swap();
|
|
rh = pop();
|
|
lh = pop();
|
|
if (stpflg)
|
|
printf("GT \t%5ld, %5ld", lh, rh);
|
|
push(lh > rh);
|
|
if (stpflg)
|
|
if (top()) printf("\t(TRUE)");
|
|
else printf("\t(FALSE)");
|
|
break;
|
|
}
|
|
case I_PLUS: {
|
|
Aint lh, rh;
|
|
if (header->vers[0] == 2 && header->vers[1] == 7) /* Check for 2.7 version */
|
|
swap();
|
|
rh = pop();
|
|
lh = pop();
|
|
if (stpflg)
|
|
printf("PLUS \t%5ld, %5ld", lh, rh);
|
|
push(lh + rh);
|
|
if (stpflg)
|
|
printf("\t(%ld)", top());
|
|
break;
|
|
}
|
|
case I_MINUS: {
|
|
Aint lh, rh;
|
|
if (header->vers[0] == 2 && header->vers[1] == 7) /* Check for 2.7 version */
|
|
swap();
|
|
rh = pop();
|
|
lh = pop();
|
|
if (stpflg)
|
|
printf("MINUS \t%5ld, %5ld", lh, rh);
|
|
push(lh - rh);
|
|
if (stpflg)
|
|
printf("\t(%ld)", top());
|
|
break;
|
|
}
|
|
case I_MULT: {
|
|
Aint lh, rh;
|
|
if (header->vers[0] == 2 && header->vers[1] == 7) /* Check for 2.7 version */
|
|
swap();
|
|
rh = pop();
|
|
lh = pop();
|
|
if (stpflg)
|
|
printf("MULT \t%5ld, %5ld", lh, rh);
|
|
push(lh * rh);
|
|
if (stpflg)
|
|
printf("\t(%ld)", top());
|
|
break;
|
|
}
|
|
case I_DIV: {
|
|
Aint lh, rh;
|
|
if (header->vers[0] == 2 && header->vers[1] == 7) /* Check for 2.7 version */
|
|
swap();
|
|
rh = pop();
|
|
lh = pop();
|
|
if (stpflg)
|
|
printf("DIV \t%5ld, %5ld", lh, rh);
|
|
push(lh / rh);
|
|
if (stpflg)
|
|
printf("\t(%ld)", top());
|
|
break;
|
|
}
|
|
case I_NOT: {
|
|
Aptr val;
|
|
val = pop();
|
|
if (stpflg) {
|
|
printf("NOT \t");
|
|
if (val) printf("TRUE");
|
|
else printf("FALSE");
|
|
}
|
|
push(!val);
|
|
if (stpflg)
|
|
if (top()) printf("\t\t(TRUE)");
|
|
else printf("\t\t(FALSE)");
|
|
break;
|
|
}
|
|
case I_MAX: {
|
|
Aptr atr, whr;
|
|
atr = pop();
|
|
whr = pop();
|
|
if (stpflg)
|
|
printf("MAX \t%5ld, %5ld", atr, whr);
|
|
push(agrmax(atr, whr));
|
|
if (stpflg)
|
|
printf("\t(%ld)", top());
|
|
break;
|
|
}
|
|
case I_SUM: {
|
|
Aptr atr, whr;
|
|
atr = pop();
|
|
whr = pop();
|
|
if (stpflg)
|
|
printf("SUM \t%5ld, %5ld", atr, whr);
|
|
push(agrsum(atr, whr));
|
|
if (stpflg)
|
|
printf("\t(%ld)", top());
|
|
break;
|
|
}
|
|
case I_COUNT: {
|
|
Aptr whr;
|
|
whr = pop();
|
|
if (stpflg)
|
|
printf("COUNT \t%5ld", whr);
|
|
push(agrcount(whr));
|
|
if (stpflg)
|
|
printf("\t(%ld)", top());
|
|
break;
|
|
}
|
|
case I_RND: {
|
|
Aptr from, to;
|
|
from = pop();
|
|
to = pop();
|
|
if (stpflg)
|
|
printf("RANDOM \t%5ld, %5ld", from, to);
|
|
push(rnd(from, to));
|
|
if (stpflg)
|
|
printf("\t(%ld)", top());
|
|
break;
|
|
}
|
|
case I_BTW: {
|
|
Aint low, high, val;
|
|
high = pop();
|
|
low = pop();
|
|
val = pop();
|
|
if (stpflg)
|
|
printf("BETWEEN \t%5ld, %5ld, %5ld", val, low, high);
|
|
push(btw(val, low, high));
|
|
if (stpflg)
|
|
printf("\t(%ld)", top());
|
|
break;
|
|
}
|
|
case I_CONTAINS: {
|
|
Aptr string, substring;
|
|
substring = pop();
|
|
string = pop();
|
|
if (stpflg)
|
|
printf("CONTAINS \t%5ld, %5ld", string, substring);
|
|
push(contains(string, substring));
|
|
if (stpflg)
|
|
printf("\t(%ld)", top());
|
|
break;
|
|
}
|
|
|
|
case I_DEPSTART:
|
|
if (stpflg)
|
|
printf("DEPSTART");
|
|
depstart();
|
|
break;
|
|
|
|
case I_DEPCASE:
|
|
if (stpflg)
|
|
printf("DEPCASE");
|
|
depcase();
|
|
break;
|
|
|
|
case I_DEPEXEC: {
|
|
Aptr v;
|
|
v = pop();
|
|
if (stpflg) {
|
|
printf("DEPEXEC \t");
|
|
if (v) printf(" TRUE");
|
|
else printf("FALSE");
|
|
}
|
|
depexec(v);
|
|
break;
|
|
}
|
|
|
|
case I_DEPELSE:
|
|
if (stpflg)
|
|
printf("DEPELSE");
|
|
depcase();
|
|
break;
|
|
|
|
case I_DEPEND:
|
|
if (stpflg)
|
|
printf("DEPEND");
|
|
break;
|
|
|
|
case I_RETURN:
|
|
if (stpflg)
|
|
printf("RETURN\n--------------------------------------------------\n");
|
|
pc = oldpc;
|
|
return;
|
|
|
|
default:
|
|
syserr("Unknown STMOP instruction.");
|
|
break;
|
|
}
|
|
if (fail) {
|
|
pc = oldpc;
|
|
return;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
syserr("Unknown instruction class.");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
} // End of namespace Alan2
|
|
} // End of namespace Glk
|