2017-05-26 05:24:38 +02:00
|
|
|
/* 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 "debug.h"
|
|
|
|
|
|
|
|
#include "allfiles.h"
|
|
|
|
#include "variable.h"
|
|
|
|
#include "newfatal.h"
|
|
|
|
#include "stringy.h"
|
|
|
|
#include "objtypes.h"
|
|
|
|
#include "people.h"
|
|
|
|
#include "fileset.h"
|
|
|
|
|
2017-05-27 20:16:54 +02:00
|
|
|
#include "sludge.h"
|
|
|
|
#include "common/debug.h"
|
|
|
|
|
2017-05-26 05:24:38 +02:00
|
|
|
#include <dirent.h>
|
|
|
|
#include "moreio.h"
|
|
|
|
#ifdef _WIN32
|
|
|
|
#include "windows.h"
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2017-05-26 21:25:11 +02:00
|
|
|
namespace Sludge {
|
|
|
|
|
2017-05-29 08:02:59 +02:00
|
|
|
const char *typeName[] = { "undefined", "number", "user function", "string",
|
|
|
|
"built-in function", "file", "stack", "object type", "animation",
|
|
|
|
"costume" };
|
2017-05-26 05:24:38 +02:00
|
|
|
|
|
|
|
extern char *outputDir;
|
|
|
|
|
|
|
|
void unlinkVar(variable &thisVar) {
|
|
|
|
switch (thisVar.varType) {
|
|
|
|
case SVT_STRING:
|
|
|
|
delete[] thisVar.varData.theString;
|
|
|
|
thisVar.varData.theString = NULL;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SVT_STACK:
|
2017-05-29 08:02:59 +02:00
|
|
|
thisVar.varData.theStack->timesUsed--;
|
|
|
|
if (thisVar.varData.theStack->timesUsed <= 0) {
|
|
|
|
while (thisVar.varData.theStack->first)
|
|
|
|
trimStack(thisVar.varData.theStack->first);
|
2017-05-26 05:24:38 +02:00
|
|
|
delete thisVar.varData.theStack;
|
|
|
|
thisVar.varData.theStack = NULL;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SVT_FASTARRAY:
|
2017-05-29 08:02:59 +02:00
|
|
|
thisVar.varData.fastArray->timesUsed--;
|
|
|
|
if (thisVar.varData.theStack->timesUsed <= 0) {
|
|
|
|
delete thisVar.varData.fastArray->fastVariables;
|
2017-05-26 05:24:38 +02:00
|
|
|
delete[] thisVar.varData.fastArray;
|
|
|
|
thisVar.varData.fastArray = NULL;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SVT_ANIM:
|
|
|
|
deleteAnim(thisVar.varData.animHandler);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void setVariable(variable &thisVar, variableType vT, int value) {
|
|
|
|
unlinkVar(thisVar);
|
|
|
|
thisVar.varType = vT;
|
|
|
|
thisVar.varData.intValue = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
void newAnimationVariable(variable &thisVar, personaAnimation *i) {
|
|
|
|
unlinkVar(thisVar);
|
|
|
|
thisVar.varType = SVT_ANIM;
|
|
|
|
thisVar.varData.animHandler = i;
|
|
|
|
}
|
|
|
|
|
|
|
|
personaAnimation *getAnimationFromVar(variable &thisVar) {
|
|
|
|
if (thisVar.varType == SVT_ANIM)
|
|
|
|
return copyAnim(thisVar.varData.animHandler);
|
|
|
|
|
|
|
|
if (thisVar.varType == SVT_INT && thisVar.varData.intValue == 0)
|
|
|
|
return makeNullAnim();
|
|
|
|
|
2017-05-29 08:02:59 +02:00
|
|
|
fatal("Expecting an animation variable; found variable of type",
|
|
|
|
typeName[thisVar.varType]);
|
2017-05-26 05:24:38 +02:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void newCostumeVariable(variable &thisVar, persona *i) {
|
|
|
|
unlinkVar(thisVar);
|
|
|
|
thisVar.varType = SVT_COSTUME;
|
|
|
|
thisVar.varData.costumeHandler = i;
|
|
|
|
}
|
|
|
|
|
|
|
|
persona *getCostumeFromVar(variable &thisVar) {
|
|
|
|
persona *p = NULL;
|
|
|
|
|
|
|
|
switch (thisVar.varType) {
|
|
|
|
case SVT_ANIM:
|
|
|
|
p = new persona;
|
2017-05-29 08:02:59 +02:00
|
|
|
if (!checkNew(p))
|
|
|
|
return NULL;
|
|
|
|
p->numDirections = 1;
|
|
|
|
p->animation = new personaAnimation *[3];
|
|
|
|
if (!checkNew(p->animation))
|
|
|
|
return NULL;
|
2017-05-26 05:24:38 +02:00
|
|
|
|
2017-05-29 08:02:59 +02:00
|
|
|
for (int iii = 0; iii < 3; iii++)
|
|
|
|
p->animation[iii] = copyAnim(thisVar.varData.animHandler);
|
2017-05-26 05:24:38 +02:00
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SVT_COSTUME:
|
|
|
|
return thisVar.varData.costumeHandler;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2017-05-29 08:02:59 +02:00
|
|
|
fatal("Expecting an animation variable; found variable of type",
|
|
|
|
typeName[thisVar.varType]);
|
2017-05-26 05:24:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
int stackSize(const stackHandler *me) {
|
|
|
|
int r = 0;
|
2017-05-29 08:02:59 +02:00
|
|
|
variableStack *a = me->first;
|
2017-05-26 05:24:38 +02:00
|
|
|
while (a) {
|
2017-05-29 08:02:59 +02:00
|
|
|
r++;
|
|
|
|
a = a->next;
|
2017-05-26 05:24:38 +02:00
|
|
|
}
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
#include <windows.h>
|
|
|
|
WCHAR *ConvertToUTF16(const char *input);
|
|
|
|
char *ConvertFromUTF16(const WCHAR *input);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
bool getSavedGamesStack(stackHandler *sH, char *ext) {
|
|
|
|
char *pattern = joinStrings("*", ext);
|
2017-05-29 08:02:59 +02:00
|
|
|
if (!pattern)
|
|
|
|
return false;
|
2017-05-26 05:24:38 +02:00
|
|
|
|
|
|
|
variable newName;
|
|
|
|
newName.varType = SVT_NULL;
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
|
|
|
|
WCHAR *w_pattern = ConvertToUTF16(pattern);
|
|
|
|
|
|
|
|
WIN32_FIND_DATA theData;
|
|
|
|
HANDLE handle = FindFirstFile(w_pattern, & theData);
|
|
|
|
|
|
|
|
delete w_pattern;
|
|
|
|
|
|
|
|
if (handle != INVALID_HANDLE_VALUE) {
|
|
|
|
bool keepGoing;
|
|
|
|
do {
|
|
|
|
theData.cFileName[lstrlen(theData.cFileName) - strlen(ext)] = TEXT('\0');
|
|
|
|
char *fileName = ConvertFromUTF16(theData.cFileName);
|
|
|
|
char *decoded = decodeFilename(fileName);
|
|
|
|
makeTextVar(newName, decoded);
|
|
|
|
delete fileName;
|
|
|
|
delete decoded;
|
|
|
|
if (! addVarToStack(newName, sH -> first)) return false;
|
|
|
|
if (sH -> last == NULL) sH -> last = sH -> first;
|
|
|
|
keepGoing = FindNextFile(handle, & theData);
|
2017-05-29 08:02:59 +02:00
|
|
|
}while (keepGoing);
|
2017-05-26 05:24:38 +02:00
|
|
|
FindClose(handle);
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
DIR *dir = opendir(".");
|
2017-05-29 08:02:59 +02:00
|
|
|
if (!dir)
|
|
|
|
return false;
|
2017-05-26 05:24:38 +02:00
|
|
|
|
|
|
|
struct dirent *d = readdir(dir);
|
|
|
|
while (d != NULL) {
|
2017-05-29 08:02:59 +02:00
|
|
|
if (!strcmp(d->d_name + strlen(d->d_name) - strlen(ext), ext)) {
|
2017-05-26 05:24:38 +02:00
|
|
|
d->d_name[strlen(d->d_name) - strlen(ext)] = 0;
|
|
|
|
char *decoded = decodeFilename(d->d_name);
|
|
|
|
makeTextVar(newName, decoded);
|
|
|
|
delete[] decoded;
|
2017-05-29 08:02:59 +02:00
|
|
|
if (!addVarToStack(newName, sH->first))
|
|
|
|
return false;
|
|
|
|
if (sH->last == NULL)
|
|
|
|
sH->last = sH->first;
|
2017-05-26 05:24:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
d = readdir(dir);
|
|
|
|
}
|
|
|
|
|
|
|
|
closedir(dir);
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
delete[] pattern;
|
|
|
|
pattern = NULL;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool copyStack(const variable &from, variable &to) {
|
|
|
|
to.varType = SVT_STACK;
|
|
|
|
to.varData.theStack = new stackHandler;
|
2017-05-29 08:02:59 +02:00
|
|
|
if (!checkNew(to.varData.theStack))
|
|
|
|
return false;
|
|
|
|
to.varData.theStack->first = NULL;
|
|
|
|
to.varData.theStack->last = NULL;
|
|
|
|
to.varData.theStack->timesUsed = 1;
|
|
|
|
variableStack *a = from.varData.theStack->first;
|
2017-05-26 05:24:38 +02:00
|
|
|
|
|
|
|
#if DEBUG_STACKINESS
|
|
|
|
{
|
|
|
|
char *str = getTextFromAnyVar(from);
|
|
|
|
stackDebug((stackfp, "in copyStack, copying %s\n", str));
|
|
|
|
delete[] str;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
while (a) {
|
2017-05-29 08:02:59 +02:00
|
|
|
addVarToStack(a->thisVar, to.varData.theStack->first);
|
|
|
|
if (to.varData.theStack->last == NULL) {
|
2017-05-26 05:24:38 +02:00
|
|
|
#if DEBUG_STACKINESS
|
|
|
|
stackDebug((stackfp, "LAST"));
|
|
|
|
#endif
|
2017-05-29 08:02:59 +02:00
|
|
|
to.varData.theStack->last = to.varData.theStack->first;
|
2017-05-26 05:24:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#if DEBUG_STACKINESS
|
|
|
|
{
|
|
|
|
char *str = getTextFromAnyVar(a->thisVar);
|
|
|
|
stackDebug((stackfp, "\ta->thisVar = %s (%p)\n", str, to.varData.theStack->first));
|
|
|
|
delete[] str;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2017-05-29 08:02:59 +02:00
|
|
|
a = a->next;
|
2017-05-26 05:24:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#if DEBUG_STACKINESS
|
|
|
|
{
|
|
|
|
char *str = getTextFromAnyVar(to);
|
|
|
|
stackDebug((stackfp, "finished copy, got %s\n", str));
|
|
|
|
delete[] str;
|
|
|
|
stackDebug((stackfp, "first = %p\n", to.varData.theStack->first));
|
|
|
|
stackDebug((stackfp, "last = %p\n", to.varData.theStack->last));
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*void newStackVar (variable & thisVar) {
|
2017-05-29 08:02:59 +02:00
|
|
|
unlinkVar (thisVar);
|
|
|
|
thisVar.varType = VT_STACK;
|
|
|
|
thisVar.varData.theStack = NULL;
|
|
|
|
} */
|
2017-05-26 05:24:38 +02:00
|
|
|
|
|
|
|
void addVariablesInSecond(variable &var1, variable &var2) {
|
|
|
|
if (var1.varType == SVT_INT && var2.varType == SVT_INT) {
|
|
|
|
var2.varData.intValue += var1.varData.intValue;
|
|
|
|
} else {
|
|
|
|
char *string1 = getTextFromAnyVar(var1);
|
|
|
|
char *string2 = getTextFromAnyVar(var2);
|
|
|
|
|
|
|
|
unlinkVar(var2);
|
|
|
|
var2.varData.theString = joinStrings(string1, string2);
|
|
|
|
var2.varType = SVT_STRING;
|
|
|
|
delete[] string1;
|
|
|
|
delete[] string2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int compareVars(const variable &var1, const variable &var2) {
|
|
|
|
int re = 0;
|
|
|
|
if (var1.varType == var2.varType) {
|
|
|
|
switch (var1.varType) {
|
|
|
|
case SVT_NULL:
|
|
|
|
re = 1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SVT_COSTUME:
|
|
|
|
re = (var1.varData.costumeHandler == var2.varData.costumeHandler);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SVT_ANIM:
|
|
|
|
re = (var1.varData.animHandler == var2.varData.animHandler);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SVT_STRING:
|
|
|
|
|
|
|
|
re = (strcmp(var1.varData.theString, var2.varData.theString) == 0);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SVT_STACK:
|
|
|
|
re = (var1.varData.theStack == var2.varData.theStack);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
re = (var1.varData.intValue == var2.varData.intValue);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return re;
|
|
|
|
}
|
|
|
|
|
|
|
|
void compareVariablesInSecond(const variable &var1, variable &var2) {
|
|
|
|
setVariable(var2, SVT_INT, compareVars(var1, var2));
|
|
|
|
}
|
|
|
|
|
|
|
|
void makeTextVar(variable &thisVar, const char *txt) {
|
|
|
|
unlinkVar(thisVar);
|
|
|
|
thisVar.varType = SVT_STRING;
|
|
|
|
thisVar.varData.theString = copyString(txt);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool loadStringToVar(variable &thisVar, int value) {
|
2017-05-27 20:16:54 +02:00
|
|
|
|
2017-05-26 05:24:38 +02:00
|
|
|
makeTextVar(thisVar, getNumberedString(value));
|
2017-05-29 08:02:59 +02:00
|
|
|
return (bool) (thisVar.varData.theString != NULL);
|
2017-05-26 05:24:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
char *getTextFromAnyVar(const variable &from) {
|
|
|
|
switch (from.varType) {
|
|
|
|
case SVT_STRING:
|
|
|
|
return copyString(from.varData.theString);
|
|
|
|
|
|
|
|
case SVT_FASTARRAY: {
|
|
|
|
char *builder = copyString("FAST:");
|
|
|
|
char *builder2;
|
|
|
|
char *grabText;
|
|
|
|
|
2017-05-29 08:02:59 +02:00
|
|
|
for (int i = 0; i < from.varData.fastArray->size; i++) {
|
2017-05-26 05:24:38 +02:00
|
|
|
builder2 = joinStrings(builder, " ");
|
2017-05-29 08:02:59 +02:00
|
|
|
if (!builder2)
|
|
|
|
return NULL;
|
2017-05-26 05:24:38 +02:00
|
|
|
delete builder;
|
2017-05-29 08:02:59 +02:00
|
|
|
grabText = getTextFromAnyVar(
|
|
|
|
from.varData.fastArray->fastVariables[i]);
|
2017-05-26 05:24:38 +02:00
|
|
|
builder = joinStrings(builder2, grabText);
|
2017-05-29 08:02:59 +02:00
|
|
|
if (!builder)
|
|
|
|
return NULL;
|
2017-05-26 05:24:38 +02:00
|
|
|
delete grabText;
|
|
|
|
grabText = NULL;
|
|
|
|
delete builder2;
|
|
|
|
builder2 = NULL;
|
|
|
|
}
|
|
|
|
return builder;
|
|
|
|
}
|
|
|
|
|
|
|
|
case SVT_STACK: {
|
|
|
|
char *builder = copyString("ARRAY:");
|
|
|
|
char *builder2;
|
|
|
|
char *grabText;
|
|
|
|
|
2017-05-29 08:02:59 +02:00
|
|
|
variableStack *stacky = from.varData.theStack->first;
|
2017-05-26 05:24:38 +02:00
|
|
|
|
|
|
|
while (stacky) {
|
|
|
|
builder2 = joinStrings(builder, " ");
|
2017-05-29 08:02:59 +02:00
|
|
|
if (!builder2)
|
|
|
|
return NULL;
|
2017-05-26 05:24:38 +02:00
|
|
|
delete builder;
|
2017-05-29 08:02:59 +02:00
|
|
|
grabText = getTextFromAnyVar(stacky->thisVar);
|
2017-05-26 05:24:38 +02:00
|
|
|
builder = joinStrings(builder2, grabText);
|
2017-05-29 08:02:59 +02:00
|
|
|
if (!builder)
|
|
|
|
return NULL;
|
2017-05-26 05:24:38 +02:00
|
|
|
delete grabText;
|
|
|
|
grabText = NULL;
|
|
|
|
delete builder2;
|
|
|
|
builder2 = NULL;
|
2017-05-29 08:02:59 +02:00
|
|
|
stacky = stacky->next;
|
2017-05-26 05:24:38 +02:00
|
|
|
}
|
|
|
|
return builder;
|
|
|
|
}
|
|
|
|
|
|
|
|
case SVT_INT: {
|
|
|
|
char *buff = new char[10];
|
2017-05-29 08:02:59 +02:00
|
|
|
if (!checkNew(buff))
|
|
|
|
return NULL;
|
2017-05-26 05:24:38 +02:00
|
|
|
sprintf(buff, "%i", from.varData.intValue);
|
|
|
|
return buff;
|
|
|
|
}
|
|
|
|
|
|
|
|
case SVT_FILE: {
|
|
|
|
// char * buff = new char[15];
|
|
|
|
// if (! checkNew (buff)) return NULL;
|
|
|
|
// sprintf (buff, "FILE %i", from.varData.intValue);
|
|
|
|
return joinStrings("", resourceNameFromNum(from.varData.intValue));
|
|
|
|
}
|
|
|
|
|
2017-05-29 08:02:59 +02:00
|
|
|
/* case SVT_ANIM:
|
|
|
|
{
|
|
|
|
char * buff = new char[20];
|
|
|
|
if (! checkNew (buff)) return NULL;
|
|
|
|
sprintf (buff, "%p", from.varData.animHandler);
|
|
|
|
return buff;
|
|
|
|
}*/
|
2017-05-26 05:24:38 +02:00
|
|
|
|
|
|
|
case SVT_OBJTYPE: {
|
|
|
|
objectType *thisType = findObjectType(from.varData.intValue);
|
2017-05-29 08:02:59 +02:00
|
|
|
if (thisType)
|
|
|
|
return copyString(thisType->screenName);
|
2017-05-26 05:24:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return copyString(typeName[from.varType]);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool getBoolean(const variable &from) {
|
|
|
|
switch (from.varType) {
|
|
|
|
case SVT_NULL:
|
|
|
|
return false;
|
|
|
|
|
|
|
|
case SVT_INT:
|
2017-05-29 08:02:59 +02:00
|
|
|
return (bool) (from.varData.intValue != 0);
|
2017-05-26 05:24:38 +02:00
|
|
|
|
|
|
|
case SVT_STACK:
|
2017-05-29 08:02:59 +02:00
|
|
|
return (bool) (from.varData.theStack->first != NULL);
|
2017-05-26 05:24:38 +02:00
|
|
|
|
|
|
|
case SVT_STRING:
|
2017-05-29 08:02:59 +02:00
|
|
|
return (bool) (from.varData.theString[0] != 0);
|
2017-05-26 05:24:38 +02:00
|
|
|
|
|
|
|
case SVT_FASTARRAY:
|
2017-05-29 08:02:59 +02:00
|
|
|
return (bool) (from.varData.fastArray->size != 0);
|
2017-05-26 05:24:38 +02:00
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool copyMain(const variable &from, variable &to) {
|
|
|
|
to.varType = from.varType;
|
|
|
|
switch (to.varType) {
|
|
|
|
case SVT_INT:
|
|
|
|
case SVT_FUNC:
|
|
|
|
case SVT_BUILT:
|
|
|
|
case SVT_FILE:
|
|
|
|
case SVT_OBJTYPE:
|
|
|
|
to.varData.intValue = from.varData.intValue;
|
|
|
|
return true;
|
|
|
|
|
|
|
|
case SVT_FASTARRAY:
|
|
|
|
to.varData.fastArray = from.varData.fastArray;
|
2017-05-29 08:02:59 +02:00
|
|
|
to.varData.fastArray->timesUsed++;
|
2017-05-26 05:24:38 +02:00
|
|
|
return true;
|
|
|
|
|
|
|
|
case SVT_STRING:
|
|
|
|
to.varData.theString = copyString(from.varData.theString);
|
|
|
|
return to.varData.theString ? true : false;
|
|
|
|
|
|
|
|
case SVT_STACK:
|
|
|
|
to.varData.theStack = from.varData.theStack;
|
2017-05-29 08:02:59 +02:00
|
|
|
to.varData.theStack->timesUsed++;
|
2017-05-26 05:24:38 +02:00
|
|
|
return true;
|
|
|
|
|
|
|
|
case SVT_COSTUME:
|
|
|
|
to.varData.costumeHandler = from.varData.costumeHandler;
|
|
|
|
return true;
|
|
|
|
|
|
|
|
case SVT_ANIM:
|
|
|
|
to.varData.animHandler = copyAnim(from.varData.animHandler);
|
|
|
|
return true;
|
|
|
|
|
|
|
|
case SVT_NULL:
|
|
|
|
return true;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
fatal("Unknown value type");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool copyVariable(const variable &from, variable &to) {
|
|
|
|
unlinkVar(to);
|
|
|
|
return copyMain(from, to);
|
|
|
|
}
|
|
|
|
|
|
|
|
variable *fastArrayGetByIndex(fastArrayHandler *vS, unsigned int theIndex) {
|
2017-05-29 08:02:59 +02:00
|
|
|
if (theIndex < 0 || theIndex >= vS->size)
|
|
|
|
return NULL;
|
|
|
|
return &vS->fastVariables[theIndex];
|
2017-05-26 05:24:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool makeFastArraySize(variable &to, int size) {
|
2017-05-29 08:02:59 +02:00
|
|
|
if (size < 0)
|
|
|
|
return fatal(
|
|
|
|
"Can't create a fast array with a negative number of elements!");
|
2017-05-26 05:24:38 +02:00
|
|
|
unlinkVar(to);
|
|
|
|
to.varType = SVT_FASTARRAY;
|
|
|
|
to.varData.fastArray = new fastArrayHandler;
|
2017-05-29 08:02:59 +02:00
|
|
|
if (!checkNew(to.varData.fastArray))
|
|
|
|
return false;
|
|
|
|
to.varData.fastArray->fastVariables = new variable[size];
|
|
|
|
if (!checkNew(to.varData.fastArray->fastVariables))
|
|
|
|
return false;
|
|
|
|
for (int i = 0; i < size; i++) {
|
|
|
|
initVarNew(to.varData.fastArray->fastVariables[i]);
|
2017-05-26 05:24:38 +02:00
|
|
|
}
|
2017-05-29 08:02:59 +02:00
|
|
|
to.varData.fastArray->size = size;
|
|
|
|
to.varData.fastArray->timesUsed = 1;
|
2017-05-26 05:24:38 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool makeFastArrayFromStack(variable &to, const stackHandler *stacky) {
|
|
|
|
int size = stackSize(stacky);
|
2017-05-29 08:02:59 +02:00
|
|
|
if (!makeFastArraySize(to, size))
|
|
|
|
return false;
|
2017-05-26 05:24:38 +02:00
|
|
|
|
|
|
|
// Now let's fill up the new array
|
|
|
|
|
2017-05-29 08:02:59 +02:00
|
|
|
variableStack *allV = stacky->first;
|
2017-05-26 05:24:38 +02:00
|
|
|
size = 0;
|
|
|
|
while (allV) {
|
2017-05-29 08:02:59 +02:00
|
|
|
copyMain(allV->thisVar, to.varData.fastArray->fastVariables[size]);
|
|
|
|
size++;
|
|
|
|
allV = allV->next;
|
2017-05-26 05:24:38 +02:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2017-05-29 08:02:59 +02:00
|
|
|
bool moveVariable (variable & from, variable & to) {
|
|
|
|
unlinkVar (to);
|
|
|
|
memcpy (& to, & from, sizeof (variable));
|
|
|
|
from.varType = SVT_NULL;
|
|
|
|
}
|
|
|
|
*/
|
2017-05-26 05:24:38 +02:00
|
|
|
|
|
|
|
bool addVarToStack(const variable &va, variableStack *&thisStack) {
|
|
|
|
variableStack *newStack = new variableStack;
|
2017-05-29 08:02:59 +02:00
|
|
|
if (!checkNew(newStack))
|
|
|
|
return false;
|
2017-05-26 05:24:38 +02:00
|
|
|
|
2017-05-29 08:02:59 +02:00
|
|
|
if (!copyMain(va, newStack->thisVar))
|
|
|
|
return false;
|
|
|
|
newStack->next = thisStack;
|
2017-05-26 05:24:38 +02:00
|
|
|
thisStack = newStack;
|
2017-05-29 08:02:59 +02:00
|
|
|
debug(kSludgeDebugStackMachine, "Variable %s was added to stack",
|
|
|
|
getTextFromAnyVar(va));
|
2017-05-26 05:24:38 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool addVarToStackQuick(variable &va, variableStack *&thisStack) {
|
|
|
|
variableStack *newStack = new variableStack;
|
2017-05-29 08:02:59 +02:00
|
|
|
if (!checkNew(newStack))
|
|
|
|
return false;
|
2017-05-26 05:24:38 +02:00
|
|
|
|
|
|
|
// if (! copyMain (va, newStack -> thisVar)) return false;
|
|
|
|
|
2017-05-29 08:02:59 +02:00
|
|
|
memcpy(&(newStack->thisVar), &va, sizeof(variable));
|
2017-05-26 05:24:38 +02:00
|
|
|
va.varType = SVT_NULL;
|
|
|
|
|
2017-05-29 08:02:59 +02:00
|
|
|
newStack->next = thisStack;
|
2017-05-26 05:24:38 +02:00
|
|
|
thisStack = newStack;
|
2017-05-29 08:02:59 +02:00
|
|
|
debug(kSludgeDebugStackMachine, "Variable %s was added to stack quick",
|
|
|
|
getTextFromAnyVar(va));
|
2017-05-26 05:24:38 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-05-29 08:02:59 +02:00
|
|
|
bool stackSetByIndex(variableStack *vS, unsigned int theIndex,
|
|
|
|
const variable &va) {
|
|
|
|
while (theIndex--) {
|
|
|
|
vS = vS->next;
|
|
|
|
if (!vS)
|
|
|
|
return fatal("Index past end of stack.");
|
2017-05-26 05:24:38 +02:00
|
|
|
}
|
2017-05-29 08:02:59 +02:00
|
|
|
return copyVariable(va, vS->thisVar);
|
2017-05-26 05:24:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
variable *stackGetByIndex(variableStack *vS, unsigned int theIndex) {
|
2017-05-29 08:02:59 +02:00
|
|
|
while (theIndex--) {
|
|
|
|
vS = vS->next;
|
|
|
|
if (!vS) {
|
2017-05-26 05:24:38 +02:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
2017-05-29 08:02:59 +02:00
|
|
|
return &(vS->thisVar);
|
2017-05-26 05:24:38 +02:00
|
|
|
}
|
|
|
|
|
2017-05-29 08:02:59 +02:00
|
|
|
int deleteVarFromStack(const variable &va, variableStack *&thisStack,
|
|
|
|
bool allOfEm) {
|
|
|
|
variableStack * * huntVar = &thisStack;
|
2017-05-26 05:24:38 +02:00
|
|
|
variableStack *killMe;
|
|
|
|
int reply = 0;
|
|
|
|
|
2017-05-29 08:02:59 +02:00
|
|
|
while (*huntVar) {
|
|
|
|
if (compareVars((*huntVar)->thisVar, va)) {
|
|
|
|
killMe = *huntVar;
|
|
|
|
*huntVar = killMe->next;
|
|
|
|
unlinkVar(killMe->thisVar);
|
2017-05-26 05:24:38 +02:00
|
|
|
delete killMe;
|
2017-05-29 08:02:59 +02:00
|
|
|
if (!allOfEm)
|
|
|
|
return 1;
|
|
|
|
reply++;
|
2017-05-26 05:24:38 +02:00
|
|
|
} else {
|
2017-05-29 08:02:59 +02:00
|
|
|
huntVar = &((*huntVar)->next);
|
2017-05-26 05:24:38 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return reply;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Would be a LOT better just to keep this up to date in the above function... ah well
|
|
|
|
variableStack *stackFindLast(variableStack *hunt) {
|
|
|
|
if (hunt == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
while (hunt->next)
|
|
|
|
hunt = hunt->next;
|
|
|
|
|
|
|
|
return hunt;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool getValueType(int &toHere, variableType vT, const variable &v) {
|
|
|
|
//if (! v) return false;
|
|
|
|
if (v.varType != vT) {
|
2017-05-29 08:02:59 +02:00
|
|
|
char *e1 =
|
|
|
|
joinStrings(
|
|
|
|
"Can only perform specified operation on a value which is of type ",
|
|
|
|
typeName[vT]);
|
|
|
|
char *e2 = joinStrings("... value supplied was of type ",
|
|
|
|
typeName[v.varType]);
|
2017-05-26 05:24:38 +02:00
|
|
|
fatal(e1, e2);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
toHere = v.varData.intValue;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void trimStack(variableStack *&stack) {
|
|
|
|
variableStack *killMe = stack;
|
2017-05-29 08:02:59 +02:00
|
|
|
stack = stack->next;
|
2017-05-26 05:24:38 +02:00
|
|
|
|
2017-05-29 08:02:59 +02:00
|
|
|
debug(kSludgeDebugStackMachine, "Variable %s was removed from stack",
|
|
|
|
getTextFromAnyVar(killMe->thisVar));
|
2017-05-26 05:24:38 +02:00
|
|
|
|
|
|
|
// When calling this, we've ALWAYS checked that stack != NULL
|
2017-05-29 08:02:59 +02:00
|
|
|
unlinkVar(killMe->thisVar);
|
2017-05-26 05:24:38 +02:00
|
|
|
delete killMe;
|
|
|
|
}
|
|
|
|
/*
|
2017-05-29 08:02:59 +02:00
|
|
|
void debugVar (FILE * fp, const variable & thisVar) {
|
|
|
|
switch (thisVar.varType) {
|
|
|
|
case SVT_INT:
|
|
|
|
fprintf (fp, "integer value %i", thisVar.varData.intValue);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SVT_FUNC:
|
|
|
|
fprintf (fp, "pointer to function %i", thisVar.varData.intValue);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SVT_BUILT:
|
|
|
|
fprintf (fp, "pointer to bif %i", thisVar.varData.intValue);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SVT_OBJTYPE:
|
|
|
|
fprintf (fp, "object type %i", thisVar.varData.intValue);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SVT_STRING:
|
|
|
|
fprintf (fp, "\"%s\"", thisVar.varData.theString);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SVT_FILE:
|
|
|
|
fprintf (fp, "file handle %i", thisVar.varData.intValue);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SVT_NULL:
|
|
|
|
fprintf (fp, "null");
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
fprintf (fp, "unknown variable type");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*/
|
2017-05-26 21:25:11 +02:00
|
|
|
|
|
|
|
} // End of namespace Sludge
|