openclonk/src/script/C4Aul.cpp

341 lines
8.1 KiB
C++
Raw Normal View History

2009-05-08 13:28:41 +00:00
/*
* OpenClonk, http://www.openclonk.org
*
* Copyright (c) 2001, 2004, 2007-2008 Sven Eberhardt
2011-09-01 14:58:52 +00:00
* Copyright (c) 2001, 2009 Peter Wortmann
* Copyright (c) 2006-2009, 2011 Günther Brammer
* Copyright (c) 2007 Matthes Bender
* Copyright (c) 2009 Nicolas Hake
* Copyright (c) 2010 Benjamin Herr
* Copyright (c) 2010 Martin Plicht
2009-05-08 13:28:41 +00:00
* Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de
*
* Portions might be copyrighted by other authors who have contributed
* to OpenClonk.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
* See isc_license.txt for full license and disclaimer.
*
* "Clonk" is a registered trademark of Matthes Bender.
* See clonk_trademark_license.txt for full license.
*/
// Miscellaneous script engine bits
2009-05-08 13:28:41 +00:00
#include <C4Include.h>
#include <C4Aul.h>
2009-04-21 21:44:56 +00:00
#include <C4AulExec.h>
#include <C4AulDebug.h>
2009-05-08 13:28:41 +00:00
#include <C4Config.h>
#include <C4Def.h>
#include <C4Log.h>
#include <C4Components.h>
2010-01-13 17:07:58 +00:00
#include <C4LangStringTable.h>
2009-05-08 13:28:41 +00:00
C4AulError::C4AulError(): shown(false) {}
2009-05-08 13:28:41 +00:00
void C4AulError::show()
2010-03-28 18:58:01 +00:00
{
shown = true;
2009-05-08 13:28:41 +00:00
// simply log error message
2010-03-28 18:58:01 +00:00
if (sMessage)
2009-05-08 13:28:41 +00:00
DebugLog(sMessage.getData());
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4AulScript::C4AulScript()
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// not compiled
State = ASS_NONE;
// defaults
Temporary = false;
// prepare lists
Prev = Next = NULL;
Engine = NULL;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4AulScript::~C4AulScript()
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// clear
Clear();
// unreg
Unreg();
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4AulScript::Unreg()
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// remove from list
if (Prev) Prev->Next = Next; else if (Engine) Engine->Child0 = Next;
if (Next) Next->Prev = Prev; else if (Engine) Engine->ChildL = Prev;
Prev = Next = NULL;
Engine = NULL;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4AulScript::Clear()
2010-03-28 18:58:01 +00:00
{
// reset flags
2009-05-08 13:28:41 +00:00
State = ASS_NONE;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4AulScript::Reg2List(C4AulScriptEngine *pEngine)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// already regged? (def reloaded)
if (Engine) return;
2009-05-08 13:28:41 +00:00
// reg to list
if ((Engine = pEngine))
2010-03-28 18:58:01 +00:00
{
if ((Prev = Engine->ChildL))
2009-05-08 13:28:41 +00:00
Prev->Next = this;
else
Engine->Child0 = this;
Engine->ChildL = this;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
else
Prev = NULL;
Next = NULL;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
std::string C4AulScript::Translate(const std::string &text) const
{
try
{
if (stringTable)
return stringTable->Translate(text);
}
catch (C4LangStringTable::NoSuchTranslation &)
{
// Ignore, soldier on
}
if (Engine && Engine != this)
return Engine->Translate(text);
throw C4LangStringTable::NoSuchTranslation(text);
}
2012-02-01 02:49:50 +00:00
C4AulScriptFunc::C4AulScriptFunc(C4AulScript *pOwner, C4ScriptHost *pOrgScript, const char *pName, const char *Script):
C4AulFunc(pOwner, pName),
CodePos(0),
Script(Script),
OwnerOverloaded(NULL),
ParCount(0),
pOrgScript(pOrgScript),
tProfileTime(0)
2011-10-14 23:38:59 +00:00
{
for (int i = 0; i < C4AUL_MAX_Par; i++) ParType[i] = C4V_Any;
}
2012-02-01 02:49:50 +00:00
C4AulScriptFunc::C4AulScriptFunc(C4AulScript *pOwner, const C4AulScriptFunc &FromFunc):
C4AulFunc(pOwner, FromFunc.GetName()),
CodePos(0),
Script(FromFunc.Script),
VarNamed(FromFunc.VarNamed),
ParNamed(FromFunc.ParNamed),
OwnerOverloaded(NULL),
ParCount(FromFunc.ParCount),
pOrgScript(FromFunc.pOrgScript),
tProfileTime(0)
2010-03-28 18:58:01 +00:00
{
for (int i = 0; i < C4AUL_MAX_Par; i++)
2009-05-08 13:28:41 +00:00
ParType[i] = FromFunc.ParType[i];
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4AulScriptFunc::~C4AulScriptFunc()
{
if (OwnerOverloaded) OwnerOverloaded->DecRef();
}
void C4AulScriptFunc::SetOverloaded(C4AulFunc * f)
{
if (OwnerOverloaded) OwnerOverloaded->DecRef();
OwnerOverloaded = f;
if (f) f->IncRef();
}
2009-05-08 13:28:41 +00:00
/*--- C4AulScriptEngine ---*/
C4AulScriptEngine::C4AulScriptEngine():
GlobalPropList(0), warnCnt(0), errCnt(0), lineCnt(0)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// /me r b engine
Engine = this;
ScriptName.Ref(C4CFN_System);
GlobalNamedNames.Reset();
GlobalNamed.Reset();
GlobalNamed.SetNameList(&GlobalNamedNames);
GlobalConstNames.Reset();
GlobalConsts.Reset();
GlobalConsts.SetNameList(&GlobalConstNames);
Child0 = ChildL = NULL;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4PropList * C4AulScriptEngine::GetPropList()
{
if (!GlobalPropList)
{
GlobalPropList = C4PropList::NewAnon(NULL, NULL, ::Strings.RegString("Global"));
RegisterGlobalConstant("Global", C4VPropList(GlobalPropList));
}
return GlobalPropList;
}
2009-05-08 13:28:41 +00:00
C4AulScriptEngine::~C4AulScriptEngine() { Clear(); }
void C4AulScriptEngine::Clear()
2010-03-28 18:58:01 +00:00
{
#ifndef NOAULDEBUG
2009-04-21 21:44:56 +00:00
// stop debugger
delete C4AulDebug::GetDebugger();
#endif
while (Child0)
if (Child0->Delete()) delete Child0;
else Child0->Unreg();
2009-05-08 13:28:41 +00:00
// clear own stuff
if (GlobalPropList)
GlobalPropList->Clear();
// clear inherited
C4AulScript::Clear();
2009-05-08 13:28:41 +00:00
// reset values
warnCnt = errCnt = lineCnt = 0;
2009-05-08 13:28:41 +00:00
// resetting name lists will reset all data lists, too
// except not...
GlobalNamedNames.Reset();
GlobalConstNames.Reset();
GlobalConsts.Reset();
GlobalConsts.SetNameList(&GlobalConstNames);
GlobalNamed.Reset();
GlobalNamed.SetNameList(&GlobalNamedNames);
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4AulScriptEngine::RegisterGlobalConstant(const char *szName, const C4Value &rValue)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// Register name and set value.
// AddName returns the index of existing element if the name is assigned already.
// That is OK, since it will only change the value of the global ("overload" it).
// A warning would be nice here. However, this warning would show up whenever a script
// containing globals constants is recompiled.
GlobalConsts[GlobalConstNames.AddName(szName)] = rValue;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4AulScriptEngine::GetGlobalConstant(const char *szName, C4Value *pTargetValue)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// get index of global by name
int32_t iConstIndex = GlobalConstNames.GetItemNr(szName);
// not found?
if (iConstIndex<0) return false;
// if it's found, assign the value if desired
if (pTargetValue) *pTargetValue = GlobalConsts[iConstIndex];
// constant exists
return true;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
bool C4AulScriptEngine::Denumerate(C4ValueNumbers * numbers)
2010-03-28 18:58:01 +00:00
{
GlobalNamed.Denumerate(numbers);
2009-05-08 13:28:41 +00:00
// runtime data only: don't denumerate consts
GameScript.ScenPropList.Denumerate(numbers);
return true;
2010-03-28 18:58:01 +00:00
}
2009-04-21 21:44:56 +00:00
void C4AulScriptEngine::CompileFunc(StdCompiler *pComp, C4ValueNumbers * numbers)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
C4ValueMapData GlobalNamedDefault;
GlobalNamedDefault.SetNameList(&GlobalNamedNames);
pComp->Value(mkNamingAdapt(mkParAdapt(GlobalNamed, numbers), "StaticVariables", GlobalNamedDefault));
pComp->Value(mkNamingAdapt(mkParAdapt(*GameScript.ScenPropList._getPropList(), numbers), "Scenario"));
2010-03-28 18:58:01 +00:00
}
2009-04-21 21:44:56 +00:00
std::list<const char*> C4AulScriptEngine::GetFunctionNames(C4PropList * p)
{
std::list<const char*> functions;
std::list<const char*> global_functions;
if (!p) p = GetPropList();
const C4ValueArray * a = p->GetProperties();
for (int i = 0; i < a->GetSize(); ++i)
{
C4String * key = (*a)[i].getStr();
if (!key) continue;
C4AulFunc * f = p->GetFunc(key);
if (!f) continue;
if (!f->GetPublic()) continue;
if (p->HasProperty(key))
functions.push_back(key->GetCStr());
else
global_functions.push_back(key->GetCStr());
}
delete a;
functions.sort();
functions.push_back(0);
global_functions.sort();
functions.splice(functions.end(), global_functions);
return functions;
}
2009-05-08 13:28:41 +00:00
/*--- C4AulFuncMap ---*/
C4AulFuncMap::C4AulFuncMap(): FuncCnt(0)
2010-03-28 18:58:01 +00:00
{
memset(Funcs, 0, sizeof (C4AulFunc *) * HashSize);
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4AulFuncMap::~C4AulFuncMap()
2010-03-28 18:58:01 +00:00
{
assert(!FuncCnt);
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
unsigned int C4AulFuncMap::Hash(const char * name)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
// Fowler/Noll/Vo hash
unsigned int h = 2166136261u;
while (*name)
h = (h ^ *(name++)) * 16777619;
return h;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4AulFunc * C4AulFuncMap::GetFirstFunc(C4String * Name)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
if (!Name) return NULL;
C4AulFunc * Func = Funcs[Hash(Name->GetCStr()) % HashSize];
while (Func && Name->GetCStr() != Func->GetName())
2009-05-08 13:28:41 +00:00
Func = Func->MapNext;
return Func;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
C4AulFunc * C4AulFuncMap::GetNextSNFunc(const C4AulFunc * After)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
C4AulFunc * Func = After->MapNext;
while (Func && After->GetName() != Func->GetName())
2009-05-08 13:28:41 +00:00
Func = Func->MapNext;
return Func;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4AulFuncMap::Add(C4AulFunc * func)
2010-03-28 18:58:01 +00:00
{
++FuncCnt;
2009-05-08 13:28:41 +00:00
// Get a pointer to the bucket
C4AulFunc ** pFunc = &(Funcs[Hash(func->GetName()) % HashSize]);
// move the current first to the second position
func->MapNext = *pFunc;
2009-05-08 13:28:41 +00:00
// Add the func
*pFunc = func;
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
void C4AulFuncMap::Remove(C4AulFunc * func)
2010-03-28 18:58:01 +00:00
{
C4AulFunc ** pFunc = &Funcs[Hash(func->GetName()) % HashSize];
2009-05-08 13:28:41 +00:00
while (*pFunc != func)
2010-03-28 18:58:01 +00:00
{
2009-05-08 13:28:41 +00:00
pFunc = &((*pFunc)->MapNext);
assert(*pFunc); // crash on remove of a not contained func
2010-03-28 18:58:01 +00:00
}
2009-05-08 13:28:41 +00:00
*pFunc = (*pFunc)->MapNext;
--FuncCnt;
2010-03-28 18:58:01 +00:00
}
C4AulScriptEngine ScriptEngine;