[Scummvm-git-logs] scummvm master -> f747445e15cbf81876d54b28f6c2d53b0500a2f5

djsrv dservilla at gmail.com
Wed Jun 9 00:10:58 UTC 2021


This automated email contains information about 5 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
9c6165554f DIRECTOR: LINGO: Add LC::readChunkRef
5378369652 DIRECTOR: Add consts
e50ea9b06e DIRECTOR: LINGO: Rework chunk references
ce30bcb0d7 DIRECTOR: LINGO: Use chunk refs in b_numberof/lastof
f747445e15 DIRECTOR: LINGO: Implement kTEAString properties


Commit: 9c6165554fe8b573a275ec184340263fe30ed6c6
    https://github.com/scummvm/scummvm/commit/9c6165554fe8b573a275ec184340263fe30ed6c6
Author: djsrv (dservilla at gmail.com)
Date: 2021-06-08T20:06:28-04:00

Commit Message:
DIRECTOR: LINGO: Add LC::readChunkRef

Changed paths:
    engines/director/lingo/lingo-code.cpp
    engines/director/lingo/lingo-code.h


diff --git a/engines/director/lingo/lingo-code.cpp b/engines/director/lingo/lingo-code.cpp
index dcb519b7dc..6afdb74143 100644
--- a/engines/director/lingo/lingo-code.cpp
+++ b/engines/director/lingo/lingo-code.cpp
@@ -954,9 +954,7 @@ Datum LC::chunkRef(ChunkType type, int startChunk, int endChunk, const Datum &sr
 	return res;
 }
 
-void LC::c_of() {
-	// put char 5 of word 1 of line 2 into field "thing"
-	Datum src = g_lingo->pop();
+Datum LC::readChunkRef(const Datum &src) {
 	Datum lastLine = g_lingo->pop();
 	Datum firstLine = g_lingo->pop();
 	Datum lastItem = g_lingo->pop();
@@ -966,18 +964,22 @@ void LC::c_of() {
 	Datum lastChar = g_lingo->pop();
 	Datum firstChar = g_lingo->pop();
 
-	Datum res = src;
-
 	if (firstChar.asInt() > 0)
-		res = LC::chunkRef(kChunkChar, firstChar.asInt(), lastChar.asInt(), src);
-	else if (firstWord.asInt() > 0)
-		res = LC::chunkRef(kChunkWord, firstWord.asInt(), lastWord.asInt(), src);
-	else if (firstItem.asInt() > 0)
-		res = LC::chunkRef(kChunkItem, firstItem.asInt(), lastItem.asInt(), src);
-	else if (lastLine.asInt() > 0)
-		res = LC::chunkRef(kChunkLine, firstLine.asInt(), lastLine.asInt(), src);
+		return LC::chunkRef(kChunkChar, firstChar.asInt(), lastChar.asInt(), src);
+	if (firstWord.asInt() > 0)
+		return LC::chunkRef(kChunkWord, firstWord.asInt(), lastWord.asInt(), src);
+	if (firstItem.asInt() > 0)
+		return LC::chunkRef(kChunkItem, firstItem.asInt(), lastItem.asInt(), src);
+	if (lastLine.asInt() > 0)
+		return LC::chunkRef(kChunkLine, firstLine.asInt(), lastLine.asInt(), src);
 
-	g_lingo->push(res);
+	return src;
+}
+
+void LC::c_of() {
+	Datum src = g_lingo->pop();
+	Datum ref = readChunkRef(src);
+	g_lingo->push(ref.eval());
 }
 
 void LC::c_charOf() {
diff --git a/engines/director/lingo/lingo-code.h b/engines/director/lingo/lingo-code.h
index c07a9a75d4..8da24fea9b 100644
--- a/engines/director/lingo/lingo-code.h
+++ b/engines/director/lingo/lingo-code.h
@@ -57,6 +57,7 @@ void c_starts();
 void c_intersects();
 void c_within();
 Datum chunkRef(ChunkType type, int startChunk, int endChunk, const Datum &src);
+Datum readChunkRef(const Datum &src);
 void c_of();
 void c_charOf();
 void c_charToOf();


Commit: 53783696525f8d1a934767034b893344860be10d
    https://github.com/scummvm/scummvm/commit/53783696525f8d1a934767034b893344860be10d
Author: djsrv (dservilla at gmail.com)
Date: 2021-06-08T20:06:28-04:00

Commit Message:
DIRECTOR: Add consts

Changed paths:
    engines/director/lingo/lingo.cpp
    engines/director/lingo/lingo.h


diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index 055e6f5c10..2405755564 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -855,7 +855,7 @@ void Datum::reset() {
 #endif
 }
 
-Datum Datum::eval() {
+Datum Datum::eval() const {
 	if (type == VAR || type == FIELDREF || type == CHUNKREF) {
 		return g_lingo->varFetch(*this);
 	}
@@ -1272,7 +1272,7 @@ int Lingo::getInt(uint pc) {
 	return (int)READ_UINT32(&((*_currentScript)[pc]));
 }
 
-void Lingo::varAssign(Datum &var, Datum &value, bool global, DatumHash *localvars) {
+void Lingo::varAssign(const Datum &var, Datum &value, bool global, DatumHash *localvars) {
 	if (localvars == nullptr) {
 		localvars = _localvars;
 	}
@@ -1325,7 +1325,7 @@ void Lingo::varAssign(Datum &var, Datum &value, bool global, DatumHash *localvar
 	}
 }
 
-Datum Lingo::varFetch(Datum &var, bool global, DatumHash *localvars, bool silent) {
+Datum Lingo::varFetch(const Datum &var, bool global, DatumHash *localvars, bool silent) {
 	if (localvars == nullptr) {
 		localvars = _localvars;
 	}
diff --git a/engines/director/lingo/lingo.h b/engines/director/lingo/lingo.h
index 1f9a5c6406..7781f460b8 100644
--- a/engines/director/lingo/lingo.h
+++ b/engines/director/lingo/lingo.h
@@ -136,7 +136,7 @@ struct Datum {	/* interpreter stack type */
 		reset();
 	}
 
-	Datum eval();
+	Datum eval() const;
 	double asFloat() const;
 	int asInt() const;
 	Common::String asString(bool printonly = false) const;
@@ -295,8 +295,8 @@ public:
 	void pushContext(const Symbol funcSym, bool allowRetVal, Datum defaultRetVal);
 	void popContext();
 	void cleanLocalVars();
-	void varAssign(Datum &var, Datum &value, bool global = false, DatumHash *localvars = nullptr);
-	Datum varFetch(Datum &var, bool global = false, DatumHash *localvars = nullptr, bool silent = false);
+	void varAssign(const Datum &var, Datum &value, bool global = false, DatumHash *localvars = nullptr);
+	Datum varFetch(const Datum &var, bool global = false, DatumHash *localvars = nullptr, bool silent = false);
 	Datum findVarV4(int varType, const Datum &id);
 
 	int getAlignedType(const Datum &d1, const Datum &d2, bool numsOnly);


Commit: e50ea9b06e4ca638e276fc3d48b2a8779418602d
    https://github.com/scummvm/scummvm/commit/e50ea9b06e4ca638e276fc3d48b2a8779418602d
Author: djsrv (dservilla at gmail.com)
Date: 2021-06-08T20:06:28-04:00

Commit Message:
DIRECTOR: LINGO: Rework chunk references

Changed paths:
    engines/director/lingo/lingo-code.cpp
    engines/director/lingo/lingo.cpp
    engines/director/lingo/lingo.h


diff --git a/engines/director/lingo/lingo-code.cpp b/engines/director/lingo/lingo-code.cpp
index 6afdb74143..a61470a93a 100644
--- a/engines/director/lingo/lingo-code.cpp
+++ b/engines/director/lingo/lingo-code.cpp
@@ -876,80 +876,128 @@ void LC::c_within() {
 
 Datum LC::chunkRef(ChunkType type, int startChunk, int endChunk, const Datum &src) {
 	// A chunk expression is made up of 0 or more chunks within a source text.
-	// These chunks are called chars, words, items, or lines, but it's easier to think of them
-	// as a substring between 0 or more skip characters and a break character (or the end of the string).
 	// This function returns a reference to the source text, the start index of the first chunk,
 	// and the end index of the last chunk in the chunk expression.
+	// If startChunk < 1, return the last chunk.
 
-	if (startChunk < 1 || (0 > endChunk && endChunk < startChunk))
+	if (0 > endChunk && endChunk < startChunk)
 		return src;
 
 	if (endChunk < 1)
 		endChunk = startChunk;
 
-	Common::String skipChars;
-	Common::String breakChars;
+	Common::String str = src.eval().asString();
+
+	// these hold the bounds of the last chunk in the expression
+	int chunkNum = 0;
+	int chunkStartIdx = -1;
+	int chunkEndIdx = -1;
+
+	// these hold the bounds of the entire chunk expression
+	int exprStartIdx = -1;
+	int exprEndIdx = -1;
 
 	switch (type) {
 	case kChunkChar:
-		skipChars = "";
-		breakChars = "";
+		if (startChunk < 1) {
+			// last char was requested. set its bounds.
+			chunkNum = str.size();
+			chunkStartIdx = str.size() - 1;
+			chunkEndIdx = str.size();
+		} else if (str.size() > 0) {
+			exprStartIdx = MIN(startChunk, (int)str.size()) - 1;
+			exprEndIdx = MIN(endChunk, (int)str.size());
+		}
 		break;
 	case kChunkWord:
-		skipChars = "\t\n\r ";
-		breakChars = "\t\n\r ";
+		{
+			Common::String whitespace = "\t\n\r ";
+
+			int idx = 0;
+			while (idx < (int)str.size() && whitespace.contains(str[idx])) {
+				idx++;
+			}
+			while (idx < (int)str.size()) {
+				// each loop processes one chunk
+				chunkNum++;
+
+				// start of chunk
+				chunkStartIdx = idx;
+				if (chunkNum == startChunk) {
+					exprStartIdx = chunkStartIdx;
+				}
+
+				while (idx < (int)str.size() && !whitespace.contains(str[idx])) {
+					idx++;
+				}
+
+				// end of chunk
+				chunkEndIdx = idx;
+
+				if (chunkNum == endChunk) {
+					exprEndIdx = chunkEndIdx;
+					break;
+				}
+
+				while (idx < (int)str.size() && whitespace.contains(str[idx])) {
+					idx++;
+				}
+			}
+		}
 		break;
 	case kChunkItem:
-		skipChars = "";
-		breakChars = g_lingo->_itemDelimiter;
-		break;
 	case kChunkLine:
-		skipChars = "";
-		breakChars = "\n\r";
-		break;
-	}
-
-	Common::String str = src.asString();
-	int idx = 0;
-	int chunkNum = 0;
+		{
+			char delimiter = (type == kChunkItem) ? g_lingo->_itemDelimiter : '\n';
+
+			int idx = 0;
+			while (true) {
+				// each loop processes one chunk
+				chunkNum++;
+
+				// start of chunk
+				chunkStartIdx = idx;
+				if (chunkNum == startChunk) {
+					exprStartIdx = chunkStartIdx;
+				}
 
-	int startIdx = -1;
-	int endIdx = -1;
+				while (idx < (int)str.size() && str[idx] != delimiter) {
+					idx++;
+				}
 
-	while (true) {
-		// each iteration processes one chunk
+				// end of chunk
+				chunkEndIdx = idx;
+				if (chunkNum == endChunk) {
+					exprEndIdx = chunkEndIdx;
+					break;
+				}
 
-		// find the start of the chunk
-		while (idx < (int)str.size() && skipChars.contains(str[idx])) {
-			idx++;
-		}
-		chunkNum++;
-		if (chunkNum == startChunk) {
-			startIdx = idx; // found start of chunk expression
+				if (idx == (int)str.size())
+					break;
+				
+				idx++; // skip delimiter
+			}
 		}
+		break;
+	}
 
-		// find the end of the chunk
-		if (!breakChars.empty()) {
-			while (idx < (int)str.size() && !breakChars.contains(str[idx])) {
-				idx++;
-			}
-		} else if (idx < (int)str.size()) {
-			idx++;
+	if (startChunk < 1) {
+		// return the last chunk we found
+		exprStartIdx = chunkStartIdx;
+		exprEndIdx = chunkEndIdx;
+	} else {
+		if (exprStartIdx < 0) {
+			// we never found the requested start chunk
+			exprStartIdx = -1;
 		}
-		if (chunkNum == endChunk || idx == (int)str.size()) {
-			endIdx = idx; // found end of chunk expression
-			break;
+		if (exprEndIdx < 0) {
+			// we never found the requested end chunk
+			exprEndIdx = str.size();
 		}
-
-		if (!breakChars.empty())
-			idx++; // skip break char
 	}
 
-	if (startIdx < 0)
-		startIdx = endIdx;
-
 	Datum res;
-	res.u.cref = new ChunkReference(src, startIdx, endIdx);
+	res.u.cref = new ChunkReference(src, type, startChunk, endChunk, exprStartIdx, exprEndIdx);
 	res.type = CHUNKREF;
 	return res;
 }
diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index 2405755564..e23d638788 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -992,8 +992,24 @@ Common::String Datum::asString(bool printonly) const {
 		break;
 	case CHUNKREF:
 		{
+			Common::String chunkType;
+			switch (u.cref->type) {
+			case kChunkChar:
+				chunkType = "char";
+				break;
+			case kChunkWord:
+				chunkType = "word";
+				break;
+			case kChunkItem:
+				chunkType = "item";
+				break;
+			case kChunkLine:
+				 chunkType = "line";
+				break;
+			}
 			Common::String src = u.cref->source.asString(true);
-			s = Common::String::format("chunk: char %d to %d of %s", u.cref->start, u.cref->end, src.c_str());
+			Common::String chunk = eval().asString(true);
+			s += Common::String::format("chunk: %s %d to %d of %s (%s)", chunkType.c_str(), u.cref->startChunk, u.cref->endChunk, src.c_str(), chunk.c_str());
 		}
 		break;
 	case POINT:
@@ -1379,7 +1395,11 @@ Datum Lingo::varFetch(const Datum &var, bool global, DatumHash *localvars, bool
 	} else if (var.type == CHUNKREF) {
 		Common::String src = var.u.cref->source.eval().asString();
 		result.type = STRING;
-		result.u.s = new Common::String(src.substr(var.u.cref->start, var.u.cref->end - var.u.cref->start));
+		if (var.u.cref->start == -1) {
+			result.u.s = new Common::String("");
+		} else {
+			result.u.s = new Common::String(src.substr(var.u.cref->start, var.u.cref->end - var.u.cref->start));
+		}
 	} else {
 		warning("varFetch: fetch from non-variable");
 	}
diff --git a/engines/director/lingo/lingo.h b/engines/director/lingo/lingo.h
index 7781f460b8..a8f8edd6ed 100644
--- a/engines/director/lingo/lingo.h
+++ b/engines/director/lingo/lingo.h
@@ -150,10 +150,14 @@ struct Datum {	/* interpreter stack type */
 
 struct ChunkReference {
 	Datum source;
+	ChunkType type;
+	int startChunk;
+	int endChunk;
 	int start;
 	int end;
 
-	ChunkReference(const Datum &src, uint s, uint e) : source(src), start(s), end(e) {}
+	ChunkReference(const Datum &src, ChunkType t, int sc, int ec, int s, int e)
+		: source(src), type(t), startChunk(sc), endChunk(ec), start(s), end(e) {}
 };
 
 struct PCell {


Commit: ce30bcb0d7c1bbbc06117f980541badb4d3bc3de
    https://github.com/scummvm/scummvm/commit/ce30bcb0d7c1bbbc06117f980541badb4d3bc3de
Author: djsrv (dservilla at gmail.com)
Date: 2021-06-08T20:06:29-04:00

Commit Message:
DIRECTOR: LINGO: Use chunk refs in b_numberof/lastof

For consistency.

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 ec2e5cf13b..fea287eb07 100644
--- a/engines/director/lingo/lingo-builtins.cpp
+++ b/engines/director/lingo/lingo-builtins.cpp
@@ -2439,112 +2439,50 @@ void LB::b_window(int nargs) {
 
 void LB::b_numberofchars(int nargs) {
 	Datum d = g_lingo->pop();
-
-	int len = strlen(d.asString().c_str());
-
-	Datum res(len);
-	g_lingo->push(res);
+	Datum chunkRef = LC::chunkRef(kChunkChar, 0, 0, d); // get reference to last char
+	g_lingo->push(chunkRef.u.cref->startChunk);
 }
 
 void LB::b_numberofitems(int nargs) {
 	Datum d = g_lingo->pop();
-
-	int numberofitems = 1;
-	Common::String contents = d.asString();
-	for (uint32 i = 0;  i < contents.size(); i++) {
-		if (contents[i] == g_lingo->_itemDelimiter)
-			numberofitems++;
-	}
-
-	Datum res(numberofitems);
-	g_lingo->push(res);
+	Datum chunkRef = LC::chunkRef(kChunkItem, 0, 0, d); // get reference to last item
+	g_lingo->push(chunkRef.u.cref->startChunk);
 }
 
 void LB::b_numberoflines(int nargs) {
 	Datum d = g_lingo->pop();
-
-	int numberoflines = 1;
-	Common::String contents = d.asString();
-	for (uint32 i = 0; i < contents.size(); i++) {
-		if (contents[i] == '\n')
-			numberoflines++;
-	}
-
-	Datum res(numberoflines);
-	g_lingo->push(res);
+	Datum chunkRef = LC::chunkRef(kChunkLine, 0, 0, d); // get reference to last line
+	g_lingo->push(chunkRef.u.cref->startChunk);
 }
 
 void LB::b_numberofwords(int nargs) {
 	Datum d = g_lingo->pop();
-
-	int numberofwords = 0;
-	Common::String contents = d.asString();
-	if (contents.empty()) {
-		g_lingo->push(Datum(0));
-		return;
-	}
-	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[contents.size() - 1]))
-		numberofwords++;
-
-	Datum res(numberofwords);
-	g_lingo->push(res);
+	Datum chunkRef = LC::chunkRef(kChunkWord, 0, 0, d); // get reference to last word
+	g_lingo->push(chunkRef.u.cref->startChunk);
 }
 
 void LB::b_lastcharof(int nargs) {
 	Datum d = g_lingo->pop();
-	if (d.type != STRING) {
-		warning("LB::b_lastcharof(): Called with wrong data type: %s", d.type2str());
-		g_lingo->push(Datum(""));
-		return;
-	}
-
-	Common::String contents = d.asString();
-	Common::String res;
-	if (contents.size() != 0)
-		res = contents.lastChar();
-	g_lingo->push(Datum(res));
+	Datum chunkRef = LC::chunkRef(kChunkChar, 0, 0, d); // get reference to last char
+	g_lingo->push(chunkRef.eval());
 }
 
 void LB::b_lastitemof(int nargs) {
 	Datum d = g_lingo->pop();
-	if (d.type != STRING) {
-		warning("LB::b_lastitemof(): Called with wrong data type: %s", d.type2str());
-		g_lingo->push(Datum(""));
-		return;
-	}
-
-	Common::String res;
-	Common::String chunkExpr = d.asString();
-	uint pos = chunkExpr.findLastOf(g_lingo->_itemDelimiter);
-	if (pos == Common::String::npos) {
-		res = chunkExpr;
-	} else {
-		pos++; // skip the item delimiter
-		res = chunkExpr.substr(pos , chunkExpr.size() - pos);
-	}
-
-	g_lingo->push(Datum(res));
+	Datum chunkRef = LC::chunkRef(kChunkItem, 0, 0, d); // get reference to last item
+	g_lingo->push(chunkRef.eval());
 }
 
 void LB::b_lastlineof(int nargs) {
 	Datum d = g_lingo->pop();
-
-	warning("STUB: b_lastlineof");
-
-	g_lingo->push(Datum(0));
+	Datum chunkRef = LC::chunkRef(kChunkLine, 0, 0, d); // get reference to last line
+	g_lingo->push(chunkRef.eval());
 }
 
 void LB::b_lastwordof(int nargs) {
 	Datum d = g_lingo->pop();
-
-	warning("STUB: b_lastwordof");
-
-	g_lingo->push(Datum(0));
+	Datum chunkRef = LC::chunkRef(kChunkWord, 0, 0, d); // get reference to last word
+	g_lingo->push(chunkRef.eval());
 }
 
 void LB::b_scummvmassert(int nargs) {


Commit: f747445e15cbf81876d54b28f6c2d53b0500a2f5
    https://github.com/scummvm/scummvm/commit/f747445e15cbf81876d54b28f6c2d53b0500a2f5
Author: djsrv (dservilla at gmail.com)
Date: 2021-06-08T20:06:29-04:00

Commit Message:
DIRECTOR: LINGO: Implement kTEAString properties

Changed paths:
    engines/director/lingo/lingo-bytecode.cpp


diff --git a/engines/director/lingo/lingo-bytecode.cpp b/engines/director/lingo/lingo-bytecode.cpp
index 17a1dd7590..d54f25aa03 100644
--- a/engines/director/lingo/lingo-bytecode.cpp
+++ b/engines/director/lingo/lingo-bytecode.cpp
@@ -679,8 +679,31 @@ void LC::cb_v4theentitypush() {
 			break;
 		case kTEAString:
 			{
-				/*Datum stringArg = */g_lingo->pop();
-				warning("cb_v4theentitypush: STUB: kTEAString");
+				Datum stringArg = g_lingo->pop();
+				ChunkType chunkType;
+				switch (entity) {
+				case kTheChars:
+					chunkType = kChunkChar;
+					break;
+				case kTheWords:
+					chunkType = kChunkWord;
+					break;
+				case kTheLines:
+					chunkType = kChunkLine;
+					break;
+				case kTheItems:
+					chunkType = kChunkItem;
+					break;
+				}
+				Datum chunkRef = LC::chunkRef(chunkType, 0, 0, stringArg); // get reference to last of chunk type
+				switch (field) {
+				case kTheLast:
+					result = chunkRef.eval();
+					break;
+				case kTheNumber:
+					result = chunkRef.u.cref->startChunk;
+					break;
+				}
 			}
 			break;
 		case kTEAMenuIdItemId:




More information about the Scummvm-git-logs mailing list