2009-05-08 13:28:41 +00:00
|
|
|
/*
|
|
|
|
* OpenClonk, http://www.openclonk.org
|
|
|
|
*
|
2009-06-05 13:41:20 +00:00
|
|
|
* Copyright (c) 2001, 2006-2007 Sven Eberhardt
|
|
|
|
* Copyright (c) 2001-2002, 2004, 2007 Peter Wortmann
|
2011-09-01 14:58:52 +00:00
|
|
|
* Copyright (c) 2006-2009, 2011 Günther Brammer
|
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.
|
|
|
|
*/
|
|
|
|
// links aul scripts; i.e. resolves includes & appends, etc
|
|
|
|
|
|
|
|
#include <C4Include.h>
|
|
|
|
#include <C4Aul.h>
|
|
|
|
|
|
|
|
#include <C4Def.h>
|
2011-03-03 16:10:22 +00:00
|
|
|
#include <C4DefList.h>
|
2009-06-05 18:46:03 +00:00
|
|
|
#include <C4Material.h>
|
2009-05-08 13:28:41 +00:00
|
|
|
#include <C4Game.h>
|
2009-06-15 21:47:26 +00:00
|
|
|
#include <C4GameObjects.h>
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
// ResolveAppends and ResolveIncludes must be called both
|
|
|
|
// for each script. ResolveAppends has to be called first!
|
2009-08-15 18:50:32 +00:00
|
|
|
bool C4AulScript::ResolveAppends(C4DefList *rDefs)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// resolve local appends
|
2009-08-15 18:50:32 +00:00
|
|
|
if (State != ASS_PREPARSED) return false;
|
2011-02-25 23:48:19 +00:00
|
|
|
for (std::list<C4ID>::iterator a = Appends.begin(); a != Appends.end(); ++a)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2011-02-25 23:48:19 +00:00
|
|
|
if (*a)
|
2009-05-08 13:28:41 +00:00
|
|
|
{
|
2011-02-25 23:48:19 +00:00
|
|
|
C4Def *Def = rDefs->ID2Def(*a);
|
2009-05-08 13:28:41 +00:00
|
|
|
if (Def)
|
2012-01-25 02:50:24 +00:00
|
|
|
{
|
|
|
|
if (std::find(Def->Script.SourceScripts.begin(), Def->Script.SourceScripts.end(), GetScriptHost()) == Def->Script.SourceScripts.end())
|
|
|
|
Def->Script.SourceScripts.push_back(GetScriptHost());
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
// save id in buffer because AulWarn will use the buffer of C4IdText
|
|
|
|
// to get the id of the object in which the error occurs...
|
|
|
|
// (stupid static buffers...)
|
2012-05-25 22:22:22 +00:00
|
|
|
Warn("#appendto %s not found", a->ToString());
|
2009-05-08 13:28:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// append to all defs
|
2010-03-28 18:58:01 +00:00
|
|
|
for (int i = 0; i < rDefs->GetDefCount(); i++)
|
2009-05-08 13:28:41 +00:00
|
|
|
{
|
|
|
|
C4Def *pDef = rDefs->GetDef(i);
|
2010-03-28 18:58:01 +00:00
|
|
|
if (!pDef) break;
|
2011-09-29 01:49:21 +00:00
|
|
|
if (pDef == GetPropList()) continue;
|
2009-05-08 13:28:41 +00:00
|
|
|
// append
|
2012-01-25 02:50:24 +00:00
|
|
|
if (std::find(pDef->Script.SourceScripts.begin(), pDef->Script.SourceScripts.end(), GetScriptHost()) == pDef->Script.SourceScripts.end())
|
|
|
|
pDef->Script.SourceScripts.push_back(GetScriptHost());
|
2009-05-08 13:28:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-03-28 18:58:01 +00:00
|
|
|
return true;
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
2009-08-15 18:50:32 +00:00
|
|
|
bool C4AulScript::ResolveIncludes(C4DefList *rDefs)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// Had been preparsed?
|
2012-01-25 03:15:39 +00:00
|
|
|
if (State != ASS_PREPARSED) return false;
|
2009-05-08 13:28:41 +00:00
|
|
|
// has already been resolved?
|
2010-03-28 18:58:01 +00:00
|
|
|
if (IncludesResolved) return true;
|
2009-05-08 13:28:41 +00:00
|
|
|
// catch circular includes
|
|
|
|
if (Resolving)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
C4AulParseError(this, "Circular include chain detected - ignoring all includes!").show();
|
|
|
|
IncludesResolved = true;
|
|
|
|
State = ASS_LINKED;
|
2009-08-15 18:50:32 +00:00
|
|
|
return false;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
Resolving=true;
|
|
|
|
// append all includes to local script
|
2012-01-26 23:20:55 +00:00
|
|
|
for (std::list<C4ID>::reverse_iterator i = Includes.rbegin(); i != Includes.rend(); ++i)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2011-02-25 23:48:19 +00:00
|
|
|
C4Def *Def = rDefs->ID2Def(*i);
|
2009-05-08 13:28:41 +00:00
|
|
|
if (Def)
|
|
|
|
{
|
|
|
|
// resolve #includes in included script first (#include-chains :( )
|
2010-03-28 18:58:01 +00:00
|
|
|
if (!((C4AulScript &)Def->Script).IncludesResolved)
|
2009-05-08 13:28:41 +00:00
|
|
|
if (!Def->Script.ResolveIncludes(rDefs))
|
|
|
|
continue; // skip this #include
|
|
|
|
|
2012-01-26 23:20:55 +00:00
|
|
|
for (std::list<C4ScriptHost *>::reverse_iterator s = Def->Script.SourceScripts.rbegin(); s != Def->Script.SourceScripts.rend(); ++s)
|
2012-01-25 02:50:24 +00:00
|
|
|
{
|
|
|
|
if (std::find(GetScriptHost()->SourceScripts.begin(), GetScriptHost()->SourceScripts.end(), *s) == GetScriptHost()->SourceScripts.end())
|
|
|
|
GetScriptHost()->SourceScripts.push_front(*s);
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// save id in buffer because AulWarn will use the buffer of C4IdText
|
|
|
|
// to get the id of the object in which the error occurs...
|
|
|
|
// (stupid static buffers...)
|
2012-05-25 22:22:22 +00:00
|
|
|
Warn("#include %s not found", i->ToString());
|
2009-05-08 13:28:41 +00:00
|
|
|
}
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
IncludesResolved = true;
|
|
|
|
// includes/appends are resolved now (for this script)
|
|
|
|
Resolving=false;
|
|
|
|
State = ASS_LINKED;
|
2009-08-15 18:50:32 +00:00
|
|
|
return true;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
2012-05-25 15:25:53 +00:00
|
|
|
void C4AulScript::LinkFunctions()
|
|
|
|
{
|
|
|
|
for (C4AulFunc *f = Func0; f; f = f->Next)
|
|
|
|
{
|
|
|
|
C4AulScriptFunc *sf = f->SFunc();
|
|
|
|
if (!sf) continue;
|
|
|
|
sf->OwnerOverloaded = GetPropList()->GetFunc(sf->Name);
|
|
|
|
if (sf->OwnerOverloaded && sf->OwnerOverloaded->Owner == this)
|
|
|
|
sf->OwnerOverloaded->OverloadedBy = sf;
|
|
|
|
GetPropList()->SetPropertyByS(sf->Name, C4VFunction(sf));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-05-08 13:28:41 +00:00
|
|
|
void C4AulScript::UnLink()
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// do not unlink temporary (e.g., DirectExec-script in ReloadDef)
|
|
|
|
if (Temporary) return;
|
|
|
|
|
2011-10-14 23:38:59 +00:00
|
|
|
C4PropList * p = GetPropList();
|
|
|
|
if (p) p->C4PropList::Thaw();
|
2010-09-22 01:33:57 +00:00
|
|
|
|
2009-05-08 13:28:41 +00:00
|
|
|
// delete included/appended functions
|
2012-05-25 15:25:53 +00:00
|
|
|
C4AulFunc* pFunc = FuncL;
|
2010-03-28 18:58:01 +00:00
|
|
|
while (pFunc)
|
2009-05-08 13:28:41 +00:00
|
|
|
{
|
2012-05-25 15:25:53 +00:00
|
|
|
C4AulFunc* pNextFunc = pFunc->Prev;
|
2009-05-08 13:28:41 +00:00
|
|
|
|
2012-05-25 15:25:53 +00:00
|
|
|
// clear stuff that's set in LinkFunctions
|
2009-05-08 13:28:41 +00:00
|
|
|
pFunc->UnLink();
|
2012-05-25 15:25:53 +00:00
|
|
|
C4Value v;
|
|
|
|
if (p && p->GetFunc(pFunc->Name) == pFunc && pFunc->SFunc())
|
|
|
|
{
|
|
|
|
p->ResetProperty(pFunc->Name);
|
|
|
|
C4AulFunc * overloaded = pFunc->SFunc()->OwnerOverloaded;
|
|
|
|
if (overloaded && overloaded != p->GetFunc(pFunc->Name))
|
|
|
|
p->SetPropertyByS(pFunc->Name, C4VFunction(overloaded));
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
2012-05-25 15:25:53 +00:00
|
|
|
if (pFunc->SFunc() && pFunc->Owner != Engine && pFunc->Owner != pFunc->SFunc()->pOrgScript)
|
|
|
|
{
|
|
|
|
pFunc->RemoveFromScript();
|
|
|
|
pFunc->DecRef();
|
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
pFunc = pNextFunc;
|
|
|
|
}
|
2011-10-13 16:01:02 +00:00
|
|
|
|
2009-05-08 13:28:41 +00:00
|
|
|
// includes will have to be re-resolved now
|
|
|
|
IncludesResolved = false;
|
|
|
|
|
|
|
|
if (State > ASS_PREPARSED) State = ASS_PREPARSED;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
void C4AulScriptFunc::UnLink()
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
OwnerOverloaded = NULL;
|
|
|
|
|
|
|
|
C4AulFunc::UnLink();
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
2011-02-06 20:37:19 +00:00
|
|
|
bool C4AulScript::ReloadScript(const char *szPath, const char *szLanguage)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2010-03-27 16:05:02 +00:00
|
|
|
return false;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
void C4AulScriptEngine::Link(C4DefList *rDefs)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
try
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
// resolve appends
|
2012-05-15 17:32:58 +00:00
|
|
|
for (C4ScriptHost *s = Child0; s; s = s->Next)
|
2012-01-25 03:15:39 +00:00
|
|
|
s->ResolveAppends(rDefs);
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
// resolve includes
|
2012-05-15 17:32:58 +00:00
|
|
|
for (C4ScriptHost *s = Child0; s; s = s->Next)
|
2012-01-25 03:15:39 +00:00
|
|
|
s->ResolveIncludes(rDefs);
|
2009-05-08 13:28:41 +00:00
|
|
|
|
2012-01-26 23:20:55 +00:00
|
|
|
// put script functions into the proplist
|
|
|
|
LinkFunctions();
|
|
|
|
|
2009-05-08 13:28:41 +00:00
|
|
|
// parse the scripts to byte code
|
2012-05-15 17:32:58 +00:00
|
|
|
for (C4ScriptHost *s = Child0; s; s = s->Next)
|
2012-01-25 03:15:39 +00:00
|
|
|
s->Parse();
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
// engine is always parsed (for global funcs)
|
|
|
|
State = ASS_PARSED;
|
|
|
|
|
|
|
|
// update material pointers
|
2009-06-05 18:46:03 +00:00
|
|
|
::MaterialMap.UpdateScriptPointers();
|
2009-05-08 13:28:41 +00:00
|
|
|
|
2009-05-19 22:30:49 +00:00
|
|
|
rDefs->CallEveryDefinition();
|
2012-05-05 22:06:33 +00:00
|
|
|
|
|
|
|
// Done modifying the proplists now
|
2012-05-15 17:32:58 +00:00
|
|
|
for (C4ScriptHost *s = Child0; s; s = s->Next)
|
2012-05-05 22:06:33 +00:00
|
|
|
s->GetPropList()->Freeze();
|
|
|
|
GetPropList()->Freeze();
|
|
|
|
|
2009-05-08 13:28:41 +00:00
|
|
|
// display state
|
2009-05-11 13:09:53 +00:00
|
|
|
LogF("C4AulScriptEngine linked - %d line%s, %d warning%s, %d error%s",
|
2010-03-28 18:58:01 +00:00
|
|
|
lineCnt, (lineCnt != 1 ? "s" : ""), warnCnt, (warnCnt != 1 ? "s" : ""), errCnt, (errCnt != 1 ? "s" : ""));
|
2009-05-08 13:28:41 +00:00
|
|
|
|
2010-03-27 16:05:02 +00:00
|
|
|
// reset counters
|
2012-01-25 03:15:53 +00:00
|
|
|
warnCnt = errCnt = lineCnt = 0;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
catch (C4AulError *err)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// error??! show it!
|
|
|
|
err->show();
|
|
|
|
delete err;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
|
|
|
|
void C4AulScriptEngine::ReLink(C4DefList *rDefs)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2009-05-08 13:28:41 +00:00
|
|
|
// unlink scripts
|
|
|
|
UnLink();
|
|
|
|
|
|
|
|
// unlink defs
|
|
|
|
if (rDefs) rDefs->ResetIncludeDependencies();
|
|
|
|
|
|
|
|
// re-link
|
|
|
|
Link(rDefs);
|
|
|
|
|
|
|
|
// update effect pointers
|
2009-06-15 21:47:26 +00:00
|
|
|
::Objects.UpdateScriptPointers();
|
2009-05-08 13:28:41 +00:00
|
|
|
|
|
|
|
// update material pointers
|
2009-06-05 18:46:03 +00:00
|
|
|
::MaterialMap.UpdateScriptPointers();
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|
2011-02-06 20:37:19 +00:00
|
|
|
bool C4AulScriptEngine::ReloadScript(const char *szScript, C4DefList *pDefs, const char *szLanguage)
|
2010-03-28 18:58:01 +00:00
|
|
|
{
|
2012-05-15 17:32:58 +00:00
|
|
|
C4ScriptHost * s;
|
2012-01-25 03:15:39 +00:00
|
|
|
for (s = Child0; s; s = s->Next)
|
|
|
|
if (s->ReloadScript(szScript, szLanguage))
|
|
|
|
break;
|
|
|
|
if (!s)
|
2010-03-27 16:05:02 +00:00
|
|
|
return false;
|
|
|
|
// relink
|
|
|
|
ReLink(pDefs);
|
|
|
|
// ok
|
|
|
|
return true;
|
2010-03-28 18:58:01 +00:00
|
|
|
}
|
2009-05-08 13:28:41 +00:00
|
|
|
|