aboutsummaryrefslogtreecommitdiff
path: root/engines/director/lingo
diff options
context:
space:
mode:
authorEugene Sandulenko2016-07-01 10:56:02 +0200
committerEugene Sandulenko2016-08-03 23:40:36 +0200
commit8cc88b6fcad2195883f058a2cd0cb3f7c2414acd (patch)
tree8c17e67c28aafbd6445a05ec4dd02f5aab962d35 /engines/director/lingo
parent061f868d7917f3104c294041ab51ac08f1fd0e38 (diff)
downloadscummvm-rg350-8cc88b6fcad2195883f058a2cd0cb3f7c2414acd.tar.gz
scummvm-rg350-8cc88b6fcad2195883f058a2cd0cb3f7c2414acd.tar.bz2
scummvm-rg350-8cc88b6fcad2195883f058a2cd0cb3f7c2414acd.zip
DIRECTOR: Lingo: Initial code for built-in functions
Diffstat (limited to 'engines/director/lingo')
-rw-r--r--engines/director/lingo/lingo-builtins.cpp53
-rw-r--r--engines/director/lingo/lingo-codegen.cpp37
-rw-r--r--engines/director/lingo/lingo-gr.cpp79
-rw-r--r--engines/director/lingo/lingo-gr.y7
-rw-r--r--engines/director/lingo/lingo.cpp19
-rw-r--r--engines/director/lingo/lingo.h29
6 files changed, 154 insertions, 70 deletions
diff --git a/engines/director/lingo/lingo-builtins.cpp b/engines/director/lingo/lingo-builtins.cpp
new file mode 100644
index 0000000000..2286bb7ed2
--- /dev/null
+++ b/engines/director/lingo/lingo-builtins.cpp
@@ -0,0 +1,53 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "engines/director/lingo/lingo.h"
+
+namespace Director {
+
+static struct BuiltinProto {
+ const char *name;
+ void (*func)(void);
+ int nparams;
+} builtins[] = {
+ { "random", Lingo::b_random, 1},
+ { 0, 0, 0 }
+};
+
+void Lingo::initBuiltIns() {
+ for (BuiltinProto *blt = builtins; blt->name; blt++) {
+ _builtins[blt->name] = new Builtin(blt->func, blt->nparams);
+ }
+}
+
+void Lingo::b_random() {
+ Datum max = g_lingo->pop();
+ Datum res;
+
+ res.u.i = 5;
+ res.type = INT;
+
+ warning("b_random");
+ g_lingo->push(res);
+}
+
+}
diff --git a/engines/director/lingo/lingo-codegen.cpp b/engines/director/lingo/lingo-codegen.cpp
index 89d30bec47..6e388ddbab 100644
--- a/engines/director/lingo/lingo-codegen.cpp
+++ b/engines/director/lingo/lingo-codegen.cpp
@@ -126,6 +126,23 @@ void Lingo::define(Common::String &name, int start, int nargs) {
sym->nargs = nargs;
}
+int Lingo::codeString(const char *str) {
+ int numInsts = calcStringAlignment(str);
+
+ // Where we copy the string over
+ int pos = _currentScript->size();
+
+ // Allocate needed space in script
+ for (int i = 0; i < numInsts; i++)
+ _currentScript->push_back(0);
+
+ byte *dst = (byte *)&_currentScript->front() + pos * sizeof(inst);
+
+ memcpy(dst, str, strlen(str) + 1);
+
+ return _currentScript->size();
+}
+
void Lingo::codeArg(Common::String *s) {
_argstack.push_back(s);
}
@@ -164,4 +181,24 @@ int Lingo::codeId_(Common::String &name) {
return ret;
}
+int Lingo::codeFunc(Common::String *name, int nargs) {
+ int ret;
+
+ if (!g_lingo->_builtins.contains(*name)) {
+ ret = g_lingo->code1(g_lingo->c_call);
+ g_lingo->codeString(name->c_str());
+
+ inst numpar = 0;
+ WRITE_UINT32(&numpar, nargs);
+ g_lingo->code1(numpar);
+ } else {
+ if (nargs != g_lingo->_builtins[*name]->nargs)
+ error("Built-in function %s expects %d arguments but got %d", name->c_str(), g_lingo->_builtins[*name]->nargs, nargs);
+
+ ret = g_lingo->code1(g_lingo->_builtins[*name]->func);
+ }
+
+ return ret;
+}
+
}
diff --git a/engines/director/lingo/lingo-gr.cpp b/engines/director/lingo/lingo-gr.cpp
index 13630f5426..01329d468b 100644
--- a/engines/director/lingo/lingo-gr.cpp
+++ b/engines/director/lingo/lingo-gr.cpp
@@ -532,10 +532,10 @@ static const yytype_uint16 yyrline[] =
102, 105, 111, 117, 125, 126, 127, 133, 145, 156,
172, 186, 187, 188, 190, 192, 198, 200, 202, 204,
205, 206, 209, 214, 217, 218, 219, 220, 221, 222,
- 223, 224, 225, 226, 227, 228, 229, 232, 238, 239,
- 240, 241, 242, 243, 246, 247, 258, 259, 260, 261,
- 266, 272, 279, 280, 281, 282, 285, 286, 287, 315,
- 315, 321, 322, 323, 324, 326, 329, 337, 338, 339
+ 223, 224, 225, 226, 227, 228, 229, 232, 235, 236,
+ 237, 238, 239, 240, 243, 244, 255, 256, 257, 258,
+ 263, 269, 276, 277, 278, 279, 282, 283, 284, 312,
+ 312, 318, 319, 320, 321, 323, 326, 334, 335, 336
};
#endif
@@ -1794,60 +1794,57 @@ yyreduce:
case 47:
#line 232 "engines/director/lingo/lingo-gr.y"
{
- g_lingo->code1(g_lingo->c_call);
- g_lingo->codeString((yyvsp[(1) - (4)].s)->c_str());
- inst numpar = 0;
- WRITE_UINT32(&numpar, (yyvsp[(3) - (4)].narg));
- g_lingo->code1(numpar); ;}
+ g_lingo->codeFunc((yyvsp[(1) - (4)].s), (yyvsp[(3) - (4)].narg));
+ delete (yyvsp[(1) - (4)].s); ;}
break;
case 48:
-#line 238 "engines/director/lingo/lingo-gr.y"
+#line 235 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_mci); g_lingo->codeString((yyvsp[(2) - (2)].s)->c_str()); delete (yyvsp[(2) - (2)].s); ;}
break;
case 49:
-#line 239 "engines/director/lingo/lingo-gr.y"
+#line 236 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_mciwait); g_lingo->codeString((yyvsp[(2) - (2)].s)->c_str()); delete (yyvsp[(2) - (2)].s); ;}
break;
case 50:
-#line 240 "engines/director/lingo/lingo-gr.y"
+#line 237 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_printtop); ;}
break;
case 52:
-#line 242 "engines/director/lingo/lingo-gr.y"
+#line 239 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_exit); ;}
break;
case 54:
-#line 246 "engines/director/lingo/lingo-gr.y"
+#line 243 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_global); g_lingo->codeString((yyvsp[(1) - (1)].s)->c_str()); delete (yyvsp[(1) - (1)].s); ;}
break;
case 55:
-#line 247 "engines/director/lingo/lingo-gr.y"
+#line 244 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_global); g_lingo->codeString((yyvsp[(3) - (3)].s)->c_str()); delete (yyvsp[(3) - (3)].s); ;}
break;
case 56:
-#line 258 "engines/director/lingo/lingo-gr.y"
+#line 255 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_gotoloop); ;}
break;
case 57:
-#line 259 "engines/director/lingo/lingo-gr.y"
+#line 256 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_gotonext); ;}
break;
case 58:
-#line 260 "engines/director/lingo/lingo-gr.y"
+#line 257 "engines/director/lingo/lingo-gr.y"
{ g_lingo->code1(g_lingo->c_gotoprevious); ;}
break;
case 59:
-#line 261 "engines/director/lingo/lingo-gr.y"
+#line 258 "engines/director/lingo/lingo-gr.y"
{
g_lingo->code1(g_lingo->c_goto);
g_lingo->codeString((yyvsp[(2) - (2)].s)->c_str());
@@ -1856,7 +1853,7 @@ yyreduce:
break;
case 60:
-#line 266 "engines/director/lingo/lingo-gr.y"
+#line 263 "engines/director/lingo/lingo-gr.y"
{
g_lingo->code1(g_lingo->c_goto);
g_lingo->codeString((yyvsp[(2) - (3)].s)->c_str());
@@ -1866,7 +1863,7 @@ yyreduce:
break;
case 61:
-#line 272 "engines/director/lingo/lingo-gr.y"
+#line 269 "engines/director/lingo/lingo-gr.y"
{
g_lingo->code1(g_lingo->c_goto);
g_lingo->codeString("");
@@ -1875,47 +1872,47 @@ yyreduce:
break;
case 62:
-#line 279 "engines/director/lingo/lingo-gr.y"
+#line 276 "engines/director/lingo/lingo-gr.y"
{ (yyval.s) = (yyvsp[(3) - (3)].s); ;}
break;
case 63:
-#line 280 "engines/director/lingo/lingo-gr.y"
+#line 277 "engines/director/lingo/lingo-gr.y"
{ (yyval.s) = (yyvsp[(2) - (2)].s); ;}
break;
case 64:
-#line 281 "engines/director/lingo/lingo-gr.y"
+#line 278 "engines/director/lingo/lingo-gr.y"
{ (yyval.s) = (yyvsp[(2) - (2)].s); ;}
break;
case 65:
-#line 282 "engines/director/lingo/lingo-gr.y"
+#line 279 "engines/director/lingo/lingo-gr.y"
{ (yyval.s) = (yyvsp[(1) - (1)].s); ;}
break;
case 66:
-#line 285 "engines/director/lingo/lingo-gr.y"
+#line 282 "engines/director/lingo/lingo-gr.y"
{ (yyval.s) = (yyvsp[(3) - (3)].s); ;}
break;
case 67:
-#line 286 "engines/director/lingo/lingo-gr.y"
+#line 283 "engines/director/lingo/lingo-gr.y"
{ (yyval.s) = (yyvsp[(2) - (2)].s); ;}
break;
case 68:
-#line 287 "engines/director/lingo/lingo-gr.y"
+#line 284 "engines/director/lingo/lingo-gr.y"
{ (yyval.s) = (yyvsp[(3) - (3)].s); ;}
break;
case 69:
-#line 315 "engines/director/lingo/lingo-gr.y"
+#line 312 "engines/director/lingo/lingo-gr.y"
{ g_lingo->_indef = true; ;}
break;
case 70:
-#line 316 "engines/director/lingo/lingo-gr.y"
+#line 313 "engines/director/lingo/lingo-gr.y"
{
g_lingo->code1(g_lingo->c_procret);
g_lingo->define(*(yyvsp[(2) - (8)].s), (yyvsp[(4) - (8)].code), (yyvsp[(5) - (8)].narg));
@@ -1923,32 +1920,32 @@ yyreduce:
break;
case 71:
-#line 321 "engines/director/lingo/lingo-gr.y"
+#line 318 "engines/director/lingo/lingo-gr.y"
{ (yyval.narg) = 0; ;}
break;
case 72:
-#line 322 "engines/director/lingo/lingo-gr.y"
+#line 319 "engines/director/lingo/lingo-gr.y"
{ g_lingo->codeArg((yyvsp[(1) - (1)].s)); (yyval.narg) = 1; ;}
break;
case 73:
-#line 323 "engines/director/lingo/lingo-gr.y"
+#line 320 "engines/director/lingo/lingo-gr.y"
{ g_lingo->codeArg((yyvsp[(3) - (3)].s)); (yyval.narg) = (yyvsp[(1) - (3)].narg) + 1; ;}
break;
case 74:
-#line 324 "engines/director/lingo/lingo-gr.y"
+#line 321 "engines/director/lingo/lingo-gr.y"
{ g_lingo->codeArg((yyvsp[(4) - (4)].s)); (yyval.narg) = (yyvsp[(1) - (4)].narg) + 1; ;}
break;
case 75:
-#line 326 "engines/director/lingo/lingo-gr.y"
+#line 323 "engines/director/lingo/lingo-gr.y"
{ g_lingo->codeArgStore(); ;}
break;
case 76:
-#line 329 "engines/director/lingo/lingo-gr.y"
+#line 326 "engines/director/lingo/lingo-gr.y"
{
g_lingo->code1(g_lingo->c_call);
g_lingo->codeString((yyvsp[(1) - (3)].s)->c_str());
@@ -1958,23 +1955,23 @@ yyreduce:
break;
case 77:
-#line 337 "engines/director/lingo/lingo-gr.y"
+#line 334 "engines/director/lingo/lingo-gr.y"
{ (yyval.narg) = 0; ;}
break;
case 78:
-#line 338 "engines/director/lingo/lingo-gr.y"
+#line 335 "engines/director/lingo/lingo-gr.y"
{ (yyval.narg) = 1; ;}
break;
case 79:
-#line 339 "engines/director/lingo/lingo-gr.y"
+#line 336 "engines/director/lingo/lingo-gr.y"
{ (yyval.narg) = (yyvsp[(1) - (3)].narg) + 1; ;}
break;
/* Line 1267 of yacc.c. */
-#line 1978 "engines/director/lingo/lingo-gr.cpp"
+#line 1975 "engines/director/lingo/lingo-gr.cpp"
default: break;
}
YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
@@ -2188,6 +2185,6 @@ yyreturn:
}
-#line 342 "engines/director/lingo/lingo-gr.y"
+#line 339 "engines/director/lingo/lingo-gr.y"
diff --git a/engines/director/lingo/lingo-gr.y b/engines/director/lingo/lingo-gr.y
index 73dc4f0e08..aac0f03582 100644
--- a/engines/director/lingo/lingo-gr.y
+++ b/engines/director/lingo/lingo-gr.y
@@ -230,11 +230,8 @@ expr: INT {
;
func: ID '(' arglist ')' {
- g_lingo->code1(g_lingo->c_call);
- g_lingo->codeString($1->c_str());
- inst numpar = 0;
- WRITE_UINT32(&numpar, $3);
- g_lingo->code1(numpar); };
+ g_lingo->codeFunc($1, $3);
+ delete $1; }
| tMCI STRING { g_lingo->code1(g_lingo->c_mci); g_lingo->codeString($2->c_str()); delete $2; }
| tMCIWAIT ID { g_lingo->code1(g_lingo->c_mciwait); g_lingo->codeString($2->c_str()); delete $2; }
| tPUT expr { g_lingo->code1(g_lingo->c_printtop); }
diff --git a/engines/director/lingo/lingo.cpp b/engines/director/lingo/lingo.cpp
index e584ac02b9..d8c3bdfad1 100644
--- a/engines/director/lingo/lingo.cpp
+++ b/engines/director/lingo/lingo.cpp
@@ -81,6 +81,8 @@ Lingo::Lingo(DirectorEngine *vm) : _vm(vm) {
for (const EventHandlerType *t = &eventHanlerDescs[0]; t->handler != kEventNone; ++t)
_eventHandlerTypes[t->handler] = t->name;
+ initBuiltIns();
+
_currentScript = 0;
_currentScriptType = kMovieScript;
_pc = 0;
@@ -93,23 +95,6 @@ Lingo::Lingo(DirectorEngine *vm) : _vm(vm) {
Lingo::~Lingo() {
}
-int Lingo::codeString(const char *str) {
- int numInsts = calcStringAlignment(str);
-
- // Where we copy the string over
- int pos = _currentScript->size();
-
- // Allocate needed space in script
- for (int i = 0; i < numInsts; i++)
- _currentScript->push_back(0);
-
- byte *dst = (byte *)&_currentScript->front() + pos * sizeof(inst);
-
- memcpy(dst, str, strlen(str) + 1);
-
- return _currentScript->size();
-}
-
void Lingo::addCode(Common::String code, ScriptType type, uint16 id) {
code += '\n';
diff --git a/engines/director/lingo/lingo.h b/engines/director/lingo/lingo.h
index f9c58f0fa4..d1969c2317 100644
--- a/engines/director/lingo/lingo.h
+++ b/engines/director/lingo/lingo.h
@@ -103,9 +103,17 @@ struct Datum { /* interpreter stack type */
Datum() { u.sym = NULL; type = VOID; }
};
+struct Builtin {
+ void (*func)(void);
+ int nargs;
+
+ Builtin(void (*func1)(void), int nargs1) : func(func1), nargs(nargs1) {}
+};
+
typedef Common::HashMap<int32, ScriptData *> ScriptHash;
typedef Common::Array<Datum> StackData;
typedef Common::HashMap<Common::String, Symbol *, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> SymbolHash;
+typedef Common::HashMap<Common::String, Builtin *, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> BuiltinHash;
struct CFrame { /* proc/func call stack frame */
Symbol *sp; /* symbol table entry */
@@ -124,6 +132,16 @@ public:
void processEvent(LEvent event, int entityId);
+ void initBuiltIns();
+
+public:
+ void execute(int pc);
+ void pushContext();
+ void popContext();
+ Symbol *lookupVar(const char *name, bool create = true, bool putInGlobalList = false);
+ void cleanLocalVars();
+ void define(Common::String &s, int start, int nargs);
+
int code1(inst code) { _currentScript->push_back(code); return _currentScript->size() - 1; }
int code2(inst code_1, inst code_2) { int o = code1(code_1); code1(code_2); return o; }
int code3(inst code_1, inst code_2, inst code_3) { int o = code1(code_1); code1(code_2); code1(code_3); return o; }
@@ -134,13 +152,7 @@ public:
int l = strlen(s); return (l + 1 + instLen - 1) / instLen;
}
-public:
- void execute(int pc);
- void pushContext();
- void popContext();
- Symbol *lookupVar(const char *name, bool create = true, bool putInGlobalList = false);
- void cleanLocalVars();
- void define(Common::String &s, int start, int nargs);
+ int codeFunc(Common::String *name, int nargs);
void codeArg(Common::String *s);
void codeArgStore();
int codeId(Common::String &s);
@@ -179,6 +191,8 @@ public:
static void c_gotoprevious();
static void c_global();
+ static void b_random();
+
void func_mci(Common::String &s);
void func_mciwait(Common::String &s);
void func_goto(Common::String &frame, Common::String &movie);
@@ -194,6 +208,7 @@ public:
Common::Array<CFrame *> _callstack;
Common::Array<Common::String *> _argstack;
+ BuiltinHash _builtins;
private:
int parse(const char *code);