[Scummvm-git-logs] scummvm refcount -> 3dc4bb38cd78c39098b855db7dfd7d6b18bce51e
moralrecordings
code at moral.net.au
Tue May 12 10:06:13 UTC 2020
This automated email contains information about 3 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
594f435ed8 DIRECTOR: LINGO: Add reference counter to Symbol and Datum
ceb81566df DIRECTOR: LINGO: Add copy assignment operator for Datum/Symbol
3dc4bb38cd DIRECTOR: LINGO: Precalculate array size for b_addAt
Commit: 594f435ed8abb1e058bb931951f6f5e3dada4628
https://github.com/scummvm/scummvm/commit/594f435ed8abb1e058bb931951f6f5e3dada4628
Author: Scott Percival (code at moral.net.au)
Date: 2020-05-12T01:13:18+08:00
Commit Message:
DIRECTOR: LINGO: Add reference counter to Symbol and Datum
Changed paths:
engines/director/lingo/lingo-builtins.cpp
engines/director/lingo/lingo-bytecode.cpp
engines/director/lingo/lingo-code.cpp
engines/director/lingo/lingo-code.h
engines/director/lingo/lingo-codegen.cpp
engines/director/lingo/lingo-funcs.cpp
engines/director/lingo/lingo-the.cpp
engines/director/lingo/lingo.cpp
engines/director/lingo/lingo.h
engines/director/util.cpp
engines/director/util.h
diff --git a/engines/director/lingo/lingo-builtins.cpp b/engines/director/lingo/lingo-builtins.cpp
index 01d9819e5a..3ad6e07416 100644
--- a/engines/director/lingo/lingo-builtins.cpp
+++ b/engines/director/lingo/lingo-builtins.cpp
@@ -315,7 +315,7 @@ void Lingo::printSTUBWithArglist(const char *funcname, int nargs, const char *pr
for (int i = 0; i < nargs; i++) {
Datum d = _stack[_stack.size() - nargs + i];
- s += d.getPrintable();
+ s += d.asString(true);
if (i != nargs - 1)
s += ", ";
@@ -365,125 +365,101 @@ void LB::b_abs(int nargs) {
void LB::b_atan(int nargs) {
Datum d = g_lingo->pop();
- d.makeFloat();
- d.u.f = atan(d.u.f);
- g_lingo->push(d);
+ Datum res(atan(d.asFloat()));
+ g_lingo->push(res);
}
void LB::b_cos(int nargs) {
Datum d = g_lingo->pop();
- d.makeFloat();
- d.u.f = cos(d.u.f);
- g_lingo->push(d);
+ Datum res(cos(d.asFloat()));
+ g_lingo->push(res);
}
void LB::b_exp(int nargs) {
Datum d = g_lingo->pop();
- d.makeInt(); // Lingo uses int, so we're enforcing it
- d.makeFloat();
- d.u.f = exp(d.u.f);
- g_lingo->push(d);
+ // Lingo uses int, so we're enforcing it
+ Datum res(exp(d.asInt()));
+ g_lingo->push(res);
}
void LB::b_float(int nargs) {
Datum d = g_lingo->pop();
- d.makeFloat();
- g_lingo->push(d);
+ Datum res(d.asFloat());
+ g_lingo->push(res);
}
void LB::b_integer(int nargs) {
Datum d = g_lingo->pop();
- d.makeInt();
- g_lingo->push(d);
+ Datum res(d.asInt());
+ g_lingo->push(res);
}
void LB::b_log(int nargs) {
Datum d = g_lingo->pop();
- d.makeFloat();
- d.u.f = log(d.u.f);
- g_lingo->push(d);
+ Datum res(log(d.asFloat()));
+ g_lingo->push(res);
}
void LB::b_pi(int nargs) {
- Datum d;
- d.makeFloat();
- d.u.f = M_PI;
- g_lingo->push(d);
+ Datum res(M_PI);
+ g_lingo->push(res);
}
void LB::b_power(int nargs) {
Datum d1 = g_lingo->pop();
Datum d2 = g_lingo->pop();
- d1.makeFloat();
- d2.makeFloat();
- d1.u.f = pow(d2.u.f, d1.u.f);
+ Datum res(pow(d2.asFloat(), d1.asFloat()));
g_lingo->push(d1);
}
void LB::b_random(int nargs) {
Datum max = g_lingo->pop();
- Datum res;
-
- max.makeInt();
-
- res.u.i = g_lingo->_vm->_rnd.getRandomNumber(max.u.i - 1) + 1;
- res.type = INT;
-
+ Datum res((int)(g_lingo->_vm->_rnd.getRandomNumber(max.asInt() - 1) + 1));
g_lingo->push(res);
}
void LB::b_sin(int nargs) {
Datum d = g_lingo->pop();
- d.makeFloat();
- d.u.f = sin(d.u.f);
- g_lingo->push(d);
+ Datum res(sin(d.asFloat()));
+ g_lingo->push(res);
}
void LB::b_sqrt(int nargs) {
Datum d = g_lingo->pop();
- d.makeFloat();
- d.u.f = sqrt(d.u.f);
- g_lingo->push(d);
+ Datum res(sqrt(d.asFloat()));
+ g_lingo->push(res);
}
void LB::b_tan(int nargs) {
Datum d = g_lingo->pop();
- d.makeFloat();
- d.u.f = tan(d.u.f);
- g_lingo->push(d);
+ Datum res(tan(d.asFloat()));
+ g_lingo->push(res);
}
///////////////////
// String
///////////////////
void LB::b_chars(int nargs) {
- Datum to = g_lingo->pop();
- Datum from = g_lingo->pop();
+ int to = g_lingo->pop().asInt();
+ int from = g_lingo->pop().asInt();
Datum s = g_lingo->pop();
+ TYPECHECK2(s, STRING, REFERENCE);
- if (s.type == REFERENCE)
- s.makeString();
-
- TYPECHECK(s, STRING);
+ Common::String src = s.asString();
- to.makeInt();
- from.makeInt();
+ int len = strlen(src.c_str());
+ int f = MAX(0, MIN(len, from - 1));
+ int t = MAX(0, MIN(len, to));
- int len = strlen(s.u.s->c_str());
- int f = MAX(0, MIN(len, from.u.i - 1));
- int t = MAX(0, MIN(len, to.u.i));
-
- Common::String *res;
+ Common::String *result;
if (f > t) {
- res = new Common::String("");
+ result = new Common::String("");
} else {
- res = new Common::String(&(s.u.s->c_str()[f]), &(s.u.s->c_str()[t]));
+ result = new Common::String(&(src.c_str()[f]), &(src.c_str()[t]));
}
- Datum ret;
- ret.type = STRING;
- ret.u.s = res;
- g_lingo->push(ret);
+ Datum res(result);
+ g_lingo->push(res);
}
void LB::b_charToNum(int nargs) {
@@ -491,55 +467,50 @@ void LB::b_charToNum(int nargs) {
TYPECHECK(d, STRING);
- byte chr = d.u.s->c_str()[0];
- delete d.u.s;
+ int chr = (uint8)d.u.s->c_str()[0];
- d.u.i = chr;
- d.type = INT;
- g_lingo->push(d);
+ Datum res(chr);
+ g_lingo->push(res);
}
void LB::b_delete(int nargs) {
Datum d = g_lingo->pop();
- d.makeInt();
+ Datum res(d.asInt());
warning("STUB: b_delete");
- g_lingo->push(Datum((char)d.u.i));
+ g_lingo->push(res);
}
void LB::b_hilite(int nargs) {
Datum d = g_lingo->pop();
- d.makeInt();
+ Datum res(d.asInt());
warning("STUB: b_hilite");
- g_lingo->push(Datum((char)d.u.i));
+ g_lingo->push(res);
}
void LB::b_length(int nargs) {
Datum d = g_lingo->pop();
- if (d.type == REFERENCE)
- d.makeString();
+ TYPECHECK2(d, STRING, REFERENCE);
- TYPECHECK(d, STRING);
+ int len = strlen(d.asString().c_str());
- int len = strlen(d.u.s->c_str());
- delete d.u.s;
-
- d.u.i = len;
- d.type = INT;
- g_lingo->push(d);
+ Datum res(len);
+ g_lingo->push(res);
}
void LB::b_numToChar(int nargs) {
Datum d = g_lingo->pop();
- d.makeInt();
+ char result[2];
+ result[0] = (char)d.asInt();
+ result[1] = 0;
- g_lingo->push(Datum((char)d.u.i));
+ g_lingo->push(Datum(Common::String(result)));
}
void LB::b_offset(int nargs) {
@@ -547,11 +518,8 @@ void LB::b_offset(int nargs) {
b_offsetRect(nargs);
return;
}
- Datum target = g_lingo->pop();
- Datum source = g_lingo->pop();
-
- target.makeString();
- source.makeString();
+ Common::String target = g_lingo->pop().asString();
+ Common::String source = g_lingo->pop().asString();
warning("STUB: b_offset()");
@@ -560,15 +528,14 @@ void LB::b_offset(int nargs) {
void LB::b_string(int nargs) {
Datum d = g_lingo->pop();
- d.makeString();
- g_lingo->push(d);
+ Datum res(d.asString());
+ g_lingo->push(res);
}
void LB::b_value(int nargs) {
Datum d = g_lingo->pop();
- d.makeInt();
warning("STUB: b_value()");
- g_lingo->push(d);
+ g_lingo->push(Datum(0));
}
///////////////////
@@ -584,19 +551,18 @@ void LB::b_addAt(int nargs) {
ARGNUMCHECK(3);
Datum value = g_lingo->pop();
- Datum index = g_lingo->pop();
+ Datum indexD = g_lingo->pop();
Datum list = g_lingo->pop();
- TYPECHECK(index, INT);
- if (index.type == FLOAT)
- index.makeInt();
+ TYPECHECK2(indexD, INT, FLOAT);
+ int index = indexD.asInt();
TYPECHECK(list, ARRAY);
- if (!((uint)index.u.i < list.u.farr->size())) {
- for (uint i = 0; i < index.u.i-list.u.farr->size()-1; i++)
+ if (!((uint)index < list.u.farr->size())) {
+ for (uint i = 0; i < index - list.u.farr->size() - 1; i++)
list.u.farr->push_back(Datum(0));
}
- list.u.farr->insert_at(index.u.i-1, value);
+ list.u.farr->insert_at(index - 1, value);
}
void LB::b_addProp(int nargs) {
@@ -649,21 +615,21 @@ void LB::b_count(int nargs) {
void LB::b_deleteAt(int nargs) {
ARGNUMCHECK(2);
- Datum index = g_lingo->pop();
+ Datum indexD = g_lingo->pop();
Datum list = g_lingo->pop();
- if (index.type == FLOAT)
- index.makeInt();
- TYPECHECK(index, INT);
+ TYPECHECK2(indexD, INT, FLOAT);
+ TYPECHECK2(list, ARRAY, PARRAY);
+ int index = indexD.asInt();
switch (list.type) {
case ARRAY:
- list.u.farr->remove_at(index.u.i-1);
+ list.u.farr->remove_at(index - 1);
break;
case PARRAY:
- list.u.parr->remove_at(index.u.i-1);
+ list.u.parr->remove_at(index - 1);
break;
default:
- TYPECHECK2(list, ARRAY, PARRAY);
+ break;
}
}
@@ -672,6 +638,7 @@ void LB::b_deleteProp(int nargs) {
Datum prop = g_lingo->pop();
Datum list = g_lingo->pop();
+ TYPECHECK2(list, ARRAY, PARRAY);
switch (list.type) {
case ARRAY:
@@ -682,12 +649,12 @@ void LB::b_deleteProp(int nargs) {
case PARRAY: {
int index = LC::compareArrays(LC::eqData, list, prop, true).u.i;
if (index > 0) {
- list.u.parr->remove_at(index-1);
+ list.u.parr->remove_at(index - 1);
}
break;
}
default:
- TYPECHECK2(list, ARRAY, PARRAY);
+ break;
}
}
@@ -711,26 +678,25 @@ void LB::b_findPos(int nargs) {
void LB::b_findPosNear(int nargs) {
ARGNUMCHECK(2);
- Datum prop = g_lingo->pop();
+ Common::String prop = g_lingo->pop().asString();
Datum list = g_lingo->pop();
- Datum d(0);
+ Datum res(0);
TYPECHECK(list, PARRAY);
// FIXME: Integrate with compareTo framework
- prop = prop.makeString();
- prop.u.s->toLowercase();
+ prop.toLowercase();
for (uint i = 0; i < list.u.parr->size(); i++) {
Datum p = *list.u.parr->operator[](i).p;
- p.makeString();
- p.u.s->toLowercase();
- if (p.u.s->find(prop.u.s->c_str()) == 0) {
- d.u.i = i+1;
+ Common::String tgt = p.asString();
+ tgt.toLowercase();
+ if (tgt.find(prop.c_str()) == 0) {
+ res.u.i = i + 1;
break;
}
}
- g_lingo->push(d);
+ g_lingo->push(res);
}
void LB::b_getaProp(int nargs) {
@@ -761,20 +727,19 @@ void LB::b_getaProp(int nargs) {
void LB::b_getAt(int nargs) {
ARGNUMCHECK(2);
- Datum index = g_lingo->pop();
+ Datum indexD = g_lingo->pop();
+ TYPECHECK2(indexD, INT, FLOAT);
Datum list = g_lingo->pop();
- if (index.type == FLOAT)
- index.makeInt();
- TYPECHECK(index, INT);
+ int index = indexD.asInt();
switch (list.type) {
case ARRAY:
- ARRBOUNDSCHECK(index.u.i, list);
- g_lingo->push(list.u.farr->operator[](index.u.i-1));
+ ARRBOUNDSCHECK(index, list);
+ g_lingo->push(list.u.farr->operator[](index - 1));
break;
case PARRAY:
- ARRBOUNDSCHECK(index.u.i, list);
- g_lingo->push(*list.u.parr->operator[](index.u.i-1).v);
+ ARRBOUNDSCHECK(index, list);
+ g_lingo->push(*list.u.parr->operator[](index - 1).v);
break;
default:
TYPECHECK2(list, ARRAY, PARRAY);
@@ -826,12 +791,10 @@ void LB::b_getPos(int nargs) {
ARGNUMCHECK(2);
Datum val = g_lingo->pop();
Datum list = g_lingo->pop();
+ TYPECHECK2(list, ARRAY, PARRAY);
switch (list.type) {
case ARRAY: {
- if (val.type == FLOAT)
- val.makeInt();
- TYPECHECK(val, INT);
Datum d(0);
int index = LC::compareArrays(LC::eqData, list, val, true).u.i;
if (index > 0) {
@@ -850,7 +813,7 @@ void LB::b_getPos(int nargs) {
break;
}
default:
- TYPECHECK2(list, ARRAY, PARRAY);
+ break;
}
}
@@ -858,6 +821,7 @@ void LB::b_getProp(int nargs) {
ARGNUMCHECK(2);
Datum prop = g_lingo->pop();
Datum list = g_lingo->pop();
+ TYPECHECK2(list, ARRAY, PARRAY);
switch (list.type) {
case ARRAY:
@@ -870,26 +834,22 @@ void LB::b_getProp(int nargs) {
if (index > 0) {
g_lingo->push(*list.u.parr->operator[](index-1).v);
} else {
- error("b_getProp: Property %s not found", prop.makeString()->c_str());
+ error("b_getProp: Property %s not found", prop.asString().c_str());
}
break;
}
default:
- TYPECHECK2(list, ARRAY, PARRAY);
+ break;
}
}
void LB::b_getPropAt(int nargs) {
ARGNUMCHECK(2);
- Datum index = g_lingo->pop();
+ int index = g_lingo->pop().asInt();
Datum list = g_lingo->pop();
TYPECHECK(list, PARRAY);
- if (index.type == FLOAT)
- index.makeInt();
- TYPECHECK(index, INT);
-
- g_lingo->push(*list.u.parr->operator[](index.u.i-1).p);
+ g_lingo->push(*list.u.parr->operator[](index-1).p);
}
void LB::b_list(int nargs) {
@@ -1010,27 +970,26 @@ void LB::b_setaProp(int nargs) {
void LB::b_setAt(int nargs) {
ARGNUMCHECK(3);
Datum value = g_lingo->pop();
- Datum index = g_lingo->pop();
+ int index = g_lingo->pop().asInt();
Datum list = g_lingo->pop();
- if (index.type == FLOAT)
- index.makeInt();
- TYPECHECK(index, INT);
+
+ TYPECHECK2(list, ARRAY, PARRAY);
switch (list.type) {
case ARRAY:
- if ((uint)index.u.i < list.u.farr->size()) {
- list.u.farr->operator[](index.u.i-1) = value;
+ if ((uint)index < list.u.farr->size()) {
+ list.u.farr->operator[](index-1) = value;
} else {
// TODO: Extend the list if we request an index beyond it
- ARRBOUNDSCHECK(index.u.i, list);
+ ARRBOUNDSCHECK(index, list);
}
break;
case PARRAY:
- ARRBOUNDSCHECK(index.u.i, list);
- *list.u.parr->operator[](index.u.i-1).v = value;
+ ARRBOUNDSCHECK(index, list);
+ *list.u.parr->operator[](index-1).v = value;
break;
default:
- TYPECHECK2(list, ARRAY, PARRAY);
+ break;
}
}
@@ -1067,21 +1026,13 @@ void LB::b_closeDA(int nargs) {
void LB::b_closeResFile(int nargs) {
Datum d = g_lingo->pop();
- d.makeString();
-
- warning("STUB: b_closeResFile(%s)", d.u.s->c_str());
-
- delete d.u.s;
+ warning("STUB: b_closeResFile(%s)", d.asString().c_str());
}
void LB::b_closeXlib(int nargs) {
Datum d = g_lingo->pop();
- d.makeString();
-
- warning("STUB: b_closeXlib(%s)", d.u.s->c_str());
-
- delete d.u.s;
+ warning("STUB: b_closeXlib(%s)", d.asString().c_str());
}
void LB::b_getNthFileNameInFolder(int nargs) {
@@ -1095,31 +1046,19 @@ void LB::b_getNthFileNameInFolder(int nargs) {
void LB::b_openDA(int nargs) {
Datum d = g_lingo->pop();
- d.makeString();
-
- warning("STUB: b_openDA(%s)", d.u.s->c_str());
-
- delete d.u.s;
+ warning("STUB: b_openDA(%s)", d.asString().c_str());
}
void LB::b_openResFile(int nargs) {
Datum d = g_lingo->pop();
- d.makeString();
-
- warning("STUB: b_openResFile(%s)", d.u.s->c_str());
-
- delete d.u.s;
+ warning("STUB: b_openResFile(%s)", d.asString().c_str());
}
void LB::b_openXlib(int nargs) {
Datum d = g_lingo->pop();
- d.makeString();
-
- warning("STUB: b_openXlib(%s)", d.u.s->c_str());
-
- delete d.u.s;
+ warning("STUB: b_openXlib(%s)", d.asString().c_str());
}
void LB::b_saveMovie(int nargs) {
@@ -1135,31 +1074,19 @@ void LB::b_setCallBack(int nargs) {
void LB::b_showResFile(int nargs) {
Datum d = g_lingo->pop();
- d.makeString();
-
- warning("STUB: b_showResFile(%s)", d.u.s->c_str());
-
- delete d.u.s;
+ warning("STUB: b_showResFile(%s)", d.asString().c_str());
}
void LB::b_showXlib(int nargs) {
Datum d = g_lingo->pop();
- d.makeString();
-
- warning("STUB: b_showXlib(%s)", d.u.s->c_str());
-
- delete d.u.s;
+ warning("STUB: b_showXlib(%s)", d.asString().c_str());
}
void LB::b_xFactoryList(int nargs) {
Datum d = g_lingo->pop();
- d.makeString();
-
- warning("STUB: b_xFactoryList(%s)", d.u.s->c_str());
-
- delete d.u.s;
+ warning("STUB: b_xFactoryList(%s)", d.asString().c_str());
}
///////////////////
@@ -1184,15 +1111,13 @@ void LB::b_nothing(int nargs) {
void LB::b_delay(int nargs) {
Datum d = g_lingo->pop();
- d.makeInt();
- g_director->getCurrentScore()->_nextFrameTime = g_system->getMillis() + (float)d.u.i / 60 * 1000;
+ g_director->getCurrentScore()->_nextFrameTime = g_system->getMillis() + (float)d.asInt() / 60 * 1000;
}
void LB::b_do(int nargs) {
Datum d = g_lingo->pop();
- d.makeString();
- warning("STUB: b_do(%s)", d.u.s->c_str());
+ warning("STUB: b_do(%s)", d.asString().c_str());
}
void LB::b_go(int nargs) {
@@ -1350,42 +1275,34 @@ void LB::b_startTimer(int nargs) {
///////////////////
void LB::b_factoryP(int nargs) {
Datum d = g_lingo->pop();
- d.makeInt();
- d.u.i = 1;
- g_lingo->push(d);
+ Datum res(d.asInt());
+ g_lingo->push(res);
warning("STUB: b_factoryP");
}
void LB::b_floatP(int nargs) {
Datum d = g_lingo->pop();
- int res = (d.type == FLOAT) ? 1 : 0;
- d.makeInt();
- d.u.i = res;
- g_lingo->push(d);
+ Datum res((d.type == FLOAT) ? 1 : 0);
+ g_lingo->push(res);
}
void LB::b_ilk(int nargs) {
Datum d = g_lingo->pop();
- d.u.s = new Common::String(d.type2str(true));
- d.type = SYMBOL;
- g_lingo->push(d);
+ Datum res(new Common::String(d.type2str(true)));
+ g_lingo->push(res);
}
void LB::b_integerp(int nargs) {
Datum d = g_lingo->pop();
- int res = (d.type == INT) ? 1 : 0;
- d.makeInt();
- d.u.i = res;
- g_lingo->push(d);
+ Datum res((d.type == INT) ? 1 : 0);
+ g_lingo->push(res);
}
void LB::b_objectp(int nargs) {
Datum d = g_lingo->pop();
- int res = (d.type == OBJECT) ? 1 : 0;
- d.makeInt();
- d.u.i = res;
- g_lingo->push(d);
+ Datum res ((d.type == OBJECT) ? 1 : 0);
+ g_lingo->push(res);
}
void LB::b_pictureP(int nargs) {
@@ -1396,26 +1313,20 @@ void LB::b_pictureP(int nargs) {
void LB::b_stringp(int nargs) {
Datum d = g_lingo->pop();
- int res = (d.type == STRING) ? 1 : 0;
- d.makeInt();
- d.u.i = res;
- g_lingo->push(d);
+ Datum res((d.type == STRING) ? 1 : 0);
+ g_lingo->push(res);
}
void LB::b_symbolp(int nargs) {
Datum d = g_lingo->pop();
- int res = (d.type == SYMBOL) ? 1 : 0;
- d.makeInt();
- d.u.i = res;
- g_lingo->push(d);
+ Datum res((d.type == SYMBOL) ? 1 : 0);
+ g_lingo->push(res);
}
void LB::b_voidP(int nargs) {
Datum d = g_lingo->pop();
- int res = (d.type == VOID) ? 1 : 0;
- d.makeInt();
- d.u.i = res;
- g_lingo->push(d);
+ Datum res((d.type == VOID) ? 1 : 0);
+ g_lingo->push(res);
}
@@ -1425,11 +1336,7 @@ void LB::b_voidP(int nargs) {
void LB::b_alert(int nargs) {
Datum d = g_lingo->pop();
- d.makeString();
-
- warning("STUB: b_alert(%s)", d.u.s->c_str());
-
- delete d.u.s;
+ warning("STUB: b_alert(%s)", d.asString().c_str());
}
void LB::b_birth(int nargs) {
@@ -1452,13 +1359,10 @@ void LB::b_cursor(int nargs) {
if (d.type == ARRAY) {
Datum sprite = d.u.farr->operator[](0);
Datum mask = d.u.farr->operator[](1);
- sprite.makeInt();
- mask.makeInt();
- g_lingo->func_cursor(sprite.u.i, mask.u.i);
+ g_lingo->func_cursor(sprite.asInt(), mask.asInt());
} else {
- d.makeInt();
- g_lingo->func_cursor(d.u.i, -1);
+ g_lingo->func_cursor(d.asInt(), -1);
}
}
@@ -1477,10 +1381,7 @@ void LB::b_constrainH(int nargs) {
Datum num = g_lingo->pop();
Datum sprite = g_lingo->pop();
- num.makeInt();
- sprite.makeInt();
-
- warning("STUB: b_constrainH(%d, %d)", sprite.u.i, num.u.i);
+ warning("STUB: b_constrainH(%d, %d)", sprite.asInt(), num.asInt());
g_lingo->push(Datum(0));
}
@@ -1489,10 +1390,7 @@ void LB::b_constrainV(int nargs) {
Datum num = g_lingo->pop();
Datum sprite = g_lingo->pop();
- num.makeInt();
- sprite.makeInt();
-
- warning("STUB: b_constrainV(%d, %d)", sprite.u.i, num.u.i);
+ warning("STUB: b_constrainV(%d, %d)", sprite.asInt(), num.asInt());
g_lingo->push(Datum(0));
}
@@ -1549,15 +1447,15 @@ void LB::b_installMenu(int nargs) {
// installMenu castNum
Datum d = g_lingo->pop();
- d.makeInt();
+ int castId = d.asInt();
if (g_director->getVersion() < 4)
- d.u.i += g_director->getCurrentScore()->_castIDoffset;
+ castId += g_director->getCurrentScore()->_castIDoffset;
- const Stxt *stxt = g_director->getCurrentScore()->_loadedStxts->getVal(d.u.i, nullptr);
+ const Stxt *stxt = g_director->getCurrentScore()->_loadedStxts->getVal(castId, nullptr);
if (!stxt) {
- warning("installMenu: Unknown cast number #%d", d.u.i);
+ warning("installMenu: Unknown cast number #%d", castId);
return;
}
@@ -1682,16 +1580,14 @@ Common::String Lingo::genMenuHandler(int *commandId, Common::String &command) {
void LB::b_label(int nargs) {
Datum d = g_lingo->pop();
- d.makeInt();
- warning("STUB: b_label(%d)", d.u.i);
+ warning("STUB: b_label(%d)", d.asInt());
g_lingo->push(Datum(0));
}
void LB::b_marker(int nargs) {
Datum d = g_lingo->pop();
- d.makeInt();
- int marker = g_lingo->func_marker(d.u.i);
+ int marker = g_lingo->func_marker(d.asInt());
g_lingo->push(marker);
}
@@ -1779,7 +1675,7 @@ void LB::b_puppetSprite(int nargs) {
void LB::b_puppetTempo(int nargs) {
Datum d = g_lingo->pop();
- warning("STUB: b_puppetTempo(%d)", d.u.i);
+ warning("STUB: b_puppetTempo(%d)", d.asInt());
}
void LB::b_puppetTransition(int nargs) {
@@ -1797,12 +1693,8 @@ void LB::b_ramNeeded(int nargs) {
void LB::b_rollOver(int nargs) {
Datum d = g_lingo->pop();
-
- d.makeInt();
-
- int arg = d.u.i;
-
- d.u.i = 0; // FALSE
+ Datum res(0);
+ int arg = d.asInt();
if (!g_director->getCurrentScore()) {
warning("b_rollOver: Reference to an empty score");
@@ -1812,16 +1704,16 @@ void LB::b_rollOver(int nargs) {
Frame *frame = g_director->getCurrentScore()->_frames[g_director->getCurrentScore()->getCurrentFrame()];
if (arg >= (int32) frame->_sprites.size()) {
- g_lingo->push(d);
+ g_lingo->push(res);
return;
}
Common::Point pos = g_system->getEventManager()->getMousePos();
if (frame->checkSpriteIntersection(arg, pos))
- d.u.i = 1; // TRUE
+ res.u.i = 1; // TRUE
- g_lingo->push(d);
+ g_lingo->push(res);
}
void LB::b_spriteBox(int nargs) {
@@ -1856,37 +1748,32 @@ void LB::b_zoomBox(int nargs) {
int delayTicks = 1;
if (nargs > 2) {
Datum d = g_lingo->pop();
- d.makeInt();
-
- delayTicks = d.u.i;
+ delayTicks = d.asInt();
}
- Datum endSprite = g_lingo->pop();
- Datum startSprite = g_lingo->pop();
-
- startSprite.makeInt();
- endSprite.makeInt();
+ int endSprite = g_lingo->pop().asInt();
+ int startSprite = g_lingo->pop().asInt();
Score *score = g_director->getCurrentScore();
uint16 curFrame = score->getCurrentFrame();
Frame *frame = score->_frames[curFrame];
- Common::Rect *startRect = frame->getSpriteRect(startSprite.u.i);
+ Common::Rect *startRect = frame->getSpriteRect(startSprite);
if (!startRect) {
- warning("b_zoomBox: unknown start sprite #%d", startSprite.u.i);
+ warning("b_zoomBox: unknown start sprite #%d", startSprite);
return;
}
// Looks for endSprite in the current frame, otherwise
// Looks for endSprite in the next frame
- Common::Rect *endRect = frame->getSpriteRect(endSprite.u.i);
+ Common::Rect *endRect = frame->getSpriteRect(endSprite);
if (!endRect) {
if ((uint)curFrame + 1 < score->_frames.size())
- score->_frames[curFrame + 1]->getSpriteRect(endSprite.u.i);
+ score->_frames[curFrame + 1]->getSpriteRect(endSprite);
}
if (!endRect) {
- warning("b_zoomBox: unknown end sprite #%d", endSprite.u.i);
+ warning("b_zoomBox: unknown end sprite #%d", endSprite);
return;
}
@@ -1953,13 +1840,10 @@ void LB::b_moveToFront(int nargs) {
// Point
///////////////////
void LB::b_point(int nargs) {
- Datum y = g_lingo->pop();
- Datum x = g_lingo->pop();
+ Datum y(g_lingo->pop().asFloat());
+ Datum x(g_lingo->pop().asFloat());
Datum d;
- x.makeFloat();
- y.makeFloat();
-
d.u.farr = new DatumArray;
d.u.farr->push_back(x);
@@ -2034,17 +1918,13 @@ void LB::b_beep(int nargs) {
void LB::b_mci(int nargs) {
Datum d = g_lingo->pop();
- d.makeString();
-
- g_lingo->func_mci(*d.u.s);
+ g_lingo->func_mci(d.asString());
}
void LB::b_mciwait(int nargs) {
Datum d = g_lingo->pop();
- d.makeString();
-
- g_lingo->func_mciwait(*d.u.s);
+ g_lingo->func_mciwait(d.asString());
}
void LB::b_sound(int nargs) {
@@ -2197,10 +2077,9 @@ void Lingo::factoryCall(Common::String &name, int nargs) {
debugC(3, kDebugLingoExec, "Stack size after call: %d", _stack.size());
if (!method.u.s->compareToIgnoreCase("mNew")) {
- Datum d;
+ Datum d(name);
d.type = OBJECT;
- d.u.s = new Common::String(name);
g_lingo->push(d);
}
@@ -2214,20 +2093,17 @@ void LB::b_cast(int nargs) {
warning("STUB: b_cast");
- d.type = REFERENCE;
- d.u.i = 0;
-
- g_lingo->push(d);
+ Datum res(0);
+ res.type = REFERENCE;
+ g_lingo->push(res);
}
void LB::b_field(int nargs) {
Datum d = g_lingo->pop();
- d.u.i = g_lingo->castIdFetch(d);
-
- d.type = REFERENCE;
-
- g_lingo->push(d);
+ Datum res(g_lingo->castIdFetch(d));
+ res.type = REFERENCE;
+ g_lingo->push(res);
}
void LB::b_script(int nargs) {
@@ -2235,10 +2111,9 @@ void LB::b_script(int nargs) {
warning("STUB: b_script");
+ Datum res(0);
d.type = REFERENCE;
- d.u.i = 0;
-
- g_lingo->push(d);
+ g_lingo->push(res);
}
void LB::b_window(int nargs) {
@@ -2246,126 +2121,99 @@ void LB::b_window(int nargs) {
warning("STUB: b_window");
- d.type = REFERENCE;
- d.u.i = 0;
-
- g_lingo->push(d);
+ Datum res(0);
+ res.type = REFERENCE;
+ g_lingo->push(res);
}
void LB::b_numberofchars(int nargs) {
Datum d = g_lingo->pop();
- d.makeString();
- int len = strlen(d.u.s->c_str());
- delete d.u.s;
+ int len = strlen(d.asString().c_str());
- d.u.i = len;
- d.type = INT;
- g_lingo->push(d);
+ Datum res(len);
+ g_lingo->push(res);
}
void LB::b_numberofitems(int nargs) {
Datum d = g_lingo->pop();
- d.makeString();
int numberofitems = 1;
- Common::String contents = *d.u.s;
- for (uint32 i = 0; i < d.u.s->size(); i++) {
+ Common::String contents = d.asString();
+ for (uint32 i = 0; i < contents.size(); i++) {
if (contents[i] == ',')
numberofitems++;
}
- delete d.u.s;
-
- d.u.i = numberofitems;
- d.type = INT;
- g_lingo->push(d);
+ Datum res(numberofitems);
+ g_lingo->push(res);
}
void LB::b_numberoflines(int nargs) {
Datum d = g_lingo->pop();
- d.makeString();
int numberoflines = 1;
- Common::String contents = *d.u.s;
- for (uint32 i = 0; i < d.u.s->size(); i++) {
+ Common::String contents = d.asString();
+ for (uint32 i = 0; i < contents.size(); i++) {
if (contents[i] == '\n')
numberoflines++;
}
- delete d.u.s;
- d.u.i = numberoflines;
- d.type = INT;
-
- g_lingo->push(d);
+ Datum res(numberoflines);
+ g_lingo->push(res);
}
void LB::b_numberofwords(int nargs) {
Datum d = g_lingo->pop();
- d.makeString();
int numberofwords = 0;
- Common::String contents = *d.u.s;
+ Common::String contents = d.asString();
if (contents.empty()) {
- d.u.i = 0;
- d.type = INT;
-
- g_lingo->push(d);
-
+ g_lingo->push(Datum(0));
return;
}
- for (uint32 i = 1; i < d.u.s->size(); i++) {
+ for (uint32 i = 1; i < contents.size(); i++) {
if (Common::isSpace(contents[i]) && !Common::isSpace(contents[i - 1]))
numberofwords++;
}
// Count the last word
- if (!Common::isSpace(contents[d.u.s->size() - 1]))
+ if (!Common::isSpace(contents[contents.size() - 1]))
numberofwords++;
- d.u.i = numberofwords;
- d.type = INT;
-
- g_lingo->push(d);
+ Datum res(numberofwords);
+ g_lingo->push(res);
}
void LB::b_lastcharof(int nargs) {
Datum d = g_lingo->pop();
warning("STUB: b_lastcharof");
- d.makeInt();
- d.u.i = 0;
- g_lingo->push(d);
+ g_lingo->push(Datum(0));
}
void LB::b_lastitemof(int nargs) {
Datum d = g_lingo->pop();
warning("STUB: b_lastitemof");
- d.makeInt();
- d.u.i = 0;
- g_lingo->push(d);
+ g_lingo->push(Datum(0));
}
void LB::b_lastlineof(int nargs) {
Datum d = g_lingo->pop();
warning("STUB: b_lastlineof");
- d.makeInt();
- d.u.i = 0;
- g_lingo->push(d);
+ g_lingo->push(Datum(0));
}
void LB::b_lastwordof(int nargs) {
Datum d = g_lingo->pop();
warning("STUB: b_lastwordof");
- d.makeInt();
- d.u.i = 0;
- g_lingo->push(d);
+ g_lingo->push(Datum(0));
}
} // End of namespace Director
diff --git a/engines/director/lingo/lingo-bytecode.cpp b/engines/director/lingo/lingo-bytecode.cpp
index b54306830f..868fa4f1d8 100644
--- a/engines/director/lingo/lingo-bytecode.cpp
+++ b/engines/director/lingo/lingo-bytecode.cpp
@@ -283,9 +283,8 @@ void LC::cb_localcall() {
void LC::cb_methodcall() {
g_lingo->readInt();
- Datum obj = g_lingo->pop();
- obj.makeString();
- warning("STUB: cb_methodcall(%s)", obj.u.s->c_str());
+ Common::String name = g_lingo->pop().asString();
+ warning("STUB: cb_methodcall(%s)", name.c_str());
Datum nargs = g_lingo->pop();
if ((nargs.type == ARGC) || (nargs.type == ARGCNORET)) {
@@ -513,22 +512,21 @@ void LC::cb_varassign() {
void LC::cb_v4theentitypush() {
int bank = g_lingo->readInt();
- Datum firstArg = g_lingo->pop();
- firstArg.makeInt();
+ int firstArg = g_lingo->pop().asInt();
Datum result;
result.u.s = NULL;
result.type = VOID;
- int key = (bank << 8) + firstArg.u.i;
+ int key = (bank << 8) + firstArg;
if (g_lingo->_lingoV4TheEntity.contains(key)) {
- debugC(3, kDebugLingoExec, "cb_v4theentitypush: mapping 0x%02x, 0x%02x", bank, firstArg.u.i);
+ debugC(3, kDebugLingoExec, "cb_v4theentitypush: mapping 0x%02x, 0x%02x", bank, firstArg);
int entity = g_lingo->_lingoV4TheEntity[key]->entity;
int field = g_lingo->_lingoV4TheEntity[key]->field;
switch (g_lingo->_lingoV4TheEntity[key]->type) {
case kTEANOArgs:
{
Datum id;
- id.u.s = NULL;
+ id.u.i = 0;
id.type = VOID;
debugC(3, kDebugLingoExec, "cb_v4theentitypush: calling getTheEntity(0x%02x, NULL, 0x%02x)", entity, field);
result = g_lingo->getTheEntity(entity, id, field);
@@ -559,7 +557,7 @@ void LC::cb_v4theentitypush() {
break;
}
} else {
- warning("cb_v4theentitypush: unhandled mapping 0x%02x 0x%02x", bank, firstArg.u.i);
+ warning("cb_v4theentitypush: unhandled mapping 0x%02x 0x%02x", bank, firstArg);
}
g_lingo->push(result);
@@ -599,24 +597,23 @@ void LC::cb_v4theentitynamepush() {
void LC::cb_v4theentityassign() {
int bank = g_lingo->readInt();
- Datum firstArg = g_lingo->pop();
- firstArg.makeInt();
+ int firstArg = g_lingo->pop().asInt();
Datum value = g_lingo->pop();
Datum result;
result.u.s = NULL;
result.type = VOID;
- int key = (bank << 8) + firstArg.u.i;
+ int key = (bank << 8) + firstArg;
if (!g_lingo->_lingoV4TheEntity.contains(key)) {
- warning("cb_v4theentityassign: unhandled mapping 0x%02x 0x%02x", bank, firstArg.u.i);
+ warning("cb_v4theentityassign: unhandled mapping 0x%02x 0x%02x", bank, firstArg);
return;
}
- debugC(3, kDebugLingoExec, "cb_v4theentityassign: mapping 0x%02x, 0x%02x", bank, firstArg.u.i);
+ debugC(3, kDebugLingoExec, "cb_v4theentityassign: mapping 0x%02x, 0x%02x", bank, firstArg);
if (!g_lingo->_lingoV4TheEntity[key]->writable) {
- warning("cb_v4theentityassign: non-writable mapping 0x%02x 0x%02x", bank, firstArg.u.i);
+ warning("cb_v4theentityassign: non-writable mapping 0x%02x 0x%02x", bank, firstArg);
return;
}
diff --git a/engines/director/lingo/lingo-code.cpp b/engines/director/lingo/lingo-code.cpp
index 124f8cdd0c..e629a5342c 100644
--- a/engines/director/lingo/lingo-code.cpp
+++ b/engines/director/lingo/lingo-code.cpp
@@ -226,22 +226,22 @@ void LC::c_printtop(void) {
}
break;
case STRING:
- warning("%s", d.u.s->c_str());
+ warning("%s", d.asString(true).c_str());
break;
case POINT:
- warning("point(%s, %s", (*d.u.farr)[0].getPrintable().c_str(), (*d.u.farr)[1].getPrintable().c_str());
+ warning("point(%s, %s", (*d.u.farr)[0].asString(true).c_str(), (*d.u.farr)[1].asString(true).c_str());
break;
case SYMBOL:
warning("%s", d.type2str(true));
break;
case OBJECT:
- warning("#%s", d.u.s->c_str());
+ warning("#%s", d.asString(true).c_str());
break;
case ARRAY:
- warning("%s", d.getPrintable().c_str());
+ warning("%s", d.asString(true).c_str());
break;
case PARRAY:
- warning("%s", d.getPrintable().c_str());
+ warning("%s", d.asString(true).c_str());
break;
default:
warning("--unknown--");
@@ -249,10 +249,8 @@ void LC::c_printtop(void) {
}
void LC::c_intpush() {
- Datum d;
- d.u.i = g_lingo->readInt();
- d.type = INT;
- g_lingo->push(d);
+ int value = g_lingo->readInt();
+ g_lingo->push(Datum(value));
}
void LC::c_voidpush() {
@@ -263,15 +261,12 @@ void LC::c_voidpush() {
}
void LC::c_floatpush() {
- Datum d;
- d.u.f = g_lingo->readFloat();
- d.type = FLOAT;
- g_lingo->push(d);
+ double value = g_lingo->readFloat();
+ g_lingo->push(Datum(value));
}
void LC::c_stringpush() {
char *s = g_lingo->readString();
-
g_lingo->push(Datum(new Common::String(s)));
}
@@ -516,7 +511,7 @@ void LC::c_swap() {
g_lingo->push(d1);
}
-Datum LC::mapBinaryOp(Datum (*mapFunc)(Datum, Datum), Datum d1, Datum d2) {
+Datum LC::mapBinaryOp(Datum (*mapFunc)(Datum &, Datum &), Datum &d1, Datum &d2) {
// At least one of d1 and d2 must be an array
uint arraySize;
if (d1.type == ARRAY && d2.type == ARRAY) {
@@ -543,16 +538,22 @@ Datum LC::mapBinaryOp(Datum (*mapFunc)(Datum, Datum), Datum d1, Datum d2) {
return res;
}
-Datum LC::addData(Datum d1, Datum d2) {
+Datum LC::addData(Datum &d1, Datum &d2) {
if (d1.type == ARRAY || d2.type == ARRAY) {
return LC::mapBinaryOp(LC::addData, d1, d2);
}
- if (g_lingo->alignTypes(d1, d2) == FLOAT) {
- d1.u.f += d2.u.f;
+
+ int alignedType = g_lingo->getAlignedType(d1, d2);
+
+ Datum result;
+ if (alignedType == FLOAT) {
+ result = Datum(d1.asFloat() + d2.asFloat());
+ } else if (alignedType == INT) {
+ result = Datum(d1.asInt() + d2.asInt());
} else {
- d1.u.i += d2.u.i;
+ warning("LC::addData: not supported between types %s and %s", d1.type2str(), d2.type2str());
}
- return d1;
+ return result;
}
void LC::c_add() {
@@ -561,16 +562,22 @@ void LC::c_add() {
g_lingo->push(LC::addData(d1, d2));
}
-Datum LC::subData(Datum d1, Datum d2) {
+Datum LC::subData(Datum &d1, Datum &d2) {
if (d1.type == ARRAY || d2.type == ARRAY) {
return LC::mapBinaryOp(LC::subData, d1, d2);
}
- if (g_lingo->alignTypes(d1, d2) == FLOAT) {
- d1.u.f -= d2.u.f;
+
+ int alignedType = g_lingo->getAlignedType(d1, d2);
+
+ Datum result;
+ if (alignedType == FLOAT) {
+ result = Datum(d1.asFloat() - d2.asFloat());
+ } else if (alignedType == INT) {
+ result = Datum(d1.asInt() - d2.asInt());
} else {
- d1.u.i -= d2.u.i;
+ warning("LC::subData: not supported between types %s and %s", d1.type2str(), d2.type2str());
}
- return d1;
+ return result;
}
void LC::c_sub() {
@@ -579,16 +586,22 @@ void LC::c_sub() {
g_lingo->push(LC::subData(d1, d2));
}
-Datum LC::mulData(Datum d1, Datum d2) {
+Datum LC::mulData(Datum &d1, Datum &d2) {
if (d1.type == ARRAY || d2.type == ARRAY) {
return LC::mapBinaryOp(LC::mulData, d1, d2);
}
- if (g_lingo->alignTypes(d1, d2) == FLOAT) {
- d1.u.f *= d2.u.f;
+
+ int alignedType = g_lingo->getAlignedType(d1, d2);
+
+ Datum result;
+ if (alignedType == FLOAT) {
+ result = Datum(d1.asFloat() * d2.asFloat());
+ } else if (alignedType == INT) {
+ result = Datum(d1.asInt() * d2.asInt());
} else {
- d1.u.i *= d2.u.i;
+ warning("LC::mulData: not supported between types %s and %s", d1.type2str(), d2.type2str());
}
- return d1;
+ return result;
}
void LC::c_mul() {
@@ -597,7 +610,7 @@ void LC::c_mul() {
g_lingo->push(LC::mulData(d1, d2));
}
-Datum LC::divData(Datum d1, Datum d2) {
+Datum LC::divData(Datum &d1, Datum &d2) {
if (d1.type == ARRAY || d2.type == ARRAY) {
return LC::mapBinaryOp(LC::divData, d1, d2);
}
@@ -606,11 +619,17 @@ Datum LC::divData(Datum d1, Datum d2) {
(d2.type == FLOAT && d2.u.f == 0.0))
error("division by zero");
- if (g_lingo->alignTypes(d1, d2) == FLOAT) {
- d1.u.f /= d2.u.f;
+ int alignedType = g_lingo->getAlignedType(d1, d2);
+
+ Datum result;
+ if (alignedType == FLOAT) {
+ result = Datum(d1.asFloat() / d2.asFloat());
+ } else if (alignedType == INT) {
+ result = Datum(d1.asInt() / d2.asInt());
} else {
- d1.u.i /= d2.u.i;
+ warning("LC::divData: not supported between types %s and %s", d1.type2str(), d2.type2str());
}
+
return d1;
}
@@ -620,18 +639,18 @@ void LC::c_div() {
g_lingo->push(divData(d1, d2));
}
-Datum LC::modData(Datum d1, Datum d2) {
+Datum LC::modData(Datum &d1, Datum &d2) {
if (d1.type == ARRAY || d2.type == ARRAY) {
return LC::mapBinaryOp(LC::modData, d1, d2);
}
- d1.makeInt();
- d2.makeInt();
- if (d2.u.i == 0)
+ int i1 = d1.asInt();
+ int i2 = d2.asInt();
+ if (i2 == 0)
error("division by zero");
- d1.u.i %= d2.u.i;
- return d1;
+ Datum res(i1 % i2);
+ return res;
}
void LC::c_mod() {
@@ -640,7 +659,7 @@ void LC::c_mod() {
g_lingo->push(LC::modData(d1, d2));
}
-Datum LC::negateData(Datum d) {
+Datum LC::negateData(Datum &d) {
if (d.type == ARRAY) {
uint arraySize = d.u.farr->size();
Datum res;
@@ -652,11 +671,15 @@ Datum LC::negateData(Datum d) {
return res;
}
- if (d.type == INT) {
- d.u.i = -d.u.i;
- } else if (d.type == FLOAT) {
- d.u.f = -d.u.f;
+ Datum res = d;
+ if (res.type == INT) {
+ res.u.i = -res.u.i;
+ } else if (res.type == FLOAT) {
+ res.u.f = -res.u.f;
+ } else {
+ warning("LC::negateData: not supported for type %s", res.type2str());
}
+
return d;
}
@@ -669,14 +692,8 @@ void LC::c_ampersand() {
Datum d2 = g_lingo->pop();
Datum d1 = g_lingo->pop();
- d1.makeString();
- d2.makeString();
-
- *d1.u.s += *d2.u.s;
-
- delete d2.u.s;
-
- g_lingo->push(d1);
+ Datum res(d1.asString() + d2.asString());
+ g_lingo->push(res);
}
void LC::c_before() {
@@ -687,70 +704,38 @@ void LC::c_after() {
Datum d2 = g_lingo->pop();
Datum d1 = g_lingo->pop();
- d1.makeString();
- d2.makeString();
-
- *d1.u.s = *d2.u.s + *d1.u.s;
-
- delete d2.u.s;
-
- g_lingo->push(d1);
+ Datum res(d2.asString() + d1.asString());
+ g_lingo->push(res);
}
void LC::c_concat() {
Datum d2 = g_lingo->pop();
Datum d1 = g_lingo->pop();
- d1.makeString();
- d2.makeString();
-
- *d1.u.s += " ";
- *d1.u.s += *d2.u.s;
-
- delete d2.u.s;
-
- g_lingo->push(d1);
+ Datum res(d1.asString() + " " + d2.asString());
+ g_lingo->push(res);
}
void LC::c_contains() {
Datum d2 = g_lingo->pop();
Datum d1 = g_lingo->pop();
- d1.makeString();
- d2.makeString();
+ Common::String s1 = toLowercaseMac(d1.asString());
+ Common::String s2 = toLowercaseMac(d2.asString());
- Common::String *s1 = toLowercaseMac(d1.u.s);
- Common::String *s2 = toLowercaseMac(d2.u.s);
+ int res = s1.contains(s2) ? 1 : 0;
- int res = s1->contains(*s2) ? 1 : 0;
-
- delete d1.u.s;
- delete d2.u.s;
- delete s1;
- delete s2;
-
- d1.type = INT;
- d1.u.i = res;
-
- g_lingo->push(d1);
+ g_lingo->push(Datum(res));
}
void LC::c_starts() {
Datum d2 = g_lingo->pop();
Datum d1 = g_lingo->pop();
- d1.makeString();
- d2.makeString();
+ Common::String s1 = toLowercaseMac(d1.asString());
+ Common::String s2 = toLowercaseMac(d2.asString());
- Common::String *s1 = toLowercaseMac(d1.u.s);
- Common::String *s2 = toLowercaseMac(d2.u.s);
-
- int res = s1->hasPrefix(*s2) ? 1 : 0;
-
- delete d1.u.s;
- delete d2.u.s;
- delete s1;
- delete s2;
+ int res = s1.hasPrefix(s2) ? 1 : 0;
d1.type = INT;
d1.u.i = res;
@@ -788,8 +773,7 @@ void LC::c_of() {
Datum last_char = g_lingo->pop();
Datum first_char = g_lingo->pop();
- target.makeString();
- Common::String result = *target.u.s;
+ Common::String result = target.asString();
if (first_line.u.i > 0) {
Common::String newline("\r");
@@ -975,34 +959,26 @@ void LC::c_and() {
Datum d2 = g_lingo->pop();
Datum d1 = g_lingo->pop();
- d1.makeInt();
- d2.makeInt();
-
- d1.u.i = (d1.u.i && d2.u.i) ? 1 : 0;
+ Datum res((d1.asInt() && d2.asInt()) ? 1 : 0);
- g_lingo->push(d1);
+ g_lingo->push(res);
}
void LC::c_or() {
Datum d2 = g_lingo->pop();
Datum d1 = g_lingo->pop();
- d1.makeInt();
- d2.makeInt();
-
- d1.u.i = (d1.u.i || d2.u.i) ? 1 : 0;
+ Datum res((d1.asInt() || d2.asInt()) ? 1 : 0);
- g_lingo->push(d1);
+ g_lingo->push(res);
}
void LC::c_not() {
Datum d = g_lingo->pop();
- d.makeInt();
+ Datum res(~d.asInt() ? 1 : 0);
- d.u.i = ~d.u.i ? 1 : 0;
-
- g_lingo->push(d);
+ g_lingo->push(res);
}
Datum LC::compareArrays(Datum (*compareFunc)(Datum, Datum), Datum d1, Datum d2, bool location, bool value) {
@@ -1159,9 +1135,8 @@ void LC::c_jump() {
void LC::c_jumpifz() {
uint jump = g_lingo->readInt();
- Datum test = g_lingo->pop();
- test.makeInt();
- if (test.u.i == 0) {
+ int test = g_lingo->pop().asInt();
+ if (test == 0) {
g_lingo->_pc = jump;
}
}
@@ -1174,10 +1149,9 @@ void LC::c_repeatwhilecode(void) {
uint end = g_lingo->getInt(savepc + 1);
g_lingo->execute(savepc + 2); /* condition */
- d = g_lingo->pop();
- d.makeInt();
+ int test = g_lingo->pop().asInt();
- while (d.u.i) {
+ while (test) {
g_lingo->execute(body + savepc - 1); /* body */
g_lingo->_nextRepeat = false;
@@ -1190,8 +1164,7 @@ void LC::c_repeatwhilecode(void) {
}
g_lingo->execute(savepc + 2); /* condition */
- d = g_lingo->pop();
- d.makeInt();
+ test = g_lingo->pop().asInt();
}
if (!g_lingo->_returning)
@@ -1199,7 +1172,6 @@ void LC::c_repeatwhilecode(void) {
}
void LC::c_repeatwithcode(void) {
- Datum d;
int savepc = g_lingo->_pc;
uint init = g_lingo->getInt(savepc);
@@ -1239,9 +1211,7 @@ void LC::c_repeatwithcode(void) {
}
g_lingo->execute(init + savepc - 1); /* condition */
- d = g_lingo->pop();
- d.makeInt();
- counter->u.i = d.u.i;
+ counter->u.i = g_lingo->pop().asInt();
counter->type = INT;
while (true) {
@@ -1258,10 +1228,9 @@ void LC::c_repeatwithcode(void) {
counter->u.i += inc;
g_lingo->execute(finish + savepc - 1); /* condition */
- d = g_lingo->pop();
- d.makeInt();
+ int base = g_lingo->pop().asInt();
- if (counter->u.i == d.u.i + inc)
+ if (counter->u.i == base + inc)
break;
}
@@ -1293,7 +1262,7 @@ void LC::c_ifcode(void) {
d = g_lingo->pop();
- if (d.makeInt()) {
+ if (d.asInt()) {
debugC(8, kDebugLingoExec, "executing then");
g_lingo->execute(then + savepc - 1);
} else if (elsep) { /* else part? */
@@ -1345,7 +1314,7 @@ void LC::c_tellcode() {
uint start = g_lingo->_pc;
uint end = g_lingo->readInt() + start - 1;
- warning("STUB: c_tellcode(%s)", d1.getPrintable().c_str());
+ warning("STUB: c_tellcode(%s)", d1.asString(true).c_str());
g_lingo->_pc = end;
}
@@ -1622,10 +1591,7 @@ void LC::c_open() {
Datum d2 = g_lingo->pop();
Datum d1 = g_lingo->pop();
- d1.makeString();
- d2.makeString();
-
- warning("STUB: c_open(%s, %s)", d1.u.s->c_str(), d2.u.s->c_str());
+ warning("STUB: c_open(%s, %s)", d1.asString().c_str(), d2.asString().c_str());
}
void LC::c_hilite() {
diff --git a/engines/director/lingo/lingo-code.h b/engines/director/lingo/lingo-code.h
index 6a5789e51d..82b2be01db 100644
--- a/engines/director/lingo/lingo-code.h
+++ b/engines/director/lingo/lingo-code.h
@@ -29,18 +29,18 @@ namespace LC {
void c_xpop();
void c_printtop();
- Datum mapBinaryOp(Datum (*func)(Datum, Datum), Datum d1, Datum d2);
- Datum addData(Datum d1, Datum d2);
+ Datum mapBinaryOp(Datum (*func)(Datum &, Datum &), Datum &d1, Datum &d2);
+ Datum addData(Datum &d1, Datum &d2);
void c_add();
- Datum subData(Datum d1, Datum d2);
+ Datum subData(Datum &d1, Datum &d2);
void c_sub();
- Datum mulData(Datum d1, Datum d2);
+ Datum mulData(Datum &d1, Datum &d2);
void c_mul();
- Datum divData(Datum d1, Datum d2);
+ Datum divData(Datum &d1, Datum &d2);
void c_div();
- Datum modData(Datum d1, Datum d2);
+ Datum modData(Datum &d1, Datum &d2);
void c_mod();
- Datum negateData(Datum d1);
+ Datum negateData(Datum &d1);
void c_negate();
void c_and();
diff --git a/engines/director/lingo/lingo-codegen.cpp b/engines/director/lingo/lingo-codegen.cpp
index d60fa60594..ab0cfaff6c 100644
--- a/engines/director/lingo/lingo-codegen.cpp
+++ b/engines/director/lingo/lingo-codegen.cpp
@@ -92,7 +92,7 @@ void Lingo::printStack(const char *s, uint pc) {
for (uint i = 0; i < _stack.size(); i++) {
Datum d = _stack[i];
- stack += Common::String::format("<%s> ", d.getPrintable().c_str());
+ stack += Common::String::format("<%s> ", d.asString(true).c_str());
}
debugC(5, kDebugLingoExec, "[%3d]: %s", pc, stack.c_str());
}
@@ -506,11 +506,11 @@ int Lingo::castIdFetch(Datum &var) {
else
warning("castIdFetch: reference to non-existent cast member: %s", var.u.s->c_str());
} else if (var.type == INT || var.type == FLOAT) {
- var.makeInt();
- if (!score->_loadedCast->contains(var.u.i))
- warning("castIdFetch: reference to non-existent cast ID: %d", var.u.i);
+ int castId = var.asInt();
+ if (!score->_loadedCast->contains(castId))
+ warning("castIdFetch: reference to non-existent cast ID: %d", castId);
else
- id = var.u.i;
+ id = castId;
} else {
error("castIdFetch: was expecting STRING or INT, got %s", var.type2str());
}
@@ -587,9 +587,7 @@ void Lingo::varAssign(Datum &var, Datum &value) {
if (cast) {
switch (cast->_type) {
case kCastText:
- value.makeString();
- ((TextCast *)cast)->setText(value.u.s->c_str());
- delete value.u.s;
+ ((TextCast *)cast)->setText(value.asString().c_str());
break;
default:
warning("varAssign: Unhandled cast type %s", tag2str(cast->_type));
@@ -621,7 +619,7 @@ Datum Lingo::varFetch(Datum &var) {
else if (sym->type == FLOAT)
result.u.f = sym->u.f;
else if (sym->type == STRING)
- result.u.s = new Common::String(*sym->u.s);
+ result.u.s = sym->u.s;
else if (sym->type == POINT)
result.u.farr = sym->u.farr;
else if (sym->type == SYMBOL)
diff --git a/engines/director/lingo/lingo-funcs.cpp b/engines/director/lingo/lingo-funcs.cpp
index 86f03a1757..8cb2d66675 100644
--- a/engines/director/lingo/lingo-funcs.cpp
+++ b/engines/director/lingo/lingo-funcs.cpp
@@ -72,10 +72,11 @@ struct MCIToken {
{ kMCITokenNone, kMCITokenNone, 0, 0 }
};
-void Lingo::func_mci(Common::String &s) {
+void Lingo::func_mci(const Common::String &name) {
Common::String params[5];
MCITokenType command = kMCITokenNone;
+ Common::String s = name;
s.trim();
s.toLowercase();
@@ -170,8 +171,8 @@ void Lingo::func_mci(Common::String &s) {
}
}
-void Lingo::func_mciwait(Common::String &s) {
- warning("STUB: MCI wait file: %s", s.c_str());
+void Lingo::func_mciwait(const Common::String &name) {
+ warning("STUB: MCI wait file: %s", name.c_str());
}
void Lingo::func_goto(Datum &frame, Datum &movie) {
@@ -181,9 +182,8 @@ void Lingo::func_goto(Datum &frame, Datum &movie) {
return;
if (movie.type != VOID) {
- movie.makeString();
-
- Common::String movieFilename = pathMakeRelative(*movie.u.s);
+ Common::String movieFilenameRaw = movie.asString();
+ Common::String movieFilename = pathMakeRelative(movieFilenameRaw);
Common::String cleanedFilename;
bool fileExists = false;
@@ -213,7 +213,7 @@ void Lingo::func_goto(Datum &frame, Datum &movie) {
}
}
- debug(1, "func_goto: '%s' -> '%s' -> '%s' -> '%s'", movie.u.s->c_str(), convertPath(*movie.u.s).c_str(),
+ debug(1, "func_goto: '%s' -> '%s' -> '%s' -> '%s'", movieFilenameRaw.c_str(), convertPath(movieFilenameRaw).c_str(),
movieFilename.c_str(), cleanedFilename.c_str());
if (!fileExists) {
@@ -235,9 +235,7 @@ void Lingo::func_goto(Datum &frame, Datum &movie) {
return;
}
- frame.makeInt();
-
- _vm->_nextMovie.frameI = frame.u.i;
+ _vm->_nextMovie.frameI = frame.asInt();
return;
}
@@ -253,10 +251,8 @@ void Lingo::func_goto(Datum &frame, Datum &movie) {
return;
}
- frame.makeInt();
-
if (_vm->getCurrentScore())
- _vm->getCurrentScore()->setCurrentFrame(frame.u.i);
+ _vm->getCurrentScore()->setCurrentFrame(frame.asInt());
}
void Lingo::func_gotoloop() {
diff --git a/engines/director/lingo/lingo-the.cpp b/engines/director/lingo/lingo-the.cpp
index 71c655ef80..77756e8f1c 100644
--- a/engines/director/lingo/lingo-the.cpp
+++ b/engines/director/lingo/lingo-the.cpp
@@ -480,7 +480,7 @@ Datum Lingo::getTheEntity(int entity, Datum &id, int field) {
void Lingo::setTheEntity(int entity, Datum &id, int field, Datum &d) {
if (debugChannelSet(3, kDebugLingoExec)) {
- debugC(3, kDebugLingoExec, "Lingo::setTheEntity(\"%s\", %s, \"%s\", %s)", field2str(field), id.getPrintable().c_str(), entity2str(entity), d.getPrintable().c_str());
+ debugC(3, kDebugLingoExec, "Lingo::setTheEntity(\"%s\", %s, \"%s\", %s)", field2str(field), id.asString(true).c_str(), entity2str(entity), d.asString(true).c_str());
}
switch (entity) {
@@ -488,13 +488,13 @@ void Lingo::setTheEntity(int entity, Datum &id, int field, Datum &d) {
setTheCast(id, field, d);
break;
case kTheColorDepth:
- _vm->_colorDepth = d.makeInt();
+ _vm->_colorDepth = d.asInt();
// bpp. 1, 2, 4, 8, 32
warning("STUB: Lingo::setTheEntity(): Set color depth to %d", _vm->_colorDepth);
break;
case kTheFloatPrecision:
- _floatPrecision = d.makeInt();
+ _floatPrecision = d.asInt();
_floatPrecision = MAX(0, MIN(_floatPrecision, 19)); // 0 to 19
_floatPrecisionFormat = Common::String::format("%%.%df", _floatPrecision);
break;
@@ -510,13 +510,13 @@ void Lingo::setTheEntity(int entity, Datum &id, int field, Datum &d) {
}
void Lingo::setTheMenuItemEntity(int entity, Datum &menuId, int field, Datum &menuItemId, Datum &d) {
- warning("STUB: setTheMenuItemEntity(%s, %s, %s, %s, %s)", entity2str(entity), menuId.getPrintable().c_str(), field2str(field),
- menuItemId.getPrintable().c_str(), d.getPrintable().c_str());
+ warning("STUB: setTheMenuItemEntity(%s, %s, %s, %s, %s)", entity2str(entity), menuId.asString(true).c_str(), field2str(field),
+ menuItemId.asString(true).c_str(), d.asString(true).c_str());
}
Datum Lingo::getTheMenuItemEntity(int entity, Datum &menuId, int field, Datum &menuItemId) {
- warning("STUB: getTheMenuItemEntity(%s, %s, %s, %s)", entity2str(entity), menuId.getPrintable().c_str(), field2str(field),
- menuItemId.getPrintable().c_str());
+ warning("STUB: getTheMenuItemEntity(%s, %s, %s, %s)", entity2str(entity), menuId.asString(true).c_str(), field2str(field),
+ menuItemId.asString(true).c_str());
return Datum();
}
@@ -562,8 +562,7 @@ Datum Lingo::getTheSprite(Datum &id1, int field) {
d.u.i = sprite->_constraint;
break;
case kTheEditableText:
- d.makeString();
- d.u.s = &sprite->_editableText;
+ d = Datum(sprite->_editableText);
break;
case kTheForeColor:
d.u.i = sprite->_foreColor;
@@ -644,8 +643,6 @@ void Lingo::setTheSprite(Datum &id1, int field, Datum &d) {
int id = 0;
Score *score = _vm->getCurrentScore();
- d.makeInt(); // Enforce Integer
-
if (!score) {
warning("Lingo::setTheSprite(): The sprite %d field \"%s\" setting over non-active score", id, field2str(field));
return;
@@ -665,94 +662,94 @@ void Lingo::setTheSprite(Datum &id1, int field, Datum &d) {
switch (field) {
case kTheBackColor:
- sprite->_backColor = d.u.i;
+ sprite->_backColor = d.asInt();
break;
case kTheBlend:
- sprite->_blend = d.u.i;
+ sprite->_blend = d.asInt();
break;
case kTheBottom:
- sprite->_bottom = d.u.i;
+ sprite->_bottom = d.asInt();
break;
case kTheCastNum:
- if (score->_loadedCast->contains(d.u.i)) {
- score->loadCastInto(sprite, d.u.i);
- sprite->_castId = d.u.i;
+ if (score->_loadedCast->contains(d.asInt())) {
+ score->loadCastInto(sprite, d.asInt());
+ sprite->_castId = d.asInt();
}
break;
case kTheConstraint:
- sprite->_constraint = d.u.i;
+ sprite->_constraint = d.asInt();
break;
case kTheEditableText:
- sprite->_editableText = *d.makeString();
+ sprite->_editableText = d.asString();
break;
case kTheForeColor:
- sprite->_foreColor = d.u.i;
+ sprite->_foreColor = d.asInt();
break;
case kTheHeight:
- sprite->_height = d.u.i;
+ sprite->_height = d.asInt();
break;
case kTheInk:
- sprite->_ink = static_cast<InkType>(d.u.i);
+ sprite->_ink = static_cast<InkType>(d.asInt());
break;
case kTheLeft:
- sprite->_left = d.u.i;
+ sprite->_left = d.asInt();
break;
case kTheLineSize:
- sprite->_thickness = d.u.i;
+ sprite->_thickness = d.asInt();
break;
case kTheLocH:
- sprite->_currentPoint.x = d.u.i;
+ sprite->_currentPoint.x = d.asInt();
break;
case kTheLocV:
- sprite->_currentPoint.y = d.u.i;
+ sprite->_currentPoint.y = d.asInt();
break;
case kTheMoveableSprite:
- sprite->_moveable = d.u.i;
+ sprite->_moveable = d.asInt();
if (!d.u.i)
sprite->_currentPoint = sprite->_startPoint;
break;
case kTheMovieRate:
- sprite->_movieRate = d.u.i;
+ sprite->_movieRate = d.asInt();
break;
case kTheMovieTime:
- sprite->_movieTime = d.u.i;
+ sprite->_movieTime = d.asInt();
break;
case kThePattern:
- sprite->setPattern(d.u.i);
+ sprite->setPattern(d.asInt());
break;
case kThePuppet:
- sprite->_puppet = d.u.i;
+ sprite->_puppet = d.asInt();
break;
case kTheRight:
- sprite->_right = d.u.i;
+ sprite->_right = d.asInt();
break;
case kTheStartTime:
- sprite->_startTime = d.u.i;
+ sprite->_startTime = d.asInt();
break;
case kTheStopTime:
- sprite->_stopTime = d.u.i;
+ sprite->_stopTime = d.asInt();
break;
case kTheStretch:
- sprite->_stretch = d.u.i;
+ sprite->_stretch = d.asInt();
break;
case kTheTop:
- sprite->_top = d.u.i;
+ sprite->_top = d.asInt();
break;
case kTheTrails:
- sprite->_trails = d.u.i;
+ sprite->_trails = d.asInt();
break;
case kTheType:
- sprite->_spriteType = static_cast<SpriteType>(d.u.i);
+ sprite->_spriteType = static_cast<SpriteType>(d.asInt());
break;
case kTheVisibility:
case kTheVisible:
- sprite->_visible = (d.u.i == 0 ? false : true);
+ sprite->_visible = (d.asInt() == 0 ? false : true);
break;
case kTheVolume:
- sprite->_volume = d.u.i;
+ sprite->_volume = d.asInt();
break;
case kTheWidth:
- sprite->_width = d.u.i;
+ sprite->_width = d.asInt();
break;
default:
warning("Lingo::setTheSprite(): Unprocessed setting field \"%s\" of sprite", field2str(field));
@@ -809,8 +806,7 @@ Datum Lingo::getTheCast(Datum &id1, int field) {
d.u.i = castType;
break;
case kTheFileName:
- d.makeString();
- d.u.s = &castInfo->fileName;
+ d = Datum(castInfo->fileName);
break;
case kTheForeColor:
{
@@ -831,24 +827,24 @@ Datum Lingo::getTheCast(Datum &id1, int field) {
d.u.i = 1; //Not loaded handled above
break;
case kTheName:
- d.type = STRING;
- d.u.s = new Common::String(castInfo->name.c_str());
+ d = Datum(castInfo->name);
break;
case kTheScriptText:
- d.type = STRING;
- d.u.s = new Common::String(castInfo->script.c_str());
+ d = Datum(castInfo->script);
break;
case kTheText:
- d.makeString();
- *d.u.s = "";
- if (castType == kCastText) {
- if (score->_loadedCast->contains(id) && score->_loadedCast->getVal(id)->_type == kCastText) {
- *d.u.s = ((TextCast *)score->_loadedCast->getVal(id))->getText();
+ {
+ Common::String text;
+ if (castType == kCastText) {
+ if (score->_loadedCast->contains(id) && score->_loadedCast->getVal(id)->_type == kCastText) {
+ text = ((TextCast *)score->_loadedCast->getVal(id))->getText();
+ } else {
+ warning("Lingo::getTheCast(): Unknown STXT cast id %d", id);
+ }
} else {
- warning("Lingo::getTheCast(): Unknown STXT cast id %d", id);
+ warning("Lingo::getTheCast(): Unprocessed getting text of cast %d type %d", id, castType);
}
- } else {
- warning("Lingo::getTheCast(): Unprocessed getting text of cast %d type %d", id, castType);
+ d = Datum(text);
}
break;
case kTheWidth:
@@ -893,8 +889,7 @@ void Lingo::setTheCast(Datum &id1, int field, Datum &d) {
}
ShapeCast *shape = (ShapeCast *)score->_loadedCast->getVal(id);
- d.makeInt();
- shape->_bgCol = d.u.i;
+ shape->_bgCol = d.asInt();
shape->_modified = 1;
}
break;
@@ -909,8 +904,7 @@ void Lingo::setTheCast(Datum &id1, int field, Datum &d) {
warning("Lingo::setTheCast(): The cast %d not found. type: %d", id, castType);
return;
}
- d.makeString();
- castInfo->fileName = *d.u.s;
+ castInfo->fileName = d.asString();
break;
case kTheForeColor:
{
@@ -924,8 +918,7 @@ void Lingo::setTheCast(Datum &id1, int field, Datum &d) {
}
break;
case kTheHeight:
- d.makeInt();
- score->getCastMemberInitialRect(id).setHeight(d.u.i);
+ score->getCastMemberInitialRect(id).setHeight(d.asInt());
score->setCastMemberModified(id);
break;
case kTheName:
@@ -933,24 +926,21 @@ void Lingo::setTheCast(Datum &id1, int field, Datum &d) {
warning("Lingo::setTheCast(): The cast %d not found. type: %d", id, castType);
return;
}
- d.makeString();
- castInfo->name = *d.u.s;
+ castInfo->name = d.asString();
break;
case kTheScriptText:
if (!castInfo) {
warning("Lingo::setTheCast(): The cast %d not found. type: %d", id, castType);
return;
}
- d.makeString();
addCode(d.u.s->c_str(), kSpriteScript, id);
- castInfo->script = *d.u.s;
+ castInfo->script = d.asString();
break;
case kTheText:
if (castType == kCastText) {
if (score->_loadedCast->contains(id) && score->_loadedCast->getVal(id)->_type == kCastText) {
- d.makeString();
- ((TextCast *)score->_loadedCast->getVal(id))->setText(d.u.s->c_str());
+ ((TextCast *)score->_loadedCast->getVal(id))->setText(d.asString().c_str());
} else {
warning("Lingo::setTheCast(): Unknown STXT cast id %d", id);
return;
@@ -960,8 +950,7 @@ void Lingo::setTheCast(Datum &id1, int field, Datum &d) {
}
break;
case kTheWidth:
- d.makeInt();
- score->getCastMemberInitialRect(id).setWidth(d.u.i);
+ score->getCastMemberInitialRect(id).setWidth(d.asInt());
score->setCastMemberModified(id);
break;
default:
diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index 1372bd40c0..e72f2ec8de 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -40,6 +40,8 @@ Lingo *g_lingo;
Symbol::Symbol() {
type = VOID;
u.s = nullptr;
+ refCount = new int;
+ *refCount = 1;
nargs = 0;
maxArgs = 0;
parens = true;
@@ -50,6 +52,56 @@ Symbol::Symbol() {
archiveIndex = 0;
}
+Symbol::Symbol(const Symbol &s) {
+ type = s.type;
+ u.s = s.u.s;
+ refCount = s.refCount;
+ *refCount += 1;
+ nargs = s.nargs;
+ maxArgs = s.maxArgs;
+ parens = s.parens;
+ global = s.global;
+ argNames = s.argNames;
+ varNames = s.varNames;
+ ctx = s.ctx;
+ archiveIndex = s.archiveIndex;
+}
+
+Symbol::~Symbol() {
+ *refCount -= 1;
+ if (*refCount <= 0) {
+ switch (type) {
+ case HANDLER:
+ delete u.defn;
+ break;
+ case STRING:
+ delete u.s;
+ break;
+ case ARRAY:
+ // fallthrough
+ case POINT:
+ // fallthrough
+ case RECT:
+ delete u.farr;
+ break;
+ case PARRAY:
+ delete u.parr;
+ break;
+ case VAR:
+ // fallthrough
+ case REFERENCE:
+ // fallthrough
+ case INT:
+ // fallthrough
+ case FLOAT:
+ // fallthrough
+ default:
+ break;
+ }
+ delete refCount;
+ }
+}
+
PCell::PCell() {
p = nullptr;
v = nullptr;
@@ -347,113 +399,101 @@ void Lingo::restartLingo() {
// tuneousScript is not reset
}
-int Lingo::alignTypes(Datum &d1, Datum &d2) {
+int Lingo::getAlignedType(Datum &d1, Datum &d2) {
int opType = VOID;
- if (d1.type == REFERENCE || d1.type == SYMBOL)
- d1.makeString();
+ int d1Type = d1.type;
+ int d2Type = d2.type;
- if (d2.type == REFERENCE || d2.type == SYMBOL)
- d2.makeString();
-
- if (d1.type == STRING) {
+ if (d1Type == STRING || d1Type == REFERENCE) {
+ Common::String src = d1.asString();
char *endPtr = 0;
- double d = strtod(d1.u.s->c_str(), &endPtr);
+ strtod(src.c_str(), &endPtr);
if (*endPtr == 0) {
- d1.type = FLOAT;
- d1.u.f = d;
+ d1Type = FLOAT;
} else {
- warning("Unable to parse '%s' as a number", d1.u.s->c_str());
+ warning("getAlignedType(): Unable to parse '%s' as a number", src.c_str());
}
}
- if (d2.type == STRING) {
+ if (d2Type == STRING || d1Type == REFERENCE) {
+ Common::String src = d1.asString();
char *endPtr = 0;
- double d = strtod(d2.u.s->c_str(), &endPtr);
+ strtod(src.c_str(), &endPtr);
if (*endPtr == 0) {
- d2.type = FLOAT;
- d2.u.f = d;
+ d2Type = FLOAT;
} else {
- warning("Unable to parse '%s' as a number", d2.u.s->c_str());
+ warning("getAlignedType(): Unable to parse '%s' as a number", src.c_str());
}
}
-
- if (d1.type == FLOAT || d2.type == FLOAT) {
+ if (d1Type == FLOAT || d2Type == FLOAT) {
opType = FLOAT;
- d1.makeFloat();
- d2.makeFloat();
- } else if (d1.type == INT && d2.type == INT) {
+ } else if (d1Type == INT && d2Type == INT) {
opType = INT;
} else {
- warning("No numeric type alignment available");
+ warning("getAlignedType(): No numeric type alignment available");
}
return opType;
}
-int Datum::makeInt() {
+int Datum::asInt() {
+ int res = 0;
+
switch (type) {
case REFERENCE:
- makeString();
// fallthrough
case STRING:
{
+ Common::String src = asString();
char *endPtr = 0;
- int result = strtol(u.s->c_str(), &endPtr, 10);
+ int result = strtol(src.c_str(), &endPtr, 10);
if (*endPtr == 0) {
- u.i = result;
+ res = result;
} else {
- warning("Invalid int '%s'", u.s->c_str());
- u.i = 0;
+ warning("Invalid int '%s'", src.c_str());
}
}
break;
case VOID:
- u.i = 0;
+ // no-op
break;
case INT:
- // no-op
+ res = u.i;
break;
case FLOAT:
- {
- int tmp = (int)u.f;
- u.i = tmp;
- break;
- }
+ res = (int)u.f;
+ break;
default:
- warning("Incorrect operation makeInt() for type: %s", type2str());
+ warning("Incorrect operation asInt() for type: %s", type2str());
}
- type = INT;
-
- return u.i;
+ return res;
}
-double Datum::makeFloat() {
+double Datum::asFloat() {
+ double res = 0.0;
+
switch (type) {
case REFERENCE:
- makeString();
// fallthrough
case STRING:
{
+ Common::String src = asString();
char *endPtr = 0;
- double result = strtod(u.s->c_str(), &endPtr);
+ double result = strtod(src.c_str(), &endPtr);
if (*endPtr == 0) {
- u.f = result;
+ res = result;
} else {
- warning("Invalid float '%s'", u.s->c_str());
- u.f = 0.0;
+ warning("Invalid float '%s'", src.c_str());
}
}
break;
case VOID:
- u.f = 0.0;
+ // no-op
break;
case INT:
- {
- double tmp = (double)u.i;
- u.f = tmp;
- }
+ res = (double)u.i;
break;
case FLOAT:
// no-op
@@ -462,54 +502,52 @@ double Datum::makeFloat() {
warning("Incorrect operation makeFloat() for type: %s", type2str());
}
- type = FLOAT;
-
- return u.f;
+ return res;
}
-Common::String *Datum::makeString(bool printonly) {
- Common::String *s = new Common::String();
+Common::String Datum::asString(bool printonly) {
+ Common::String s;
switch (type) {
case INT:
- *s = Common::String::format("%d", u.i);
+ s = Common::String::format("%d", u.i);
break;
case ARGC:
- *s = Common::String::format("argc: %d", u.i);
+ s = Common::String::format("argc: %d", u.i);
break;
case ARGCNORET:
- *s = Common::String::format("argcnoret: %d", u.i);
+ s = Common::String::format("argcnoret: %d", u.i);
break;
case FLOAT:
- *s = Common::String::format(g_lingo->_floatPrecisionFormat.c_str(), u.f);
+ s = Common::String::format(g_lingo->_floatPrecisionFormat.c_str(), u.f);
if (printonly)
- *s += "f"; // 0.0f
+ s += "f"; // 0.0f
break;
case STRING:
if (!printonly) {
- *s = *u.s;
+ s = *u.s;
} else {
- *s = Common::String::format("\"%s\"", u.s->c_str());
+ s = Common::String::format("\"%s\"", u.s->c_str());
}
break;
case SYMBOL:
if (!printonly) {
- *s = Common::String::format("#%s", u.s->c_str());
+ s = Common::String::format("#%s", u.s->c_str());
} else {
- *s = Common::String::format("symbol: #%s", u.s->c_str());
+ s = Common::String::format("symbol: #%s", u.s->c_str());
}
break;
case OBJECT:
if (!printonly) {
- *s = Common::String::format("#%s", u.s->c_str());
+ s = Common::String::format("#%s", u.s->c_str());
} else {
- *s = Common::String::format("object: #%s", u.s->c_str());
+ s = Common::String::format("object: #%s", u.s->c_str());
}
break;
case VOID:
- *s = "#void";
+ s = "#void";
break;
case VAR:
- *s = Common::String::format("var: #%s", u.sym->name.c_str());
+ s = Common::String::format("var: #%s", u.sym->name.c_str());
break;
case REFERENCE:
{
@@ -517,15 +555,15 @@ Common::String *Datum::makeString(bool printonly) {
Score *score = g_director->getCurrentScore();
if (!score) {
- warning("makeString(): No score");
- *s = "";
+ warning("asString(): No score");
+ s = "";
break;
}
if (!score->_loadedCast->contains(idx)) {
if (!score->_loadedCast->contains(idx - score->_castIDoffset)) {
- warning("makeString(): Unknown REFERENCE %d", idx);
- *s = "";
+ warning("asString(): Unknown REFERENCE %d", idx);
+ s = "";
break;
} else {
idx -= 1024;
@@ -533,49 +571,43 @@ Common::String *Datum::makeString(bool printonly) {
}
if (!printonly) {
- *s = ((TextCast *)score->_loadedCast->getVal(idx))->getText();
+ s = ((TextCast *)score->_loadedCast->getVal(idx))->getText();
} else {
- *s = Common::String::format("reference: \"%s\"", ((TextCast *)score->_loadedCast->getVal(idx))->getText().c_str());
+ s = Common::String::format("reference: \"%s\"", ((TextCast *)score->_loadedCast->getVal(idx))->getText().c_str());
}
}
break;
case ARRAY:
- *s = "[";
+ s = "[";
for (uint i = 0; i < u.farr->size(); i++) {
if (i > 0)
- *s += ", ";
+ s += ", ";
Datum d = u.farr->operator[](i);
- *s += *d.makeString(printonly);
+ s += d.asString(printonly);
}
- *s += "]";
+ s += "]";
break;
case PARRAY:
- *s = "[";
+ s = "[";
if (u.parr->size() == 0)
- *s += ":";
+ s += ":";
for (uint i = 0; i < u.parr->size(); i++) {
if (i > 0)
- *s += ", ";
+ s += ", ";
Datum p = *u.parr->operator[](i).p;
Datum v = *u.parr->operator[](i).v;
- *s += Common::String::format("%s:%s", p.makeString(printonly)->c_str(), v.makeString(printonly)->c_str());
+ s += Common::String::format("%s:%s", p.asString(printonly).c_str(), v.asString(printonly).c_str());
}
- *s += "]";
+ s += "]";
break;
default:
- warning("Incorrect operation makeString() for type: %s", type2str());
+ warning("Incorrect operation asString() for type: %s", type2str());
}
- if (printonly)
- return s;
-
- u.s = s;
- type = STRING;
-
- return u.s;
+ return s;
}
const char *Datum::type2str(bool isk) {
@@ -608,31 +640,40 @@ const char *Datum::type2str(bool isk) {
}
}
-int Datum::compareTo(Datum d, bool ignoreCase) {
+int Datum::compareTo(Datum &d, bool ignoreCase) {
if (type == STRING && d.type == STRING) {
if (ignoreCase) {
- return toLowercaseMac(u.s)->compareTo(*toLowercaseMac(d.u.s));
+ return toLowercaseMac(*u.s).compareTo(toLowercaseMac(*d.u.s));
} else {
return u.s->compareTo(*d.u.s);
}
} else if (type == SYMBOL && d.type == SYMBOL) {
// TODO: Implement union comparisons
return ignoreCase ? u.sym->name.compareToIgnoreCase(d.u.sym->name) : u.sym->name.compareTo(d.u.sym->name);
- } else if (g_lingo->alignTypes(*this, d) == FLOAT) {
- if (u.f < d.u.f) {
- return -1;
- } else if (u.f == d.u.f) {
- return 0;
- } else {
- return 1;
- }
} else {
- if (u.i < d.u.i) {
- return -1;
- } else if (u.i == d.u.i) {
- return 0;
+ int alignType = g_lingo->getAlignedType(*this, d);
+ if (alignType == FLOAT) {
+ double f1 = asFloat();
+ double f2 = d.asFloat();
+ if (f1 < f2) {
+ return -1;
+ } else if (f1 == f2) {
+ return 0;
+ } else {
+ return 1;
+ }
+ } else if (alignType == INT) {
+ double i1 = asInt();
+ double i2 = asInt();
+ if (i1 < i2) {
+ return -1;
+ } else if (i1 == i2) {
+ return 0;
+ } else {
+ return 1;
+ }
} else {
- return 1;
+ error("Invalid comparison between types %s and %s", type2str(), d.type2str());
}
}
}
diff --git a/engines/director/lingo/lingo.h b/engines/director/lingo/lingo.h
index 733bacd373..dec242fe3a 100644
--- a/engines/director/lingo/lingo.h
+++ b/engines/director/lingo/lingo.h
@@ -73,13 +73,16 @@ struct Symbol { /* symbol table entry */
union {
int i; /* VAR */
double f; /* FLOAT */
- ScriptData *defn; /* FUNCTION, PROCEDURE */
+ ScriptData *defn; /* HANDLER */
void (*func)(); /* OPCODE */
void (*bltin)(int); /* BUILTIN */
Common::String *s; /* STRING */
DatumArray *farr; /* ARRAY, POINT, RECT */
PropertyArray *parr;
} u;
+
+ int *refCount;
+
int nargs; /* number of arguments */
int maxArgs; /* maximal number of arguments, for builtins */
bool parens; /* whether parens required or not, for builitins */
@@ -91,6 +94,8 @@ struct Symbol { /* symbol table entry */
int archiveIndex; /* optional archive to execute with */
Symbol();
+ Symbol(const Symbol &s);
+ ~Symbol();
};
struct PCell {
@@ -113,19 +118,83 @@ struct Datum { /* interpreter stack type */
PropertyArray *parr; /* PARRAY */
} u;
- Datum() { u.sym = NULL; type = VOID; }
- Datum(int val) { u.i = val; type = INT; }
- Datum(double val) { u.f = val; type = FLOAT; }
- Datum(Common::String *val) { u.s = val; type = STRING; }
+ int *refCount;
+
+ Datum() {
+ u.sym = NULL;
+ type = VOID;
+ refCount = new int;
+ *refCount = 1;
+ }
+ Datum(const Datum &d) {
+ type = d.type;
+ u = d.u;
+ refCount = d.refCount;
+ *refCount += 1;
+ }
+ Datum(int val) {
+ u.i = val;
+ type = INT;
+ refCount = new int;
+ *refCount = 1;
+ }
+ Datum(double val) {
+ u.f = val;
+ type = FLOAT;
+ refCount = new int;
+ *refCount = 1;
+ }
+ Datum(const Common::String &val) {
+ u.s = new Common::String(val);
+ type = STRING;
+ refCount = new int;
+ *refCount = 1;
+ }
+ Datum(Common::String *val) {
+ u.s = val;
+ type = STRING;
+ refCount = new int;
+ *refCount = 1;
+ }
+ ~Datum() {
+ *refCount -= 1;
+ if (*refCount <= 0) {
+ switch (type) {
+ case STRING:
+ delete u.s;
+ break;
+ case ARRAY:
+ // fallthrough
+ case POINT:
+ // fallthrough
+ case RECT:
+ delete u.farr;
+ break;
+ case PARRAY:
+ delete u.parr;
+ break;
+ case VAR:
+ // fallthrough
+ case REFERENCE:
+ // fallthrough
+ case INT:
+ // fallthrough
+ case FLOAT:
+ // fallthrough
+ default:
+ break;
+ }
+ delete refCount;
+ }
+ }
- double makeFloat();
- int makeInt();
- Common::String *makeString(bool printonly = false);
- Common::String getPrintable() { return *makeString(true); }
+ double asFloat();
+ int asInt();
+ Common::String asString(bool printonly = false);
const char *type2str(bool isk = false);
- int compareTo(Datum d, bool ignoreCase = false);
+ int compareTo(Datum &d, bool ignoreCase = false);
};
struct Builtin {
@@ -225,7 +294,7 @@ public:
void varAssign(Datum &var, Datum &value);
Datum varFetch(Datum &var);
- int alignTypes(Datum &d1, Datum &d2);
+ int getAlignedType(Datum &d1, Datum &d2);
void printAllVars();
@@ -271,8 +340,8 @@ public:
void factoryCall(Common::String &name, int nargs);
- void func_mci(Common::String &s);
- void func_mciwait(Common::String &s);
+ void func_mci(const Common::String &name);
+ void func_mciwait(const Common::String &name);
void func_beep(int repeats);
void func_goto(Datum &frame, Datum &movie);
void func_gotoloop();
diff --git a/engines/director/util.cpp b/engines/director/util.cpp
index 599f64abd3..04755940ce 100644
--- a/engines/director/util.cpp
+++ b/engines/director/util.cpp
@@ -84,22 +84,22 @@ static char lowerCaseConvert[] =
".. aao.." // c8
"--.....y";// d0-d8
-Common::String *toLowercaseMac(Common::String *s) {
- Common::String *res = new Common::String;
- const unsigned char *p = (const unsigned char *)s->c_str();
+Common::String toLowercaseMac(const Common::String &s) {
+ Common::String res;
+ const unsigned char *p = (const unsigned char *)s.c_str();
while (*p) {
if (*p >= 0x80 && *p <= 0xd8) {
if (lowerCaseConvert[*p - 0x80] != '.')
- *res += lowerCaseConvert[*p - 0x80];
+ res += lowerCaseConvert[*p - 0x80];
else
- *res += *p;
+ res += *p;
} else if (*p < 0x80) {
- *res += tolower(*p);
+ res += tolower(*p);
} else {
warning("Unacceptable symbol in toLowercaseMac: %c", *p);
- *res += *p;
+ res += *p;
}
p++;
}
diff --git a/engines/director/util.h b/engines/director/util.h
index f9401f3f6b..23447da4bf 100644
--- a/engines/director/util.h
+++ b/engines/director/util.h
@@ -32,7 +32,7 @@ namespace Director {
int castNumToNum(const char *str);
char *numToCastNum(int num);
-Common::String *toLowercaseMac(Common::String *s);
+Common::String toLowercaseMac(const Common::String &s);
Common::String convertPath(Common::String &path);
Commit: ceb81566df7e31ad1946e8f29be546b5e7766a6d
https://github.com/scummvm/scummvm/commit/ceb81566df7e31ad1946e8f29be546b5e7766a6d
Author: Scott Percival (code at moral.net.au)
Date: 2020-05-12T01:13:19+08:00
Commit Message:
DIRECTOR: LINGO: Add copy assignment operator for Datum/Symbol
Changed paths:
engines/director/lingo/lingo-builtins.cpp
engines/director/lingo/lingo-codegen.cpp
engines/director/lingo/lingo.cpp
engines/director/lingo/lingo.h
diff --git a/engines/director/lingo/lingo-builtins.cpp b/engines/director/lingo/lingo-builtins.cpp
index 3ad6e07416..b024345ed5 100644
--- a/engines/director/lingo/lingo-builtins.cpp
+++ b/engines/director/lingo/lingo-builtins.cpp
@@ -714,7 +714,7 @@ void LB::b_getaProp(int nargs) {
Datum d;
int index = LC::compareArrays(LC::eqData, list, prop, true).u.i;
if (index > 0) {
- d = *list.u.parr->operator[](index-1).v;
+ d = *list.u.parr->operator[](index - 1).v;
}
g_lingo->push(d);
break;
@@ -777,7 +777,7 @@ void LB::b_getOne(int nargs) {
Datum d;
int index = LC::compareArrays(LC::eqData, list, val, true, true).u.i;
if (index > 0) {
- d = *list.u.parr->operator[](index-1).p;
+ d = *list.u.parr->operator[](index - 1).p;
}
g_lingo->push(d);
break;
@@ -791,6 +791,7 @@ void LB::b_getPos(int nargs) {
ARGNUMCHECK(2);
Datum val = g_lingo->pop();
Datum list = g_lingo->pop();
+ TYPECHECK2(val, INT, FLOAT);
TYPECHECK2(list, ARRAY, PARRAY);
switch (list.type) {
@@ -832,7 +833,7 @@ void LB::b_getProp(int nargs) {
case PARRAY: {
int index = LC::compareArrays(LC::eqData, list, prop, true).u.i;
if (index > 0) {
- g_lingo->push(*list.u.parr->operator[](index-1).v);
+ g_lingo->push(*list.u.parr->operator[](index - 1).v);
} else {
error("b_getProp: Property %s not found", prop.asString().c_str());
}
@@ -845,11 +846,14 @@ void LB::b_getProp(int nargs) {
void LB::b_getPropAt(int nargs) {
ARGNUMCHECK(2);
- int index = g_lingo->pop().asInt();
+
+ Datum indexD = g_lingo->pop();
Datum list = g_lingo->pop();
+ TYPECHECK2(indexD, INT, FLOAT);
TYPECHECK(list, PARRAY);
+ int index = indexD.asInt();
- g_lingo->push(*list.u.parr->operator[](index-1).p);
+ g_lingo->push(*list.u.parr->operator[](index - 1).p);
}
void LB::b_list(int nargs) {
@@ -955,7 +959,7 @@ void LB::b_setaProp(int nargs) {
case PARRAY: {
int index = LC::compareArrays(LC::eqData, list, prop, true).u.i;
if (index > 0) {
- *list.u.parr->operator[](index-1).v = value;
+ *list.u.parr->operator[](index - 1).v = value;
} else {
PCell cell = PCell(prop, value);
list.u.parr->push_back(cell);
@@ -970,15 +974,17 @@ void LB::b_setaProp(int nargs) {
void LB::b_setAt(int nargs) {
ARGNUMCHECK(3);
Datum value = g_lingo->pop();
- int index = g_lingo->pop().asInt();
+ Datum indexD = g_lingo->pop();
Datum list = g_lingo->pop();
+ TYPECHECK2(indexD, INT, FLOAT);
TYPECHECK2(list, ARRAY, PARRAY);
+ int index = indexD.asInt();
switch (list.type) {
case ARRAY:
if ((uint)index < list.u.farr->size()) {
- list.u.farr->operator[](index-1) = value;
+ list.u.farr->operator[](index - 1) = value;
} else {
// TODO: Extend the list if we request an index beyond it
ARRBOUNDSCHECK(index, list);
@@ -986,7 +992,7 @@ void LB::b_setAt(int nargs) {
break;
case PARRAY:
ARRBOUNDSCHECK(index, list);
- *list.u.parr->operator[](index-1).v = value;
+ *list.u.parr->operator[](index - 1).v = value;
break;
default:
break;
@@ -1004,7 +1010,7 @@ void LB::b_setProp(int nargs) {
int index = LC::compareArrays(LC::eqData, list, prop, true).u.i;
if (index > 0) {
- *list.u.parr->operator[](index-1).v = value;
+ *list.u.parr->operator[](index - 1).v = value;
} else {
warning("b_setProp: Property not found");
}
diff --git a/engines/director/lingo/lingo-codegen.cpp b/engines/director/lingo/lingo-codegen.cpp
index ab0cfaff6c..417318805b 100644
--- a/engines/director/lingo/lingo-codegen.cpp
+++ b/engines/director/lingo/lingo-codegen.cpp
@@ -269,10 +269,10 @@ Symbol *Lingo::define(Common::String &name, int nargs, ScriptData *code) {
warning("Redefining handler '%s'", name.c_str());
// Do not attempt to remove code from built-ins
- if (sym->type == HANDLER)
- delete sym->u.defn;
- else
- sym->type = HANDLER;
+ sym->reset();
+ sym->refCount = new int;
+ *sym->refCount = 1;
+ sym->type = HANDLER;
}
sym->u.defn = code;
@@ -538,27 +538,20 @@ void Lingo::varAssign(Datum &var, Datum &value) {
return;
}
- if ((sym->type == STRING || sym->type == VOID) && sym->u.s) // Free memory if needed
- delete var.u.sym->u.s;
-
- if (sym->type == POINT || sym->type == RECT || sym->type == ARRAY)
- delete var.u.sym->u.farr;
- else if (sym->type == PARRAY)
- delete var.u.sym->u.parr;
-
+ sym->reset();
+ sym->refCount = value.refCount;
+ *sym->refCount += 1;
sym->type = value.type;
if (value.type == INT) {
sym->u.i = value.u.i;
} else if (value.type == FLOAT) {
sym->u.f = value.u.f;
} else if (value.type == STRING) {
- sym->u.s = new Common::String(*value.u.s);
- delete value.u.s;
+ sym->u.s = value.u.s;
} else if (value.type == POINT || value.type == ARRAY) {
- sym->u.farr = new DatumArray(*value.u.farr);
- delete value.u.farr;
+ sym->u.farr = value.u.farr;
} else if (value.type == PARRAY) {
- sym->u.parr = new PropertyArray(*value.u.parr);
+ sym->u.parr = value.u.parr;
} else if (value.type == SYMBOL) {
sym->u.s = value.u.s;
} else if (value.type == OBJECT) {
@@ -575,15 +568,16 @@ void Lingo::varAssign(Datum &var, Datum &value) {
warning("varAssign: Assigning to a reference to an empty score");
return;
}
- if (!score->_loadedCast->contains(var.u.i)) {
- if (!score->_loadedCast->contains(var.u.i - score->_castIDoffset)) {
- warning("varAssign: Unknown REFERENCE %d", var.u.i);
+ int referenceId = var.u.i;
+ if (!score->_loadedCast->contains(referenceId)) {
+ if (!score->_loadedCast->contains(referenceId - score->_castIDoffset)) {
+ warning("varAssign: Unknown REFERENCE %d", referenceId);
return;
} else {
- var.u.i -= score->_castIDoffset;
+ referenceId -= score->_castIDoffset;
}
}
- Cast *cast = score->_loadedCast->getVal(var.u.i);
+ Cast *cast = score->_loadedCast->getVal(referenceId);
if (cast) {
switch (cast->_type) {
case kCastText:
@@ -613,6 +607,9 @@ Datum Lingo::varFetch(Datum &var) {
}
result.type = sym->type;
+ delete result.refCount;
+ result.refCount = sym->refCount;
+ *result.refCount += 1;
if (sym->type == INT)
result.u.i = sym->u.i;
diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index e72f2ec8de..76a08ae76d 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -67,7 +67,26 @@ Symbol::Symbol(const Symbol &s) {
archiveIndex = s.archiveIndex;
}
-Symbol::~Symbol() {
+Symbol& Symbol::operator=(const Symbol &s) {
+ if (this != &s) {
+ reset();
+ type = s.type;
+ u.s = s.u.s;
+ refCount = s.refCount;
+ *refCount += 1;
+ nargs = s.nargs;
+ maxArgs = s.maxArgs;
+ parens = s.parens;
+ global = s.global;
+ argNames = s.argNames;
+ varNames = s.varNames;
+ ctx = s.ctx;
+ archiveIndex = s.archiveIndex;
+ }
+ return *this;
+}
+
+void Symbol::reset() {
*refCount -= 1;
if (*refCount <= 0) {
switch (type) {
@@ -102,6 +121,10 @@ Symbol::~Symbol() {
}
}
+Symbol::~Symbol() {
+ reset();
+}
+
PCell::PCell() {
p = nullptr;
v = nullptr;
@@ -664,7 +687,7 @@ int Datum::compareTo(Datum &d, bool ignoreCase) {
}
} else if (alignType == INT) {
double i1 = asInt();
- double i2 = asInt();
+ double i2 = d.asInt();
if (i1 < i2) {
return -1;
} else if (i1 == i2) {
diff --git a/engines/director/lingo/lingo.h b/engines/director/lingo/lingo.h
index dec242fe3a..b460e840b5 100644
--- a/engines/director/lingo/lingo.h
+++ b/engines/director/lingo/lingo.h
@@ -95,6 +95,8 @@ struct Symbol { /* symbol table entry */
Symbol();
Symbol(const Symbol &s);
+ Symbol& operator=(const Symbol &s);
+ void reset();
~Symbol();
};
@@ -132,6 +134,16 @@ struct Datum { /* interpreter stack type */
refCount = d.refCount;
*refCount += 1;
}
+ Datum& operator=(const Datum &d) {
+ if (this != &d) {
+ reset();
+ type = d.type;
+ u = d.u;
+ refCount = d.refCount;
+ *refCount += 1;
+ }
+ return *this;
+ }
Datum(int val) {
u.i = val;
type = INT;
@@ -156,7 +168,7 @@ struct Datum { /* interpreter stack type */
refCount = new int;
*refCount = 1;
}
- ~Datum() {
+ void reset() {
*refCount -= 1;
if (*refCount <= 0) {
switch (type) {
@@ -186,6 +198,11 @@ struct Datum { /* interpreter stack type */
}
delete refCount;
}
+
+ }
+
+ ~Datum() {
+ reset();
}
double asFloat();
Commit: 3dc4bb38cd78c39098b855db7dfd7d6b18bce51e
https://github.com/scummvm/scummvm/commit/3dc4bb38cd78c39098b855db7dfd7d6b18bce51e
Author: Scott Percival (code at moral.net.au)
Date: 2020-05-12T18:05:14+08:00
Commit Message:
DIRECTOR: LINGO: Precalculate array size for b_addAt
Changed paths:
engines/director/lingo/lingo-builtins.cpp
diff --git a/engines/director/lingo/lingo-builtins.cpp b/engines/director/lingo/lingo-builtins.cpp
index b024345ed5..f70285ca55 100644
--- a/engines/director/lingo/lingo-builtins.cpp
+++ b/engines/director/lingo/lingo-builtins.cpp
@@ -558,8 +558,9 @@ void LB::b_addAt(int nargs) {
int index = indexD.asInt();
TYPECHECK(list, ARRAY);
- if (!((uint)index < list.u.farr->size())) {
- for (uint i = 0; i < index - list.u.farr->size() - 1; i++)
+ int size = list.u.farr->size();
+ if (index > size) {
+ for (int i = 0; i < index - size - 1; i++)
list.u.farr->push_back(Datum(0));
}
list.u.farr->insert_at(index - 1, value);
More information about the Scummvm-git-logs
mailing list