OpenClonk
C4ScriptHost.cpp
Go to the documentation of this file.
1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 1998-2000, Matthes Bender
5  * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
6  * Copyright (c) 2009-2016, The OpenClonk Team and contributors
7  *
8  * Distributed under the terms of the ISC license; see accompanying file
9  * "COPYING" for details.
10  *
11  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
12  * See accompanying file "TRADEMARK" for details.
13  *
14  * To redistribute this file separately, substitute the full license texts
15  * for the above references.
16  */
17 
18 /* Handles script file components (calls, inheritance, function maps) */
19 
20 #include "C4Include.h"
21 #include "script/C4ScriptHost.h"
22 
23 #include "object/C4Def.h"
24 #include "script/C4AulCompiler.h"
25 #include "script/C4AulParse.h"
26 #include "script/C4AulScriptFunc.h"
27 #include "script/C4AulScriptFunc.h"
28 #include "script/C4Effect.h"
29 
30 /*--- C4ScriptHost ---*/
31 
33 {
34  Script = nullptr;
35  stringTable = nullptr;
36  SourceScripts.push_back(this);
37  // prepare include list
38  IncludesResolved = false;
39  Resolving=false;
40  Includes.clear();
41  Appends.clear();
42 }
44 {
45  Unreg();
46  Clear();
47 }
48 
50 {
53  ast.reset();
54  Script.Clear();
57  SourceScripts.clear();
58  SourceScripts.push_back(this);
59  if (stringTable)
60  {
62  stringTable = nullptr;
63  }
64  // remove includes
65  Includes.clear();
66  Appends.clear();
67  // reset flags
68  State = ASS_NONE;
69  enabledWarnings.clear();
70 }
71 
73 {
74  // Remove owned functions from their parents. This solves a problem
75  // where overloading a definition would unload the C4ScriptHost, but
76  // keep around global functions, which then contained dangling pointers.
77  for (const auto &box : ownedFunctions)
78  {
79  assert(box.GetType() == C4V_Function);
80  C4AulScriptFunc *func = box._getFunction()->SFunc();
81  C4PropList *parent = func->Parent;
82  if (parent == GetPropList())
83  continue;
84  assert(parent == &::ScriptEngine);
85  C4Value v;
86  parent->GetPropertyByS(func->Name, &v);
87  if (v.getFunction() == func)
88  {
89  // If the function we're deleting is the top-level function in
90  // the inheritance chain, promote the next one in its stead;
91  // if there is no overloaded function, remove the property.
92  parent->Thaw();
93  if (func->OwnerOverloaded)
94  parent->SetPropertyByS(func->Name, C4VFunction(func->OwnerOverloaded));
95  else
96  parent->ResetProperty(func->Name);
97  }
98  else
99  {
100  C4AulScriptFunc *func_chain = v.getFunction()->SFunc();
101  assert(func_chain != func);
102  while (func_chain)
103  {
104  // Unlink the removed function from the inheritance chain
105  if (func_chain->OwnerOverloaded == func)
106  {
107  func_chain->OwnerOverloaded = func->OwnerOverloaded;
108  func->OwnerOverloaded = nullptr; // func_chain now takes care of this.
109  func->DecRef(); // decrease rc because func_chain no longer has a reference to func.
110  break;
111  }
112  assert(func_chain->OwnerOverloaded && "Removed function not found in inheritance chain");
113  func_chain = func_chain->OwnerOverloaded->SFunc();
114  }
115  }
116  }
117  ownedFunctions.clear();
118 }
119 
121 {
122  // delete all static proplists associated to this script host.
123  // Note that just clearing the vector is not enough in case of
124  // cyclic references.
125  for (C4Value& value: ownedPropLists)
126  {
127  C4PropList* plist = value.getPropList();
128  if (plist)
129  {
130  if (plist->Delete()) delete plist;
131  else plist->Clear();
132  }
133  }
134  ownedPropLists.clear();
135 }
136 
138 {
139  // remove from list
140  if (Prev) Prev->Next = Next; else if (Engine) Engine->Child0 = Next;
141  if (Next) Next->Prev = Prev; else if (Engine) Engine->ChildL = Prev;
142  Prev = Next = nullptr;
143  Engine = nullptr;
144 }
145 
147 {
148  // already regged? (def reloaded)
149  if (Engine) return;
150  // reg to list
151  if ((Engine = pEngine))
152  {
153  if ((Prev = Engine->ChildL))
154  Prev->Next = this;
155  else
156  Engine->Child0 = this;
157  Engine->ChildL = this;
158  }
159  else
160  Prev = nullptr;
161  Next = nullptr;
162 }
163 
164 bool C4ScriptHost::Load(C4Group &hGroup, const char *szFilename,
165  const char *szLanguage, class C4LangStringTable *pLocalTable)
166 {
167  // Base load
168  bool fSuccess = C4ComponentHost::Load(hGroup,szFilename,szLanguage);
169  // String Table
170  if (stringTable != pLocalTable)
171  {
173  stringTable = pLocalTable;
175  }
176  // set name
178  // preparse script
179  MakeScript();
180  // Success
181  return fSuccess;
182 }
183 
184 bool C4ScriptHost::LoadData(const char *szFilename, const char *szData, class C4LangStringTable *pLocalTable)
185 {
186  // String Table
187  if (stringTable != pLocalTable)
188  {
190  stringTable = pLocalTable;
192  }
193  ScriptName.Copy(szFilename);
194 
195  StdStrBuf tempScript;
196  tempScript.Copy(szData);
197 
198  Script.Clear();
199  if(stringTable)
200  stringTable->ReplaceStrings(tempScript, Script);
201  else
202  Script.Take(tempScript);
203 
204  Preparse();
205  return true;
206 }
207 
209 {
210  // clear prev
211  Script.Clear();
212 
213  // create script
214  if (stringTable)
215  {
217  }
218  else
219  {
220  Script.Ref(GetDataBuf());
221  }
222 
223  // preparse script
224  Preparse();
225 }
226 
227 bool C4ScriptHost::ReloadScript(const char *szPath, const char *szLanguage)
228 {
229  // this?
230  if (SEqualNoCase(szPath, GetFilePath()) || (stringTable && SEqualNoCase(szPath, stringTable->GetFilePath())))
231  {
232  // try reload
233  char szParentPath[_MAX_PATH_LEN]; C4Group ParentGrp;
234  if (GetParentPath(szPath, szParentPath))
235  if (ParentGrp.Open(szParentPath))
236  if (Load(ParentGrp, nullptr, szLanguage, stringTable))
237  return true;
238  }
239  return false;
240 }
241 
242 std::string C4ScriptHost::Translate(const std::string &text) const
243 {
244  if (stringTable)
245  return stringTable->Translate(text);
247 }
248 
249 /*--- C4ExtraScriptHost ---*/
250 
252  ParserPropList(C4PropList::NewStatic(nullptr, nullptr, parent_key_name))
253 {
254 }
255 
257 {
258  Clear();
259 }
260 
262 {
264  ParserPropList._getPropList()->Clear();
265 }
266 
268 {
269  return ParserPropList._getPropList()->IsStatic();
270 }
271 
272 
273 /*--- C4ScenarioObjectsScriptHost ---*/
274 
276 {
277  // Note that "ScenarioObjects" is a fake key name under which you cannot access this prop list from script.
278  // It's just given to have a proper name when script errors are reported.
279 }
280 
281 /*--- C4DefScriptHost ---*/
282 
284 {
285  bool r = C4ScriptHost::Parse();
286  assert(Def);
287 
288  // Check category
289  if (!Def->GetPlane() && Def->Category & C4D_SortLimit)
290  {
291  int Plane; bool gotplane = true;
292  switch (Def->Category & C4D_SortLimit)
293  {
294  case C4D_StaticBack: Plane = 100; break;
295  case C4D_Structure: Plane = C4Plane_Structure; break;
296  case C4D_Vehicle: Plane = 300; break;
297  case C4D_Living: Plane = 400; break;
298  case C4D_Object: Plane = 500; break;
299  case C4D_StaticBack | C4D_Background: Plane = -500; break;
300  case C4D_Structure | C4D_Background: Plane = -400; break;
301  case C4D_Vehicle | C4D_Background: Plane = -300; break;
302  case C4D_Living | C4D_Background: Plane = -200; break;
303  case C4D_Object | C4D_Background: Plane = -100; break;
304  case C4D_StaticBack | C4D_Foreground: Plane = 1100; break;
305  case C4D_Structure | C4D_Foreground: Plane = 1200; break;
306  case C4D_Vehicle | C4D_Foreground: Plane = 1300; break;
307  case C4D_Living | C4D_Foreground: Plane = 1400; break;
308  case C4D_Object | C4D_Foreground: Plane = 1500; break;
309  default:
310  Warn("Def %s (%s) has invalid category", Def->GetName(), Def->GetDataString().getData());
311  gotplane = false;
312  break;
313  }
314  if (gotplane) Def->SetProperty(P_Plane, C4VInt(Plane));
315  }
316  if (!Def->GetPlane())
317  {
318  Warn("Def %s (%s) has invalid Plane", Def->GetName(), Def->GetDataString().getData());
320  }
321  return r;
322 }
323 
325 
327 {
328 public:
329  C4PropListScen(const C4PropListStatic * parent, C4String * key): C4PropListStatic(nullptr, parent, key)
330  {
333  }
334  void SetPropertyByS(C4String * k, const C4Value & to) override
335  {
336  if (k == &Strings.P[P_Prototype])
337  {
338  DebugLog("ERROR: Attempt to set Scenario.Prototype.");
339  return;
340  }
342  }
343 };
344 
345 /*--- C4GameScriptHost ---*/
346 
347 C4GameScriptHost::C4GameScriptHost(): ScenPrototype(0), ScenPropList(0) { }
349 
350 bool C4GameScriptHost::Load(C4Group & g, const char * f, const char * l, C4LangStringTable * t)
351 {
352  assert(ScriptEngine.GetPropList());
353  C4PropListStatic * pScen = new C4PropListScen(nullptr, &::Strings.P[P_Scenario]);
354  ScenPropList.SetPropList(pScen);
358  return C4ScriptHost::Load(g, f, l, t);
359 }
360 
361 bool C4GameScriptHost::LoadData(const char * f, const char * d, C4LangStringTable * t)
362 {
363  assert(ScriptEngine.GetPropList());
364  C4PropListStatic * pScen = new C4PropListScen(nullptr, &::Strings.P[P_Scenario]);
365  ScenPropList.SetPropList(pScen);
369  return C4ScriptHost::LoadData(f, d, t);
370 }
371 
373 {
375  ScenPropList.Set0();
377  delete pScenarioEffects; pScenarioEffects=nullptr;
378 }
379 
381 {
383  return p ? p->IsStatic() : nullptr;
384 }
385 
387 {
388  ScenPropList.Denumerate(numbers);
390 }
391 
392 C4Value C4GameScriptHost::Call(const char *szFunction, C4AulParSet *Pars, bool fPassError)
393 {
394  return ScenPropList._getPropList()->Call(szFunction, Pars, fPassError);
395 }
396 
const int32_t C4D_Foreground
Definition: C4Def.h:53
const int32_t C4D_SortLimit
Definition: C4Def.h:57
const int32_t C4D_Background
Definition: C4Def.h:50
const int32_t C4D_Structure
Definition: C4Def.h:41
const int32_t C4D_Living
Definition: C4Def.h:43
const int32_t C4D_StaticBack
Definition: C4Def.h:40
const int32_t C4Plane_Structure
Definition: C4Def.h:60
const int32_t C4D_Object
Definition: C4Def.h:44
const int32_t C4D_Vehicle
Definition: C4Def.h:42
C4AulScriptEngine ScriptEngine
Definition: C4Globals.cpp:43
C4StringTable Strings
Definition: C4Globals.cpp:42
bool DebugLog(const char *strMessage)
Definition: C4Log.cpp:282
C4GameScriptHost GameScript
@ ASS_NONE
Definition: C4ScriptHost.h:33
@ P_Plane
@ P_Scenario
@ P_Prototype
C4Value C4VFunction(C4AulFunc *pFn)
Definition: C4Value.h:247
@ C4V_Function
Definition: C4Value.h:31
C4Value C4VInt(int32_t i)
Definition: C4Value.h:239
C4Value C4VPropList(C4PropList *p)
Definition: C4Value.h:242
#define _MAX_PATH_LEN
bool SEqualNoCase(const char *szStr1, const char *szStr2, int iLen)
Definition: Standard.cpp:213
bool GetParentPath(const char *szFilename, char *szBuffer)
Definition: StdFile.cpp:186
C4RefCntPointer< C4String > Name
Definition: C4AulFunc.h:60
virtual C4AulScriptFunc * SFunc()
Definition: C4AulFunc.h:65
C4PropListStatic * Parent
Definition: C4AulFunc.h:55
C4ScriptHost * ChildL
Definition: C4Aul.h:121
C4PropListStatic * GetPropList()
Definition: C4Aul.h:151
C4ScriptHost * Child0
Definition: C4Aul.h:121
void RegisterGlobalConstant(const char *szName, const C4Value &rValue)
Definition: C4Aul.cpp:123
C4AulFunc * OwnerOverloaded
C4AulScriptFunc * SFunc() override
bool Load(C4Group &hGroup, const char *szFilename, const char *szLanguage=nullptr)
const StdStrBuf & GetDataBuf() const
const char * GetFilePath() const
int32_t Category
Definition: C4Def.h:117
int32_t GetPlane()
Definition: C4Def.h:211
bool Parse() override
C4PropListStatic * GetPropList() override
void Denumerate(C4ValueNumbers *) override
Definition: C4Effect.cpp:176
C4PropListStatic * GetPropList() override
~C4ExtraScriptHost() override
C4ExtraScriptHost(C4String *parent_key_name=nullptr)
C4PropListStatic * GetPropList() override
C4Value ScenPrototype
Definition: C4ScriptHost.h:165
C4Effect * pScenarioEffects
Definition: C4ScriptHost.h:166
bool Load(C4Group &, const char *, const char *, C4LangStringTable *) override
C4Value Call(const char *szFunction, C4AulParSet *pPars=nullptr, bool fPassError=false)
void Denumerate(C4ValueNumbers *numbers)
~C4GameScriptHost() override
C4Value ScenPropList
Definition: C4ScriptHost.h:164
bool LoadData(const char *, const char *, C4LangStringTable *) override
bool Open(const char *group_name, bool do_create=false)
Definition: C4Group.cpp:660
const std::string & Translate(const std::string &text) const
void ReplaceStrings(StdStrBuf &rBuf)
void Thaw()
Definition: C4PropList.h:133
virtual bool Delete()
Definition: C4PropList.h:94
virtual class C4PropListStatic * IsStatic()
Definition: C4PropList.h:89
virtual bool GetPropertyByS(const C4String *k, C4Value *pResult) const
Definition: C4PropList.cpp:726
virtual void ResetProperty(C4String *k)
Definition: C4PropList.cpp:961
C4PropList * GetPrototype() const
Definition: C4PropList.h:85
C4Value Call(C4PropertyName k, C4AulParSet *pPars=nullptr, bool fPassErrors=false)
Definition: C4PropList.h:114
virtual void SetPropertyByS(C4String *k, const C4Value &to)
Definition: C4PropList.cpp:940
void Clear()
Definition: C4PropList.h:70
void SetProperty(C4PropertyName k, const C4Value &to)
Definition: C4PropList.h:124
static C4PropListStatic * NewStatic(C4PropList *prototype, const C4PropListStatic *parent, C4String *key)
Definition: C4PropList.cpp:46
C4PropListScen(const C4PropListStatic *parent, C4String *key)
void SetPropertyByS(C4String *k, const C4Value &to) override
StdStrBuf GetDataString() const
Definition: C4PropList.cpp:229
const char * GetName() const override
Definition: C4PropList.cpp:243
void DecRef()
Definition: C4StringTable.h:28
std::vector< C4Value > ownedPropLists
Definition: C4ScriptHost.h:102
C4Set< C4Property > LocalValues
Definition: C4ScriptHost.h:93
std::vector< C4Value > ownedFunctions
Definition: C4ScriptHost.h:97
bool Preparse()
Definition: C4AulParse.cpp:693
std::string Translate(const std::string &text) const
C4ScriptHost * Next
Definition: C4ScriptHost.h:78
~C4ScriptHost() override
virtual bool Load(C4Group &hGroup, const char *szFilename, const char *szLanguage, C4LangStringTable *pLocalTable)
void DeleteOwnedPropLists()
virtual bool ReloadScript(const char *szPath, const char *szLanguage)
C4AulScriptEngine * Engine
Definition: C4ScriptHost.h:77
C4AulScriptState State
Definition: C4ScriptHost.h:94
virtual bool Parse()
C4LangStringTable * stringTable
Definition: C4ScriptHost.h:92
void UnlinkOwnedFunctions()
StdStrBuf Script
Definition: C4ScriptHost.h:91
bool IncludesResolved
Definition: C4ScriptHost.h:89
StdCopyStrBuf ScriptName
Definition: C4ScriptHost.h:58
std::list< StdCopyStrBuf > Appends
Definition: C4ScriptHost.h:81
std::list< StdCopyStrBuf > Includes
Definition: C4ScriptHost.h:80
virtual C4PropListStatic * GetPropList()
Definition: C4ScriptHost.h:51
std::deque< C4ScriptHost * > SourceScripts
Definition: C4ScriptHost.h:57
void Warn(const char *pMsg,...) GNUC_FORMAT_ATTRIBUTE_O
Definition: C4AulParse.cpp:124
void Reg2List(C4AulScriptEngine *pEngine)
virtual bool LoadData(const char *szFilename, const char *szData, class C4LangStringTable *pLocalTable)
C4ScriptHost * Prev
Definition: C4ScriptHost.h:78
void Clear()
C4String P[P_LAST]
void SetPropList(C4PropList *PropList)
Definition: C4Value.h:141
C4PropList * _getPropList() const
Definition: C4Value.h:129
void Set0()
Definition: C4Value.h:332
C4AulFunc * getFunction() const
Definition: C4Value.h:119
void Denumerate(C4ValueNumbers *)
Definition: C4Value.cpp:251
void Ref(const char *pnData)
Definition: StdBuf.h:455
const char * getData() const
Definition: StdBuf.h:442
void Copy()
Definition: StdBuf.h:467
void Clear()
Definition: StdBuf.h:466
void Take(char *pnData)
Definition: StdBuf.h:457