[Scummvm-git-logs] scummvm master -> 5f95faf1160421f7f6b04934ae644d71fd6bc438

djsrv dservilla at gmail.com
Fri Jun 25 05:52:50 UTC 2021


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

Summary:
5b436c48aa DIRECTOR: LINGO: Clean up c_hilite
c6e6da2d2c DIRECTOR: LINGO: Remove localvars arg from varAssign
2cfa27b02d DIRECTOR: LINGO: Add CHUNKREF to varAssign
25c59ba25d DIRECTOR: LINGO: Change varFetch index check for consistency
895c36129e DIRECTOR: LINGO: Add put tests
f4d57ed911 DIRECTOR: LINGO: Fix constant compilation
f43026398f DIRECTOR: LINGO: Fix assert line numbers
effc76b14e DIRECTOR: LINGO: Implement put for non-existent chunks
fae07331ae DIRECTOR: LINGO: Add put tests for non-existent chunks
2fd96002d7 DIRECTOR: LINGO: Support nested chunks in delete and hilite
a3537bd5df DIRECTOR: LINGO: Add nested chunks tests
b4a7d4bdff DIRECTOR: LINGO: Support nested chunks in readChunkRef
5f95faf116 DIRECTOR: LINGO: Implement cb_v4assign2


Commit: 5b436c48aaf3718b5fea64b00b1cad070c9d6a0e
    https://github.com/scummvm/scummvm/commit/5b436c48aaf3718b5fea64b00b1cad070c9d6a0e
Author: djsrv (dservilla at gmail.com)
Date: 2021-06-25T01:52:40-04:00

Commit Message:
DIRECTOR: LINGO: Clean up c_hilite

For consistency with c_delete

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


diff --git a/engines/director/lingo/lingo-code.cpp b/engines/director/lingo/lingo-code.cpp
index 1fafa47941..899c99f0fe 100644
--- a/engines/director/lingo/lingo-code.cpp
+++ b/engines/director/lingo/lingo-code.cpp
@@ -1627,19 +1627,19 @@ void LC::c_hilite() {
 	Datum d = g_lingo->pop();
 
 	int fieldId, start, end;
-	if (d.isCastRef()) {
-		fieldId = d.u.i;
-		start = 0;
-		end = -1;
-	} else if (d.type == CHUNKREF) {
+	if (d.type == CHUNKREF) {
 		if (d.u.cref->source.isCastRef()) {
 			fieldId = d.u.cref->source.u.i;
 			start = d.u.cref->start;
 			end = d.u.cref->end;
 		} else {
-			warning("BUILDBOT: c_delete: bad chunk ref field type: %s", d.u.cref->source.type2str());
+			warning("BUILDBOT: c_hilite: bad chunk ref field type: %s", d.u.cref->source.type2str());
 			return;
 		}
+	} else if (d.isCastRef()) {
+		fieldId = d.u.i;
+		start = 0;
+		end = -1;
 	} else {
 		warning("BUILDBOT: c_hilite: bad field type: %s", d.type2str());
 		return;


Commit: c6e6da2d2c79c1b5877eefded0012668f5c6667d
    https://github.com/scummvm/scummvm/commit/c6e6da2d2c79c1b5877eefded0012668f5c6667d
Author: djsrv (dservilla at gmail.com)
Date: 2021-06-25T01:52:40-04:00

Commit Message:
DIRECTOR: LINGO: Remove localvars arg from varAssign

I eliminated uses of this.

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 899c99f0fe..84caa70775 100644
--- a/engines/director/lingo/lingo-code.cpp
+++ b/engines/director/lingo/lingo-code.cpp
@@ -1394,7 +1394,7 @@ void LC::call(const Common::String &name, int nargs, bool allowRetVal) {
 		if (firstArg.isVarRef()) { // first arg could be method name
 			Datum objName(name);
 			objName.type = VARREF;
-			Datum obj = g_lingo->varFetch(objName, nullptr, true);
+			Datum obj = g_lingo->varFetch(objName, true);
 			if (obj.type == OBJECT && (obj.u.obj->getObjType() & (kFactoryObj | kXObj))) {
 				debugC(3, kDebugLingoExec, "Method called on object: <%s>", obj.asString(true).c_str());
 				AbstractObject *target = obj.u.obj;
diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index 364e9f6caf..db2aee7c5d 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -1138,17 +1138,13 @@ int Lingo::getInt(uint pc) {
 	return (int)READ_UINT32(&((*_currentScript)[pc]));
 }
 
-void Lingo::varAssign(const Datum &var, Datum &value, DatumHash *localvars) {
-	if (localvars == nullptr) {
-		localvars = _localvars;
-	}
-
+void Lingo::varAssign(const Datum &var, Datum &value) {
 	switch (var.type) {
 	case VARREF:
 		{
 			Common::String name = *var.u.s;
-			if (localvars && localvars->contains(name)) {
-				(*localvars)[name] = value;
+			if (_localvars && _localvars->contains(name)) {
+				(*_localvars)[name] = value;
 				return;
 			}
 			if (_currentMe.type == OBJECT && _currentMe.u.obj->hasProp(name)) {
@@ -1168,8 +1164,8 @@ void Lingo::varAssign(const Datum &var, Datum &value, DatumHash *localvars) {
 	case LOCALREF:
 		{
 			Common::String name = *var.u.s;
-			if (localvars && localvars->contains(name)) {
-				(*localvars)[name] = value;
+			if (_localvars && _localvars->contains(name)) {
+				(*_localvars)[name] = value;
 			} else {
 				warning("varAssign: local variable %s not defined", name.c_str());
 			}
@@ -1215,11 +1211,7 @@ void Lingo::varAssign(const Datum &var, Datum &value, DatumHash *localvars) {
 	}
 }
 
-Datum Lingo::varFetch(const Datum &var, DatumHash *localvars, bool silent) {
-	if (localvars == nullptr) {
-		localvars = _localvars;
-	}
-
+Datum Lingo::varFetch(const Datum &var, bool silent) {
 	Datum result;
 
 	switch (var.type) {
@@ -1228,8 +1220,8 @@ Datum Lingo::varFetch(const Datum &var, DatumHash *localvars, bool silent) {
 			Datum d;
 			Common::String name = *var.u.s;
 
-			if (localvars && localvars->contains(name)) {
-				return (*localvars)[name];
+			if (_localvars && _localvars->contains(name)) {
+				return (*_localvars)[name];
 			}
 			if (_currentMe.type == OBJECT && _currentMe.u.obj->hasProp(name)) {
 				return _currentMe.u.obj->getProp(name);
@@ -1256,8 +1248,8 @@ Datum Lingo::varFetch(const Datum &var, DatumHash *localvars, bool silent) {
 	case LOCALREF:
 		{
 			Common::String name = *var.u.s;
-			if (localvars && localvars->contains(name)) {
-				return (*localvars)[name];
+			if (_localvars && _localvars->contains(name)) {
+				return (*_localvars)[name];
 			}
 			warning("varFetch: local variable %s not defined", name.c_str());
 			return result;
diff --git a/engines/director/lingo/lingo.h b/engines/director/lingo/lingo.h
index 8900109282..41b03eaad0 100644
--- a/engines/director/lingo/lingo.h
+++ b/engines/director/lingo/lingo.h
@@ -277,8 +277,8 @@ public:
 	void pushContext(const Symbol funcSym, bool allowRetVal, Datum defaultRetVal);
 	void popContext();
 	void cleanLocalVars();
-	void varAssign(const Datum &var, Datum &value, DatumHash *localvars = nullptr);
-	Datum varFetch(const Datum &var, DatumHash *localvars = nullptr, bool silent = false);
+	void varAssign(const Datum &var, Datum &value);
+	Datum varFetch(const Datum &var, bool silent = false);
 	Datum findVarV4(int varType, const Datum &id);
 
 	int getAlignedType(const Datum &d1, const Datum &d2, bool numsOnly);


Commit: 2cfa27b02dae72a32369c258d25e182a5801318f
    https://github.com/scummvm/scummvm/commit/2cfa27b02dae72a32369c258d25e182a5801318f
Author: djsrv (dservilla at gmail.com)
Date: 2021-06-25T01:52:40-04:00

Commit Message:
DIRECTOR: LINGO: Add CHUNKREF to varAssign

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 db2aee7c5d..d90e92ac47 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -1138,7 +1138,7 @@ int Lingo::getInt(uint pc) {
 	return (int)READ_UINT32(&((*_currentScript)[pc]));
 }
 
-void Lingo::varAssign(const Datum &var, Datum &value) {
+void Lingo::varAssign(const Datum &var, const Datum &value) {
 	switch (var.type) {
 	case VARREF:
 		{
@@ -1205,6 +1205,16 @@ void Lingo::varAssign(const Datum &var, Datum &value) {
 			}
 		}
 		break;
+	case CHUNKREF:
+		{
+			if (var.u.cref->start < 0)
+				return;
+
+			Common::String src = var.u.cref->source.eval().asString();
+			Common::String res = src.substr(0, var.u.cref->start) + value.asString() + src.substr(var.u.cref->end);
+			varAssign(var.u.cref->source, res);
+		}
+		break;
 	default:
 		warning("varAssign: assignment to non-variable");
 		break;
diff --git a/engines/director/lingo/lingo.h b/engines/director/lingo/lingo.h
index 41b03eaad0..c6fb17b885 100644
--- a/engines/director/lingo/lingo.h
+++ b/engines/director/lingo/lingo.h
@@ -277,7 +277,7 @@ public:
 	void pushContext(const Symbol funcSym, bool allowRetVal, Datum defaultRetVal);
 	void popContext();
 	void cleanLocalVars();
-	void varAssign(const Datum &var, Datum &value);
+	void varAssign(const Datum &var, const Datum &value);
 	Datum varFetch(const Datum &var, bool silent = false);
 	Datum findVarV4(int varType, const Datum &id);
 


Commit: 25c59ba25d9d9abf92d26be572738403bad42997
    https://github.com/scummvm/scummvm/commit/25c59ba25d9d9abf92d26be572738403bad42997
Author: djsrv (dservilla at gmail.com)
Date: 2021-06-25T01:52:40-04:00

Commit Message:
DIRECTOR: LINGO: Change varFetch index check for consistency

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


diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index d90e92ac47..4f4f7cde41 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -1304,7 +1304,7 @@ Datum Lingo::varFetch(const Datum &var, bool silent) {
 		{
 			Common::String src = var.u.cref->source.eval().asString();
 			result.type = STRING;
-			if (var.u.cref->start == -1) {
+			if (var.u.cref->start < 0) {
 				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));


Commit: 895c36129e6abc38de07d2ec03907afd32daec89
    https://github.com/scummvm/scummvm/commit/895c36129e6abc38de07d2ec03907afd32daec89
Author: djsrv (dservilla at gmail.com)
Date: 2021-06-25T01:52:40-04:00

Commit Message:
DIRECTOR: LINGO: Add put tests

Changed paths:
  A engines/director/lingo/tests/put.lingo


diff --git a/engines/director/lingo/tests/put.lingo b/engines/director/lingo/tests/put.lingo
new file mode 100644
index 0000000000..03bf4a5e03
--- /dev/null
+++ b/engines/director/lingo/tests/put.lingo
@@ -0,0 +1,23 @@
+put "qwertyuiop" into test
+put "a" before char 3 of test
+scummvmAssertEqual(test, "qwaertyuiop")
+
+put "qwertyuiop" into test
+put "a" into char 3 of test
+scummvmAssertEqual(test, "qwartyuiop")
+
+put "qwertyuiop" into test
+put "a" after char 3 of test
+scummvmAssertEqual(test, "qweartyuiop")
+
+put "lorem ipsum dolor sit amet" into test
+put "asdf" before word 3 of test
+scummvmAssertEqual(test, "lorem ipsum asdfdolor sit amet")
+
+put "lorem ipsum dolor sit amet" into test
+put "asdf" into word 3 of test
+scummvmAssertEqual(test, "lorem ipsum asdf sit amet")
+
+put "lorem ipsum dolor sit amet" into test
+put "asdf" after word 3 of test
+scummvmAssertEqual(test, "lorem ipsum dolorasdf sit amet")


Commit: f4d57ed911249d9e9f4bbbc69ff89b48e988ed14
    https://github.com/scummvm/scummvm/commit/f4d57ed911249d9e9f4bbbc69ff89b48e988ed14
Author: djsrv (dservilla at gmail.com)
Date: 2021-06-25T01:52:40-04:00

Commit Message:
DIRECTOR: LINGO: Fix constant compilation

Constants should never be coded as references.

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


diff --git a/engines/director/lingo/lingo-codegen.cpp b/engines/director/lingo/lingo-codegen.cpp
index ff259614ef..1b253f75c8 100644
--- a/engines/director/lingo/lingo-codegen.cpp
+++ b/engines/director/lingo/lingo-codegen.cpp
@@ -1079,15 +1079,15 @@ bool LingoCompiler::visitVarNode(VarNode *node) {
 			return true;
 		}
 	}
-	if (_refMode) {
-		codeVarRef(*node->name);
-		return true;
-	}
 	if (g_lingo->_builtinConsts.contains(*node->name)) {
 		code1(LC::c_constpush);
 		codeString(node->name->c_str());
 		return true;
 	}
+	if (_refMode) {
+		codeVarRef(*node->name);
+		return true;
+	}
 	codeVarGet(*node->name);
 	return true;
 }


Commit: f43026398f03137af6aae4e509c459c2ae7706fa
    https://github.com/scummvm/scummvm/commit/f43026398f03137af6aae4e509c459c2ae7706fa
Author: djsrv (dservilla at gmail.com)
Date: 2021-06-25T01:52:40-04:00

Commit Message:
DIRECTOR: LINGO: Fix assert line numbers

Changed paths:
    engines/director/lingo/lingo-ast.h
    engines/director/lingo/lingo-codegen.cpp
    engines/director/lingo/lingo-gr.cpp
    engines/director/lingo/lingo-gr.y


diff --git a/engines/director/lingo/lingo-ast.h b/engines/director/lingo/lingo-ast.h
index 341d147a24..696938c22c 100644
--- a/engines/director/lingo/lingo-ast.h
+++ b/engines/director/lingo/lingo-ast.h
@@ -308,9 +308,10 @@ struct HandlerNode : Node {
 struct CmdNode : StmtNode {
 	Common::String *name;
 	NodeList *args;
+	uint lineNumber;
 
-	CmdNode(Common::String *nameIn, NodeList *argsIn)
-		: StmtNode(kCmdNode), name(nameIn), args(argsIn) {}
+	CmdNode(Common::String *nameIn, NodeList *argsIn, uint lineNumberIn)
+		: StmtNode(kCmdNode), name(nameIn), args(argsIn), lineNumber(lineNumberIn) {}
 	virtual ~CmdNode() {
 		delete name;
 		deleteList(args);
diff --git a/engines/director/lingo/lingo-codegen.cpp b/engines/director/lingo/lingo-codegen.cpp
index 1b253f75c8..5721786d1e 100644
--- a/engines/director/lingo/lingo-codegen.cpp
+++ b/engines/director/lingo/lingo-codegen.cpp
@@ -253,14 +253,6 @@ int LingoCompiler::codeInt(int val) {
 }
 
 int LingoCompiler::codeCmd(const Common::String &s, int numpar) {
-	// Insert current line number to our asserts
-	if (s.equalsIgnoreCase("scummvmAssert") || s.equalsIgnoreCase("scummvmAssertEqual")) {
-		code1(LC::c_intpush);
-		codeInt(_linenumber);
-
-		numpar++;
-	}
-
 	int ret = code1(LC::c_callcmd);
 
 	codeString(s.c_str());
@@ -484,7 +476,9 @@ bool LingoCompiler::visitHandlerNode(HandlerNode *node) {
 /* CmdNode */
 
 bool LingoCompiler::visitCmdNode(CmdNode *node) {
-	if (node->name->equalsIgnoreCase("go") && node->args->size() == 1 && (*node->args)[0]->type == kVarNode){
+	int numargs = node->args->size();
+
+	if (node->name->equalsIgnoreCase("go") && numargs == 1 && (*node->args)[0]->type == kVarNode){
 		VarNode *var = static_cast<VarNode *>((*node->args)[0]);
 		if (var->name->equalsIgnoreCase("loop") ||
 				var->name->equalsIgnoreCase("next") ||
@@ -497,7 +491,7 @@ bool LingoCompiler::visitCmdNode(CmdNode *node) {
 	}
 
 	// `play done` compiles to `play()`
-	if (node->name->equalsIgnoreCase("play") && node->args->size() == 1 && (*node->args)[0]->type == kVarNode) {
+	if (node->name->equalsIgnoreCase("play") && numargs == 1 && (*node->args)[0]->type == kVarNode) {
 		VarNode *var = static_cast<VarNode *>((*node->args)[0]);
 		if (var->name->equalsIgnoreCase("done")) {
 			codeCmd(*node->name, 0);
@@ -506,7 +500,7 @@ bool LingoCompiler::visitCmdNode(CmdNode *node) {
 	}
 
 	if (node->name->equalsIgnoreCase("playAccel")) {
-		for (uint i = 0; i < node->args->size(); i++) {
+		for (uint i = 0; i < numargs; i++) {
 			Node *arg = (*node->args)[i];
 			if (arg->type == kVarNode) {
 				code1(LC::c_symbolpush);
@@ -515,11 +509,11 @@ bool LingoCompiler::visitCmdNode(CmdNode *node) {
 				COMPILE(arg);
 			}
 		}
-		codeCmd(*node->name, node->args->size());
+		codeCmd(*node->name, numargs);
 		return true;
 	}
 
-	if (node->name->equalsIgnoreCase("sound") && node->args->size() >= 1 && (*node->args)[0]->type == kVarNode) {
+	if (node->name->equalsIgnoreCase("sound") && numargs >= 1 && (*node->args)[0]->type == kVarNode) {
 		VarNode *var = static_cast<VarNode *>((*node->args)[0]);
 		if (var->name->equalsIgnoreCase("close") ||
 				var->name->equalsIgnoreCase("fadeIn") ||
@@ -528,24 +522,30 @@ bool LingoCompiler::visitCmdNode(CmdNode *node) {
 				var->name->equalsIgnoreCase("stop")) {
 			code1(LC::c_symbolpush);
 			codeString(var->name->c_str());
-			for (uint i = 1; i < node->args->size(); i++) {
+			for (uint i = 1; i < numargs; i++) {
 				COMPILE((*node->args)[i]);
 			}
-			codeCmd(*node->name, node->args->size());
+			codeCmd(*node->name, numargs);
 			return true;
 		}
 	}
 
-	if (node->args->size() >= 1 && (*node->args)[0]->type == kVarNode) {
+	if (numargs >= 1 && (*node->args)[0]->type == kVarNode) {
 		// This could be a method call. Code the first arg as a reference.
 		COMPILE_REF((*node->args)[0]);
-		for (uint i = 1; i < node->args->size(); i++) {
+		for (uint i = 1; i < numargs; i++) {
 			COMPILE((*node->args)[i]);
 		}
 	} else {
 		COMPILE_LIST(node->args);
 	}
-	codeCmd(*node->name, node->args->size());
+	// Insert current line number to our asserts
+	if (node->name->equalsIgnoreCase("scummvmAssert") || node->name->equalsIgnoreCase("scummvmAssertEqual")) {
+		code1(LC::c_intpush);
+		codeInt(node->lineNumber);
+		numargs++;
+	}
+	codeCmd(*node->name, numargs);
 	return true;
 }
 
diff --git a/engines/director/lingo/lingo-gr.cpp b/engines/director/lingo/lingo-gr.cpp
index b9b0cc9e34..20deafc912 100644
--- a/engines/director/lingo/lingo-gr.cpp
+++ b/engines/director/lingo/lingo-gr.cpp
@@ -3179,43 +3179,43 @@ yyreduce:
 
   case 113: /* proc: CMDID cmdargs '\n'  */
 #line 405 "engines/director/lingo/lingo-gr.y"
-                                                        { (yyval.node) = new CmdNode((yyvsp[-2].s), (yyvsp[-1].nodelist)); }
+                                                        { (yyval.node) = new CmdNode((yyvsp[-2].s), (yyvsp[-1].nodelist), g_lingo->_compiler->_linenumber - 1); }
 #line 3184 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 114: /* proc: tPUT cmdargs '\n'  */
 #line 406 "engines/director/lingo/lingo-gr.y"
-                                                                { (yyval.node) = new CmdNode(new Common::String("put"), (yyvsp[-1].nodelist)); }
+                                                                { (yyval.node) = new CmdNode(new Common::String("put"), (yyvsp[-1].nodelist), g_lingo->_compiler->_linenumber - 1); }
 #line 3190 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 115: /* proc: tGO cmdargs '\n'  */
 #line 407 "engines/director/lingo/lingo-gr.y"
-                                                                { (yyval.node) = new CmdNode(new Common::String("go"), (yyvsp[-1].nodelist)); }
+                                                                { (yyval.node) = new CmdNode(new Common::String("go"), (yyvsp[-1].nodelist), g_lingo->_compiler->_linenumber - 1); }
 #line 3196 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 116: /* proc: tGO frameargs '\n'  */
 #line 408 "engines/director/lingo/lingo-gr.y"
-                                                        { (yyval.node) = new CmdNode(new Common::String("go"), (yyvsp[-1].nodelist)); }
+                                                        { (yyval.node) = new CmdNode(new Common::String("go"), (yyvsp[-1].nodelist), g_lingo->_compiler->_linenumber - 1); }
 #line 3202 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 117: /* proc: tPLAY cmdargs '\n'  */
 #line 409 "engines/director/lingo/lingo-gr.y"
-                                                        { (yyval.node) = new CmdNode(new Common::String("play"), (yyvsp[-1].nodelist)); }
+                                                        { (yyval.node) = new CmdNode(new Common::String("play"), (yyvsp[-1].nodelist), g_lingo->_compiler->_linenumber - 1); }
 #line 3208 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 118: /* proc: tPLAY frameargs '\n'  */
 #line 410 "engines/director/lingo/lingo-gr.y"
-                                                        { (yyval.node) = new CmdNode(new Common::String("play"), (yyvsp[-1].nodelist)); }
+                                                        { (yyval.node) = new CmdNode(new Common::String("play"), (yyvsp[-1].nodelist), g_lingo->_compiler->_linenumber - 1); }
 #line 3214 "engines/director/lingo/lingo-gr.cpp"
     break;
 
   case 119: /* proc: tOPEN cmdargs '\n'  */
 #line 411 "engines/director/lingo/lingo-gr.y"
-                                                        { (yyval.node) = new CmdNode(new Common::String("open"), (yyvsp[-1].nodelist)); }
+                                                        { (yyval.node) = new CmdNode(new Common::String("open"), (yyvsp[-1].nodelist), g_lingo->_compiler->_linenumber - 1); }
 #line 3220 "engines/director/lingo/lingo-gr.cpp"
     break;
 
@@ -3225,7 +3225,7 @@ yyreduce:
 		NodeList *args = new NodeList;
 		args->push_back((yyvsp[-3].node));
 		args->push_back((yyvsp[-1].node));
-		(yyval.node) = new CmdNode(new Common::String("open"), args); }
+		(yyval.node) = new CmdNode(new Common::String("open"), args, g_lingo->_compiler->_linenumber - 1); }
 #line 3230 "engines/director/lingo/lingo-gr.cpp"
     break;
 
diff --git a/engines/director/lingo/lingo-gr.y b/engines/director/lingo/lingo-gr.y
index 24315eacd4..0b367ea532 100644
--- a/engines/director/lingo/lingo-gr.y
+++ b/engines/director/lingo/lingo-gr.y
@@ -402,18 +402,18 @@ stmtoneliner: proc
 	| definevars
 	;
 
-proc: CMDID cmdargs '\n'				{ $$ = new CmdNode($CMDID, $cmdargs); }
-	| tPUT cmdargs '\n'					{ $$ = new CmdNode(new Common::String("put"), $cmdargs); }
-	| tGO cmdargs '\n'					{ $$ = new CmdNode(new Common::String("go"), $cmdargs); }
-	| tGO frameargs '\n'				{ $$ = new CmdNode(new Common::String("go"), $frameargs); }
-	| tPLAY cmdargs '\n'				{ $$ = new CmdNode(new Common::String("play"), $cmdargs); }
-	| tPLAY frameargs '\n'				{ $$ = new CmdNode(new Common::String("play"), $frameargs); }
-	| tOPEN cmdargs '\n'				{ $$ = new CmdNode(new Common::String("open"), $cmdargs); }
+proc: CMDID cmdargs '\n'				{ $$ = new CmdNode($CMDID, $cmdargs, g_lingo->_compiler->_linenumber - 1); }
+	| tPUT cmdargs '\n'					{ $$ = new CmdNode(new Common::String("put"), $cmdargs, g_lingo->_compiler->_linenumber - 1); }
+	| tGO cmdargs '\n'					{ $$ = new CmdNode(new Common::String("go"), $cmdargs, g_lingo->_compiler->_linenumber - 1); }
+	| tGO frameargs '\n'				{ $$ = new CmdNode(new Common::String("go"), $frameargs, g_lingo->_compiler->_linenumber - 1); }
+	| tPLAY cmdargs '\n'				{ $$ = new CmdNode(new Common::String("play"), $cmdargs, g_lingo->_compiler->_linenumber - 1); }
+	| tPLAY frameargs '\n'				{ $$ = new CmdNode(new Common::String("play"), $frameargs, g_lingo->_compiler->_linenumber - 1); }
+	| tOPEN cmdargs '\n'				{ $$ = new CmdNode(new Common::String("open"), $cmdargs, g_lingo->_compiler->_linenumber - 1); }
 	| tOPEN expr[arg1] tWITH expr[arg2] '\n' {
 		NodeList *args = new NodeList;
 		args->push_back($arg1);
 		args->push_back($arg2);
-		$$ = new CmdNode(new Common::String("open"), args); }
+		$$ = new CmdNode(new Common::String("open"), args, g_lingo->_compiler->_linenumber - 1); }
 	| tNEXT tREPEAT '\n'				{ $$ = new NextRepeatNode(); }
 	| tEXIT tREPEAT '\n'				{ $$ = new ExitRepeatNode(); }
 	| tEXIT '\n'						{ $$ = new ExitNode(); }


Commit: effc76b14e270b5e59ad6f4d3fef56a488aa6cc3
    https://github.com/scummvm/scummvm/commit/effc76b14e270b5e59ad6f4d3fef56a488aa6cc3
Author: djsrv (dservilla at gmail.com)
Date: 2021-06-25T01:52:40-04:00

Commit Message:
DIRECTOR: LINGO: Implement put for non-existent chunks

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


diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index 4f4f7cde41..3aa804b46e 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -1207,11 +1207,38 @@ void Lingo::varAssign(const Datum &var, const Datum &value) {
 		break;
 	case CHUNKREF:
 		{
-			if (var.u.cref->start < 0)
-				return;
-
 			Common::String src = var.u.cref->source.eval().asString();
-			Common::String res = src.substr(0, var.u.cref->start) + value.asString() + src.substr(var.u.cref->end);
+			Common::String res;
+			if (var.u.cref->start >= 0) {
+				res = src.substr(0, var.u.cref->start) + value.asString() + src.substr(var.u.cref->end);
+			} else {
+				// non-existent chunk - insert more chars, items, or lines
+				res = src;
+				int numberOfChunks = LC::lastChunk(var.u.cref->type, var.u.cref->source).u.cref->startChunk;
+				switch (var.u.cref->type) {
+				case kChunkChar:
+					while (numberOfChunks < var.u.cref->startChunk - 1) {
+						res += ' ';
+						numberOfChunks++;
+					}
+					break;
+				case kChunkWord:
+					break;
+				case kChunkItem:
+					while (numberOfChunks < var.u.cref->startChunk ) {
+						res += _itemDelimiter;
+						numberOfChunks++;
+					}
+					break;
+				case kChunkLine:
+					while (numberOfChunks < var.u.cref->startChunk ) {
+						res += '\n';
+						numberOfChunks++;
+					}
+					break;
+				}
+				res += value.asString();
+			}
 			varAssign(var.u.cref->source, res);
 		}
 		break;


Commit: fae07331ae67606a2a06df3b6f05b12d4343b21b
    https://github.com/scummvm/scummvm/commit/fae07331ae67606a2a06df3b6f05b12d4343b21b
Author: djsrv (dservilla at gmail.com)
Date: 2021-06-25T01:52:40-04:00

Commit Message:
DIRECTOR: LINGO: Add put tests for non-existent chunks

Changed paths:
    engines/director/lingo/tests/put.lingo


diff --git a/engines/director/lingo/tests/put.lingo b/engines/director/lingo/tests/put.lingo
index 03bf4a5e03..1ebcaf4c14 100644
--- a/engines/director/lingo/tests/put.lingo
+++ b/engines/director/lingo/tests/put.lingo
@@ -21,3 +21,19 @@ scummvmAssertEqual(test, "lorem ipsum asdf sit amet")
 put "lorem ipsum dolor sit amet" into test
 put "asdf" after word 3 of test
 scummvmAssertEqual(test, "lorem ipsum dolorasdf sit amet")
+
+put "123456789" into test
+put "foo" into char 20 of test
+scummvmAssertEqual(test, "123456789          foo")
+
+put "foo" into test
+put "bar" into word 10000 of test
+scummvmAssertEqual(test, "foobar")
+
+put "foo" into test
+put "bar" into item 10 of test
+scummvmAssertEqual(test, "foo,,,,,,,,,bar")
+
+put "foo" into test"
+put "bar" into line 10 of test
+scummvmAssertEqual(test, "foo" & RETURN & RETURN & RETURN & RETURN & RETURN & RETURN & RETURN & RETURN & RETURN & "bar")


Commit: 2fd96002d7bc7f794b489082e7fac65a76f8429b
    https://github.com/scummvm/scummvm/commit/2fd96002d7bc7f794b489082e7fac65a76f8429b
Author: djsrv (dservilla at gmail.com)
Date: 2021-06-25T01:52:40-04:00

Commit Message:
DIRECTOR: LINGO: Support nested chunks in delete and hilite

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


diff --git a/engines/director/lingo/lingo-code.cpp b/engines/director/lingo/lingo-code.cpp
index 84caa70775..f56b8b3941 100644
--- a/engines/director/lingo/lingo-code.cpp
+++ b/engines/director/lingo/lingo-code.cpp
@@ -1578,11 +1578,15 @@ void LC::c_delete() {
 	Datum field;
 	int start, end;
 	if (d.type == CHUNKREF) {
-		if (d.u.cref->source.isVarRef() || d.u.cref->source.isCastRef()) {
-			field = d.u.cref->source;
-			start = d.u.cref->start;
-			end = d.u.cref->end;
-		} else {
+		start = d.u.cref->start;
+		end = d.u.cref->end;
+		field = d.u.cref->source;
+		while (field.type == CHUNKREF) {
+			start += field.u.cref->start;
+			end += field.u.cref->start;
+			field = field.u.cref->source;
+		}
+		if (!field.isVarRef() && !field.isCastRef()) {
 			warning("BUILDBOT: c_delete: bad chunk ref field type: %s", d.u.cref->source.type2str());
 			return;
 		}
@@ -1628,10 +1632,16 @@ void LC::c_hilite() {
 
 	int fieldId, start, end;
 	if (d.type == CHUNKREF) {
-		if (d.u.cref->source.isCastRef()) {
-			fieldId = d.u.cref->source.u.i;
-			start = d.u.cref->start;
-			end = d.u.cref->end;
+		start = d.u.cref->start;
+		end = d.u.cref->end;
+		Datum src = d.u.cref->source;
+		while (src.type == CHUNKREF) {
+			start += src.u.cref->start;
+			end += src.u.cref->start;
+			src = src.u.cref->source;
+		}
+		if (src.isCastRef()) {
+			fieldId = src.u.i;
 		} else {
 			warning("BUILDBOT: c_hilite: bad chunk ref field type: %s", d.u.cref->source.type2str());
 			return;


Commit: a3537bd5dfc373237b9dbbaf95df12e05acd7c8b
    https://github.com/scummvm/scummvm/commit/a3537bd5dfc373237b9dbbaf95df12e05acd7c8b
Author: djsrv (dservilla at gmail.com)
Date: 2021-06-25T01:52:40-04:00

Commit Message:
DIRECTOR: LINGO: Add nested chunks tests

Changed paths:
    engines/director/lingo/tests/delete.lingo
    engines/director/lingo/tests/put.lingo


diff --git a/engines/director/lingo/tests/delete.lingo b/engines/director/lingo/tests/delete.lingo
index c400a0ed4d..dcab0c170b 100644
--- a/engines/director/lingo/tests/delete.lingo
+++ b/engines/director/lingo/tests/delete.lingo
@@ -57,3 +57,7 @@ scummvmAssertEqual(test, "lorem")
 put "lorem" & RETURN & "ipsum" & RETURN & "dolor" & RETURN & "sit" & RETURN & "amet" into test
 delete the last line of test
 scummvmAssertEqual(test, "lorem" & RETURN & "ipsum" & RETURN & "dolor" & RETURN & "sit")
+
+put "foo" & RETURN & "lorem ipsum" into test
+delete char 3 of word 2 of line 2 of test
+scummvmAssertEqual(test, "foo" & RETURN & "lorem ipum")
diff --git a/engines/director/lingo/tests/put.lingo b/engines/director/lingo/tests/put.lingo
index 1ebcaf4c14..5653675f86 100644
--- a/engines/director/lingo/tests/put.lingo
+++ b/engines/director/lingo/tests/put.lingo
@@ -37,3 +37,7 @@ scummvmAssertEqual(test, "foo,,,,,,,,,bar")
 put "foo" into test"
 put "bar" into line 10 of test
 scummvmAssertEqual(test, "foo" & RETURN & RETURN & RETURN & RETURN & RETURN & RETURN & RETURN & RETURN & RETURN & "bar")
+
+put "foo" & RETURN & "lorem ipsum" into test
+put "bar" into char 3 of word 2 of line 2 of test
+scummvmAssertEqual(test, "foo" & RETURN & "lorem ipbarum")


Commit: b4a7d4bdffdce7f07cad15ae62fa35763d785571
    https://github.com/scummvm/scummvm/commit/b4a7d4bdffdce7f07cad15ae62fa35763d785571
Author: djsrv (dservilla at gmail.com)
Date: 2021-06-25T01:52:40-04:00

Commit Message:
DIRECTOR: LINGO: Support nested chunks in readChunkRef

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


diff --git a/engines/director/lingo/lingo-code.cpp b/engines/director/lingo/lingo-code.cpp
index f56b8b3941..82233365fb 100644
--- a/engines/director/lingo/lingo-code.cpp
+++ b/engines/director/lingo/lingo-code.cpp
@@ -1012,16 +1012,17 @@ Datum LC::readChunkRef(const Datum &src) {
 	Datum lastChar = g_lingo->pop();
 	Datum firstChar = g_lingo->pop();
 
-	if (firstChar.asInt() != 0)
-		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);
+	Datum ref = src;
 	if (firstLine.asInt() != 0)
-		return LC::chunkRef(kChunkLine, firstLine.asInt(), lastLine.asInt(), src);
+		ref = LC::chunkRef(kChunkLine, firstLine.asInt(), lastLine.asInt(), ref);
+	if (firstItem.asInt() != 0)
+		ref = LC::chunkRef(kChunkItem, firstItem.asInt(), lastItem.asInt(), ref);
+	if (firstWord.asInt() != 0)
+		ref = LC::chunkRef(kChunkWord, firstWord.asInt(), lastWord.asInt(), ref);
+	if (firstChar.asInt() != 0)
+		ref = LC::chunkRef(kChunkChar, firstChar.asInt(), lastChar.asInt(), ref);
 
-	return src;
+	return ref;
 }
 
 void LC::c_of() {


Commit: 5f95faf1160421f7f6b04934ae644d71fd6bc438
    https://github.com/scummvm/scummvm/commit/5f95faf1160421f7f6b04934ae644d71fd6bc438
Author: djsrv (dservilla at gmail.com)
Date: 2021-06-25T01:52:40-04:00

Commit Message:
DIRECTOR: LINGO: Implement cb_v4assign2

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 2ed91411a3..fe1a6b6243 100644
--- a/engines/director/lingo/lingo-bytecode.cpp
+++ b/engines/director/lingo/lingo-bytecode.cpp
@@ -644,9 +644,33 @@ void LC::cb_varassign() {
 
 
 void LC::cb_v4assign2() {
-	g_lingo->readInt();
-	g_lingo->printSTUBWithArglist("cb_v4assign2", 10);
-	g_lingo->dropStack(10);
+int arg = g_lingo->readInt();
+	int op = (arg >> 4) & 0xF;
+	int varType = arg & 0xF;
+	Datum varId = g_lingo->pop();
+
+	Datum var = g_lingo->findVarV4(varType, varId);
+	Datum ref = readChunkRef(var);
+	g_lingo->push(ref);
+
+	switch (op) {
+	case 1:
+		// put value into chunk
+		LC::c_assign();
+		break;
+	case 2:
+		// put value after chunk
+		LC::c_putafter();
+		break;
+	case 3:
+		// put value before chunk
+		LC::c_putbefore();
+		break;
+	default:
+		warning("cb_v4assign2: unknown operator %d", op);
+		g_lingo->pop();
+		break;
+	}
 }
 
 




More information about the Scummvm-git-logs mailing list