OpenClonk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros
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  break;
109  }
110  assert(func_chain->OwnerOverloaded && "Removed function not found in inheritance chain");
111  func_chain = func_chain->OwnerOverloaded->SFunc();
112  }
113  }
114  }
115  ownedFunctions.clear();
116 }
117 
119 {
120  // delete all static proplists associated to this script host.
121  // Note that just clearing the vector is not enough in case of
122  // cyclic references.
123  for (C4Value& value: ownedPropLists)
124  {
125  C4PropList* plist = value.getPropList();
126  if (plist)
127  {
128  if (plist->Delete()) delete plist;
129  else plist->Clear();
130  }
131  }
132  ownedPropLists.clear();
133 }
134 
136 {
137  // remove from list
138  if (Prev) Prev->Next = Next; else if (Engine) Engine->Child0 = Next;
139  if (Next) Next->Prev = Prev; else if (Engine) Engine->ChildL = Prev;
140  Prev = Next = nullptr;
141  Engine = nullptr;
142 }
143 
145 {
146  // already regged? (def reloaded)
147  if (Engine) return;
148  // reg to list
149  if ((Engine = pEngine))
150  {
151  if ((Prev = Engine->ChildL))
152  Prev->Next = this;
153  else
154  Engine->Child0 = this;
155  Engine->ChildL = this;
156  }
157  else
158  Prev = nullptr;
159  Next = nullptr;
160 }
161 
162 bool C4ScriptHost::Load(C4Group &hGroup, const char *szFilename,
163  const char *szLanguage, class C4LangStringTable *pLocalTable)
164 {
165  // Base load
166  bool fSuccess = C4ComponentHost::Load(hGroup,szFilename,szLanguage);
167  // String Table
168  if (stringTable != pLocalTable)
169  {
171  stringTable = pLocalTable;
173  }
174  // set name
176  // preparse script
177  MakeScript();
178  // Success
179  return fSuccess;
180 }
181 
182 bool C4ScriptHost::LoadData(const char *szFilename, const char *szData, class C4LangStringTable *pLocalTable)
183 {
184  // String Table
185  if (stringTable != pLocalTable)
186  {
188  stringTable = pLocalTable;
190  }
191  ScriptName.Copy(szFilename);
192 
193  StdStrBuf tempScript;
194  tempScript.Copy(szData);
195 
196  Script.Clear();
197  if(stringTable)
198  stringTable->ReplaceStrings(tempScript, Script);
199  else
200  Script.Take(tempScript);
201 
202  Preparse();
203  return true;
204 }
205 
207 {
208  // clear prev
209  Script.Clear();
210 
211  // create script
212  if (stringTable)
213  {
215  }
216  else
217  {
218  Script.Ref(GetDataBuf());
219  }
220 
221  // preparse script
222  Preparse();
223 }
224 
225 bool C4ScriptHost::ReloadScript(const char *szPath, const char *szLanguage)
226 {
227  // this?
228  if (SEqualNoCase(szPath, GetFilePath()) || (stringTable && SEqualNoCase(szPath, stringTable->GetFilePath())))
229  {
230  // try reload
231  char szParentPath[_MAX_PATH + 1]; C4Group ParentGrp;
232  if (GetParentPath(szPath, szParentPath))
233  if (ParentGrp.Open(szParentPath))
234  if (Load(ParentGrp, nullptr, szLanguage, stringTable))
235  return true;
236  }
237  return false;
238 }
239 
240 std::string C4ScriptHost::Translate(const std::string &text) const
241 {
242  if (stringTable)
243  return stringTable->Translate(text);
245 }
246 
247 /*--- C4ExtraScriptHost ---*/
248 
250  ParserPropList(C4PropList::NewStatic(nullptr, nullptr, parent_key_name))
251 {
252 }
253 
255 {
256  Clear();
257 }
258 
260 {
262  ParserPropList._getPropList()->Clear();
263 }
264 
266 {
267  return ParserPropList._getPropList()->IsStatic();
268 }
269 
270 
271 /*--- C4ScenarioObjectsScriptHost ---*/
272 
274 {
275  // Note that "ScenarioObjects" is a fake key name under which you cannot access this prop list from script.
276  // It's just given to have a proper name when script errors are reported.
277 }
278 
279 /*--- C4DefScriptHost ---*/
280 
282 {
283  bool r = C4ScriptHost::Parse();
284  assert(Def);
285 
286  // Check category
287  if (!Def->GetPlane() && Def->Category & C4D_SortLimit)
288  {
289  int Plane; bool gotplane = true;
290  switch (Def->Category & C4D_SortLimit)
291  {
292  case C4D_StaticBack: Plane = 100; break;
293  case C4D_Structure: Plane = C4Plane_Structure; break;
294  case C4D_Vehicle: Plane = 300; break;
295  case C4D_Living: Plane = 400; break;
296  case C4D_Object: Plane = 500; break;
297  case C4D_StaticBack | C4D_Background: Plane = -500; break;
298  case C4D_Structure | C4D_Background: Plane = -400; break;
299  case C4D_Vehicle | C4D_Background: Plane = -300; break;
300  case C4D_Living | C4D_Background: Plane = -200; break;
301  case C4D_Object | C4D_Background: Plane = -100; break;
302  case C4D_StaticBack | C4D_Foreground: Plane = 1100; break;
303  case C4D_Structure | C4D_Foreground: Plane = 1200; break;
304  case C4D_Vehicle | C4D_Foreground: Plane = 1300; break;
305  case C4D_Living | C4D_Foreground: Plane = 1400; break;
306  case C4D_Object | C4D_Foreground: Plane = 1500; break;
307  default:
308  Warn("Def %s (%s) has invalid category", Def->GetName(), Def->GetDataString().getData());
309  gotplane = false;
310  break;
311  }
312  if (gotplane) Def->SetProperty(P_Plane, C4VInt(Plane));
313  }
314  if (!Def->GetPlane())
315  {
316  Warn("Def %s (%s) has invalid Plane", Def->GetName(), Def->GetDataString().getData());
318  }
319  return r;
320 }
321 
323 
325 {
326 public:
327  C4PropListScen(const C4PropListStatic * parent, C4String * key): C4PropListStatic(nullptr, parent, key)
328  {
331  }
332  void SetPropertyByS(C4String * k, const C4Value & to) override
333  {
334  if (k == &Strings.P[P_Prototype])
335  {
336  DebugLog("ERROR: Attempt to set Scenario.Prototype.");
337  return;
338  }
340  }
341 };
342 
343 /*--- C4GameScriptHost ---*/
344 
345 C4GameScriptHost::C4GameScriptHost(): ScenPrototype(0), ScenPropList(0) { }
347 
348 bool C4GameScriptHost::Load(C4Group & g, const char * f, const char * l, C4LangStringTable * t)
349 {
350  assert(ScriptEngine.GetPropList());
351  C4PropListStatic * pScen = new C4PropListScen(nullptr, &::Strings.P[P_Scenario]);
352  ScenPropList.SetPropList(pScen);
354  ScenPrototype.SetPropList(pScen->GetPrototype());
356  return C4ScriptHost::Load(g, f, l, t);
357 }
358 
359 bool C4GameScriptHost::LoadData(const char * f, const char * d, C4LangStringTable * t)
360 {
361  assert(ScriptEngine.GetPropList());
362  C4PropListStatic * pScen = new C4PropListScen(nullptr, &::Strings.P[P_Scenario]);
363  ScenPropList.SetPropList(pScen);
365  ScenPrototype.SetPropList(pScen->GetPrototype());
367  return C4ScriptHost::LoadData(f, d, t);
368 }
369 
371 {
373  ScenPropList.Set0();
375  delete pScenarioEffects; pScenarioEffects=nullptr;
376 }
377 
379 {
381  return p ? p->IsStatic() : nullptr;
382 }
383 
385 {
386  ScenPropList.Denumerate(numbers);
388 }
389 
390 C4Value C4GameScriptHost::Call(const char *szFunction, C4AulParSet *Pars, bool fPassError)
391 {
392  return ScenPropList._getPropList()->Call(szFunction, Pars, fPassError);
393 }
394 
virtual void ResetProperty(C4String *k)
Definition: C4PropList.cpp:969
const char * getData() const
Definition: StdBuf.h:442
C4String P[P_LAST]
void RegisterGlobalConstant(const char *szName, const C4Value &rValue)
const std::string & Translate(const std::string &text) const
bool IncludesResolved
Definition: C4ScriptHost.h:88
virtual bool ReloadScript(const char *szPath, const char *szLanguage)
void Thaw()
Definition: C4PropList.h:129
const int32_t C4D_Vehicle
Definition: C4Def.h:42
C4PropListStatic * GetPropList()
Definition: C4Aul.h:151
bool Load(C4Group &hGroup, const char *szFilename, const char *szLanguage=nullptr)
const int32_t C4Plane_Structure
Definition: C4Def.h:60
C4PropListStatic * GetPropList() override
C4GameScriptHost GameScript
C4AulScriptEngine ScriptEngine
Definition: C4Globals.cpp:43
void Clear()
Definition: StdBuf.h:466
int32_t GetPlane()
Definition: C4Def.h:212
std::list< StdCopyStrBuf > Appends
Definition: C4ScriptHost.h:80
bool DebugLog(const char *strMessage)
Definition: C4Log.cpp:270
C4Value Call(const char *szFunction, C4AulParSet *pPars=nullptr, bool fPassError=false)
void Denumerate(C4ValueNumbers *) override
Definition: C4Effect.cpp:176
bool LoadData(const char *, const char *, C4LangStringTable *) override
C4Value C4VInt(int32_t i)
Definition: C4Value.h:242
void SetProperty(C4PropertyName k, const C4Value &to)
Definition: C4PropList.h:120
bool SEqualNoCase(const char *szStr1, const char *szStr2, int iLen)
Definition: Standard.cpp:185
void Set0()
Definition: C4Value.h:336
virtual class C4PropListStatic * IsStatic()
Definition: C4PropList.h:85
C4AulScriptEngine * Engine
Definition: C4ScriptHost.h:76
void Clear()
#define _MAX_PATH
virtual C4PropListStatic * GetPropList()
Definition: C4ScriptHost.h:50
C4AulFunc * OwnerOverloaded
void Clear()
Definition: C4PropList.h:66
const StdStrBuf & GetDataBuf() const
const char * GetName() const override
Definition: C4PropList.cpp:267
C4PropListStatic * GetPropList() override
bool GetParentPath(const char *szFilename, char *szBuffer)
Definition: StdFile.cpp:189
void Reg2List(C4AulScriptEngine *pEngine)
const int32_t C4D_Object
Definition: C4Def.h:44
void Denumerate(C4ValueNumbers *)
Definition: C4Value.cpp:251
void UnlinkOwnedFunctions()
bool Load(C4Group &, const char *, const char *, C4LangStringTable *) override
C4PropListScen(const C4PropListStatic *parent, C4String *key)
C4StringTable Strings
Definition: C4Globals.cpp:42
virtual bool GetPropertyByS(const C4String *k, C4Value *pResult) const
Definition: C4PropList.cpp:753
C4Value C4VPropList(C4PropList *p)
Definition: C4Value.h:245
C4AulScriptFunc * SFunc() override
void DeleteOwnedPropLists()
bool Open(const char *szGroupName, bool fCreate=false)
Definition: C4Group.cpp:514
C4Value ScenPropList
Definition: C4ScriptHost.h:163
bool Parse() override
void Take(char *pnData)
Definition: StdBuf.h:457
std::list< StdCopyStrBuf > Includes
Definition: C4ScriptHost.h:79
~C4ExtraScriptHost() override
const int32_t C4D_Background
Definition: C4Def.h:50
virtual bool LoadData(const char *szFilename, const char *szData, class C4LangStringTable *pLocalTable)
void ReplaceStrings(StdStrBuf &rBuf)
virtual bool Parse()
void Denumerate(C4ValueNumbers *numbers)
C4Value ScenPrototype
Definition: C4ScriptHost.h:164
const int32_t C4D_StaticBack
Definition: C4Def.h:40
static C4PropListStatic * NewStatic(C4PropList *prototype, const C4PropListStatic *parent, C4String *key)
Definition: C4PropList.cpp:70
void Ref(const char *pnData)
Definition: StdBuf.h:455
C4Set< C4Property > LocalValues
Definition: C4ScriptHost.h:92
const int32_t C4D_Structure
Definition: C4Def.h:41
void Warn(const char *pMsg,...) GNUC_FORMAT_ATTRIBUTE_O
Definition: C4AulParse.cpp:123
~C4GameScriptHost() override
bool Preparse()
Definition: C4AulParse.cpp:679
const int32_t C4D_Living
Definition: C4Def.h:43
C4PropListStatic * GetPropList() override
std::string Translate(const std::string &text) const
virtual bool Delete()
Definition: C4PropList.h:90
int32_t Category
Definition: C4Def.h:117
C4Effect * pScenarioEffects
Definition: C4ScriptHost.h:165
C4ExtraScriptHost(C4String *parent_key_name=nullptr)
C4ScriptHost * ChildL
Definition: C4Aul.h:121
C4Value C4VFunction(C4AulFunc *pFn)
Definition: C4Value.h:250
virtual void SetPropertyByS(C4String *k, const C4Value &to)
Definition: C4PropList.cpp:948
void SetPropList(C4PropList *PropList)
Definition: C4Value.h:141
std::list< C4ScriptHost * > SourceScripts
Definition: C4ScriptHost.h:56
C4PropList * _getPropList() const
Definition: C4Value.h:129
virtual C4AulScriptFunc * SFunc()
Definition: C4AulFunc.h:66
std::vector< C4Value > ownedFunctions
Definition: C4ScriptHost.h:96
virtual bool Load(C4Group &hGroup, const char *szFilename, const char *szLanguage, C4LangStringTable *pLocalTable)
const char * GetFilePath() const
const int32_t C4D_SortLimit
Definition: C4Def.h:57
C4LangStringTable * stringTable
Definition: C4ScriptHost.h:91
void Copy()
Definition: StdBuf.h:467
StdCopyStrBuf ScriptName
Definition: C4ScriptHost.h:57
void SetPropertyByS(C4String *k, const C4Value &to) override
C4AulScriptState State
Definition: C4ScriptHost.h:93
C4AulFunc * getFunction() const
Definition: C4Value.h:119
~C4ScriptHost() override
C4ScriptHost * Next
Definition: C4ScriptHost.h:77
C4ScriptHost * Prev
Definition: C4ScriptHost.h:77
C4ScriptHost * Child0
Definition: C4Aul.h:121
const int32_t C4D_Foreground
Definition: C4Def.h:53
StdStrBuf Script
Definition: C4ScriptHost.h:90
C4Value Call(C4PropertyName k, C4AulParSet *pPars=nullptr, bool fPassErrors=false)
Definition: C4PropList.h:110
StdStrBuf GetDataString() const
Definition: C4PropList.cpp:253
std::vector< C4Value > ownedPropLists
Definition: C4ScriptHost.h:101