[Scummvm-cvs-logs] SF.net SVN: scummvm: [24935] tools/trunk/descumm6.cpp
fingolfin at users.sourceforge.net
fingolfin at users.sourceforge.net
Wed Dec 27 15:10:20 CET 2006
Revision: 24935
http://scummvm.svn.sourceforge.net/scummvm/?rev=24935&view=rev
Author: fingolfin
Date: 2006-12-27 06:10:18 -0800 (Wed, 27 Dec 2006)
Log Message:
-----------
Objectify StackEnt code
Modified Paths:
--------------
tools/trunk/descumm6.cpp
Modified: tools/trunk/descumm6.cpp
===================================================================
--- tools/trunk/descumm6.cpp 2006-12-27 13:27:11 UTC (rev 24934)
+++ tools/trunk/descumm6.cpp 2006-12-27 14:10:18 UTC (rev 24935)
@@ -58,16 +58,17 @@
*/
+class StackEnt;
-struct StackEnt {
- byte type;
- long data;
- StackEnt *left, *right;
- char *str;
- StackEnt **list;
-};
+const char *getVarName(uint var);
+StackEnt *pop();
-enum {
+
+static int dupindex = 0;
+
+
+
+enum StackEntType {
seInt = 1,
seVar = 2,
seArray = 3,
@@ -117,6 +118,196 @@
"%"
};
+
+
+class StackEnt {
+public:
+ StackEntType type;
+
+public:
+ virtual ~StackEnt() {}
+ virtual char *asText(char *where, bool wantparens = true) const = 0;
+ virtual StackEnt* dup(char *output);
+
+ virtual int getIntVal() const { error("getIntVal call on StackEnt type %d", type); }
+};
+
+class IntStackEnt : public StackEnt {
+ int _val;
+public:
+ IntStackEnt(int val) : _val(val) { type = seInt; }
+ virtual char *asText(char *where, bool wantparens) const {
+ where += sprintf(where, "%d", _val);
+ return where;
+ }
+ virtual StackEnt* dup(char *output) {
+ return new IntStackEnt(_val);
+ }
+ virtual int getIntVal() const { return _val; }
+};
+
+class VarStackEnt : public StackEnt {
+ int _var;
+public:
+ VarStackEnt(int var) : _var(var) { type = seVar; }
+ virtual char *asText(char *where, bool wantparens = true) const {
+ int var;
+ const char *s;
+ if (g_options.scriptVersion == 8) {
+ if (!(_var & 0xF0000000)) {
+ var = _var & 0xFFFFFFF;
+ if ((s = getVarName(var)) != NULL)
+ where = strecpy(where, s);
+ else
+ where += sprintf(where, "var%d", _var & 0xFFFFFFF);
+ } else if (_var & 0x80000000) {
+ where += sprintf(where, "bitvar%d", _var & 0x7FFFFFFF);
+ } else if (_var & 0x40000000) {
+ where += sprintf(where, "localvar%d", _var & 0xFFFFFFF);
+ } else {
+ where += sprintf(where, "?var?%d", _var);
+ }
+ } else {
+ if (!(_var & 0xF000)) {
+ var = _var & 0xFFF;
+ if ((s = getVarName(var)) != NULL)
+ where = strecpy(where, s);
+ else
+ where += sprintf(where, "var%d", _var & 0xFFF);
+ } else if (_var & 0x8000) {
+ where += sprintf(where, "bitvar%d", _var & 0x7FFF);
+ } else if (_var & 0x4000) {
+ where += sprintf(where, "localvar%d", _var & 0xFFF);
+ } else {
+ where += sprintf(where, "?var?%d", _var);
+ }
+ }
+ return where;
+ }
+};
+
+class ArrayStackEnt : public StackEnt {
+ int _idx;
+ StackEnt *_dim1;
+ StackEnt *_dim2;
+public:
+ ArrayStackEnt(int idx, StackEnt *dim2, StackEnt *dim1) : _idx(idx), _dim1(dim1), _dim2(dim2) { type = seArray; }
+ virtual char *asText(char *where, bool wantparens) const {
+ const char *s;
+
+ if(g_options.scriptVersion == 8 && !(_idx & 0xF0000000) &&
+ (s = getVarName(_idx & 0xFFFFFFF)) != NULL)
+ where += sprintf(where, "%s[",s);
+ else if(g_options.scriptVersion < 8 && !(_idx & 0xF000) &&
+ (s = getVarName(_idx & 0xFFF)) != NULL)
+ where += sprintf(where, "%s[",s);
+ else
+ where += sprintf(where, "array%d[", _idx);
+
+ if (_dim2) {
+ where = _dim2->asText(where);
+ where = strecpy(where, "][");
+ }
+
+ where = _dim1->asText(where);
+ where = strecpy(where, "]");
+
+ return where;
+ }
+};
+
+class UnaryOpStackEnt : public StackEnt {
+ int _op;
+ StackEnt *_valA;
+public:
+ UnaryOpStackEnt(int op, StackEnt *valA) : _op(op), _valA(valA) { type = seUnary; }
+ virtual char *asText(char *where, bool wantparens) const {
+ where += sprintf(where, "%s", oper_list[_op]);
+ where = _valA->asText(where);
+ return where;
+ }
+};
+
+class BinaryOpStackEnt : public StackEnt {
+ int _op;
+ StackEnt *_valA;
+ StackEnt *_valB;
+public:
+ BinaryOpStackEnt(int op, StackEnt *valA, StackEnt *valB) : _op(op), _valA(valA), _valB(valB) { type = seBinary; }
+ virtual char *asText(char *where, bool wantparens) const {
+ if (wantparens)
+ *where++ = '(';
+ where = _valA->asText(where);
+ where += sprintf(where, " %s ", oper_list[_op]);
+ where = _valB->asText(where);
+ if (wantparens)
+ *where++ = ')';
+ *where = 0;
+ return where;
+ }
+};
+
+class ComplexStackEnt : public StackEnt {
+ char *_str;
+public:
+ ComplexStackEnt(const char *s) { _str = strdup(s); type = seComplex; }
+ ~ComplexStackEnt() { free(_str); }
+ virtual char *asText(char *where, bool wantparens) const {
+ where = strecpy(where, _str);
+ return where;
+ }
+};
+
+class ListStackEnt : public StackEnt {
+public:
+ int _size;
+ StackEnt **_list;
+public:
+ ListStackEnt(StackEnt *senum) {
+ type = seStackList;
+
+ _size = senum->getIntVal();
+ _list = new StackEnt* [_size];
+
+ for (int i = 0; i < _size; ++i) {
+ _list[i] = pop();
+ }
+ }
+ ~ListStackEnt() { delete [] _list; }
+ virtual char *asText(char *where, bool wantparens) const {
+ *where++ = '[';
+ for (int i = _size - 1; i >= 0; --i) {
+ where = _list[i]->asText(where);
+ if (i)
+ *where++ = ',';
+ }
+ *where++ = ']';
+ *where = 0;
+ return where;
+ }
+};
+
+class DupStackEnt : public StackEnt {
+public:
+ int _idx;
+public:
+ DupStackEnt(int idx) : _idx(idx) { type = seDup; }
+ virtual char *asText(char *where, bool wantparens) const {
+ where += sprintf(where, "dup[%d]", _idx);
+ return where;
+ }
+};
+
+class NegStackEnt : public StackEnt {
+ StackEnt *_op;
+public:
+ NegStackEnt(StackEnt *op) : _op(op) { type = seNeg; }
+ virtual char *asText(char *where, bool wantparens) const {
+ *where++ = '!';
+ where = _op->asText(where);
+ return where;
+ }
+};
#define MAX_STACK_SIZE 256
static StackEnt *stack[MAX_STACK_SIZE];
static int num_stack = 0;
@@ -741,8 +932,7 @@
NULL,
};
-const char *getVarName(uint var)
-{
+const char *getVarName(uint var) {
if (g_options.heVersion == 72) {
if (var >= sizeof(var_names72) / sizeof(var_names72[0]))
return NULL;
@@ -762,186 +952,56 @@
}
}
-void push(StackEnt * se)
-{
- assert(se);
- assert(num_stack < MAX_STACK_SIZE);
- stack[num_stack++] = se;
+StackEnt *se_neg(StackEnt *se) {
+ return new NegStackEnt(se);
}
-void invalidop(const char *cmd, int op)
-{
- if (cmd)
- error("Unknown opcode %s:0x%x (stack count %d)", cmd, op, num_stack);
- else
- error("Unknown opcode 0x%x (stack count %d)", op, num_stack);
+StackEnt *se_int(int i) {
+ return new IntStackEnt(i);
}
-StackEnt *se_new(int type)
-{
- StackEnt *se = (StackEnt *) malloc(sizeof(StackEnt));
- se->type = type;
- return se;
+StackEnt *se_var(int i) {
+ return new VarStackEnt(i);
}
-void se_free(StackEnt * se)
-{
- free(se);
+StackEnt *se_array(int i, StackEnt * dim2, StackEnt * dim1) {
+ return new ArrayStackEnt(i, dim2, dim1);
}
-StackEnt *se_neg(StackEnt * se)
-{
- StackEnt *s = se_new(seNeg);
- s->left = se;
- return s;
+StackEnt *se_oper(StackEnt * a, int op) {
+ return new UnaryOpStackEnt(op, a);
}
-StackEnt *se_int(int i)
-{
- StackEnt *se = se_new(seInt);
- se->data = i;
- return se;
+StackEnt *se_oper(StackEnt * a, int op, StackEnt * b) {
+ return new BinaryOpStackEnt(op, a, b);
}
-StackEnt *se_var(int i)
-{
- StackEnt *se = se_new(seVar);
- se->data = i;
- return se;
+StackEnt *se_complex(const char *s) {
+ return new ComplexStackEnt(s);
}
-StackEnt *se_array(int i, StackEnt * dim2, StackEnt * dim1)
-{
- StackEnt *se = se_new(seArray);
- se->left = dim2;
- se->right = dim1;
- se->data = i;
- return se;
+char *se_astext(StackEnt * se, char *where, bool wantparens = true) {
+ return se->asText(where, wantparens);
}
-StackEnt *se_oper(StackEnt * a, int op)
-{
- StackEnt *se = se_new(seUnary);
- se->data = op;
- se->left = a;
- return se;
+StackEnt *se_get_list() {
+ return new ListStackEnt(pop());
}
-StackEnt *se_oper(StackEnt * a, int op, StackEnt * b)
-{
- StackEnt *se = se_new(seBinary);
- se->data = op;
- se->left = a;
- se->right = b;
- return se;
+void invalidop(const char *cmd, int op) {
+ if (cmd)
+ error("Unknown opcode %s:0x%x (stack count %d)", cmd, op, num_stack);
+ else
+ error("Unknown opcode 0x%x (stack count %d)", op, num_stack);
}
-StackEnt *se_complex(const char *s)
-{
- StackEnt *se = se_new(seComplex);
- se->str = strdup(s);
- return se;
+void push(StackEnt *se) {
+ assert(se);
+ assert(num_stack < MAX_STACK_SIZE);
+ stack[num_stack++] = se;
}
-char *se_astext(StackEnt * se, char *where, bool wantparens = true)
-{
- int i;
- int var;
- const char *s;
-
- switch (se->type) {
- case seInt:
- where += sprintf(where, "%ld", se->data);
- break;
- case seVar:
- if (g_options.scriptVersion == 8) {
- if (!(se->data & 0xF0000000)) {
- var = se->data & 0xFFFFFFF;
- if ((s = getVarName(var)) != NULL)
- where = strecpy(where, s);
- else
- where += sprintf(where, "var%ld", se->data & 0xFFFFFFF);
- } else if (se->data & 0x80000000) {
- where += sprintf(where, "bitvar%ld", se->data & 0x7FFFFFFF);
- } else if (se->data & 0x40000000) {
- where += sprintf(where, "localvar%ld", se->data & 0xFFFFFFF);
- } else {
- where += sprintf(where, "?var?%ld", se->data);
- }
- } else {
- if (!(se->data & 0xF000)) {
- var = se->data & 0xFFF;
- if ((s = getVarName(var)) != NULL)
- where = strecpy(where, s);
- else
- where += sprintf(where, "var%ld", se->data & 0xFFF);
- } else if (se->data & 0x8000) {
- where += sprintf(where, "bitvar%ld", se->data & 0x7FFF);
- } else if (se->data & 0x4000) {
- where += sprintf(where, "localvar%ld", se->data & 0xFFF);
- } else {
- where += sprintf(where, "?var?%ld", se->data);
- }
- }
- break;
- case seArray:
- if(g_options.scriptVersion == 8 && !(se->data & 0xF0000000) &&
- (s = getVarName(se->data & 0xFFFFFFF)) != NULL)
- where += sprintf(where, "%s[",s);
- else if(g_options.scriptVersion < 8 && !(se->data & 0xF000) &&
- (s = getVarName(se->data & 0xFFF)) != NULL)
- where += sprintf(where, "%s[",s);
- else
- where += sprintf(where, "array%ld[", se->data);
-
- if (se->left) {
- where = se_astext(se->left, where);
- where = strecpy(where, "][");
- }
-
- where = se_astext(se->right, where);
- where = strecpy(where, "]");
- break;
- case seUnary:
- where += sprintf(where, "%s", oper_list[se->data]);
- where = se_astext(se->left, where);
- break;
- case seBinary:
- if (wantparens)
- *where++ = '(';
- where = se_astext(se->left, where);
- where += sprintf(where, " %s ", oper_list[se->data]);
- where = se_astext(se->right, where);
- if (wantparens)
- *where++ = ')';
- *where = 0;
- break;
- case seComplex:
- where = strecpy(where, se->str);
- break;
- case seStackList:
- *where++ = '[';
- for (i = se->data; --i >= 0;) {
- where = se_astext(se->list[i], where);
- if (i)
- *where++ = ',';
- }
- *where++ = ']';
- *where = 0;
- break;
- case seDup:
- where += sprintf(where, "dup[%ld]", se->data);
- break;
- case seNeg:
- *where++ = '!';
- where = se_astext(se->left, where);
- break;
- }
- return where;
-}
-
-StackEnt *pop()
-{
+StackEnt *pop() {
if (num_stack == 0) {
printf("ERROR: No items on stack to pop!\n");
@@ -953,13 +1013,12 @@
}
-void kill(char *output, StackEnt * se)
-{
+void kill(char *output, StackEnt * se) {
if (se->type != seDup) {
char *e = strecpy(output, "pop(");
e = se_astext(se, e);
strcpy(e, ")");
- se_free(se);
+ delete se;
} else {
// FIXME: Evil hack: We re-push DUPs, instead of killing
// them. We do this to support switch-case constructs
@@ -972,7 +1031,7 @@
void doAssign(char *output, StackEnt * dst, StackEnt * src)
{
if (src->type == seDup && dst->type == seDup) {
- dst->data = src->data;
+ ((DupStackEnt *)dst)->_idx = ((DupStackEnt *)src)->_idx;
return;
}
char *e = se_astext(dst, output);
@@ -980,6 +1039,12 @@
se_astext(src, e);
}
+StackEnt* StackEnt::dup(char *output) {
+ StackEnt *dse = new DupStackEnt(++dupindex);
+ doAssign(output, dse, this);
+ return dse;
+}
+
void doAdd(char *output, StackEnt * se, int val)
{
char *e = se_astext(se, output);
@@ -993,45 +1058,36 @@
}
}
-StackEnt *dup(char *output, StackEnt * se)
-{
- static int dupindex = 0;
-
- if (se->type == seInt)
- return se;
-
- StackEnt *dse = se_new(seDup);
- dse->data = ++dupindex;
- doAssign(output, dse, se);
- return dse;
+StackEnt *dup(char *output, StackEnt * se) {
+ return se->dup(output);
}
void writeArray(char *output, int i, StackEnt * dim2, StackEnt * dim1, StackEnt * value)
{
StackEnt *array = se_array(i, dim2, dim1);
doAssign(output, array, value);
- se_free(array);
+ delete array;
}
void writeVar(char *output, int i, StackEnt * value)
{
StackEnt *se = se_var(i);
doAssign(output, se, value);
- se_free(se);
+ delete se;
}
void addArray(char *output, int i, StackEnt * dim1, int val)
{
StackEnt *array = se_array(i, NULL, dim1);
doAdd(output, array, val);
- se_free(array);
+ delete array;
}
void addVar(char *output, int i, int val)
{
StackEnt *se = se_var(i);
doAdd(output, se, val);
- se_free(se);
+ delete se;
}
StackEnt *se_get_string()
@@ -1064,11 +1120,9 @@
case 6: // addNameToStack
case 7: // addStringToStack
{
- StackEnt foo;
- foo.type = seVar;
- foo.data = get_word();
+ VarStackEnt tmp(get_word());
e += sprintf(e, ":");
- e = se_astext(&foo, e);
+ e = tmp.asText(e);
e += sprintf(e, ":");
}
break;
@@ -1131,11 +1185,12 @@
byte string[1024];
byte chr;
int len = 1;
- StackEnt *array;
+ StackEnt *value;
- array = pop();
+ value = pop();
+
*e++ = '"';
- if (array->data == -1) {
+ if (value->getIntVal() == -1) {
if (_stringLength == 1) {
*e++ = '"';
*e++ = 0;
@@ -1155,11 +1210,9 @@
while (--len)
*e++ = string[len];
} else {
- StackEnt foo;
- foo.type = seVar;
- foo.data = array->data;
+ VarStackEnt tmp(value->getIntVal());
e += sprintf(e, ":");
- e = se_astext(&foo, e);
+ e = tmp.asText(e);
e += sprintf(e, ":");
}
*e++ = '"';
@@ -1168,24 +1221,6 @@
return se_complex(buf);
}
-StackEnt *se_get_list()
-{
- StackEnt *se = se_new(seStackList);
- StackEnt *senum = pop();
- int num, i;
-
- if (senum->type != seInt) {
- error("stackList with variable number of arguments, cannot disassemble");
- }
- se->data = num = senum->data;
- se->list = (StackEnt **) calloc(num, sizeof(StackEnt *));
-
- for(i = 0; i < num; i++) {
- se->list[i] = pop();
- }
- return se;
-}
-
void ext(char *output, const char *fmt)
{
bool wantresult;
@@ -1228,25 +1263,28 @@
}
if (cmd == 'y' && !extstr) {
/* Sub-op: parameters are in a list, first element of the list specified the command */
- StackEnt *se;
+ ListStackEnt *se;
extstr = fmt;
while (*fmt++)
;
e += sprintf(e, "%s.", extstr);
- args[numArgs++] = se_get_list();
+ se = new ListStackEnt(pop());
+ args[numArgs++] = se;
/* extended thing */
- se = args[numArgs - 1];
- se->data--;
- extcmd = (byte) se->list[se->data]->data;
+ se->_size--;
+ extcmd = (byte) se->_list[se->_size]->getIntVal();
/* locate our extended item */
while ((cmd = *fmt++) != extcmd) {
/* scan until we find , or \0 */
while ((cmd = *fmt++) != ',') {
if (cmd == 0) {
- se->data++;
+ /* End reached and command was not found: re-add the extcmd to
+ the list and output the whole thing as "unknown".
+ */
+ se->_size++;
fmt = "Unknown";
goto output_command;
}
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