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 "script/C4AulAST.h"
24 #include "script/C4AulCompiler.h"
25 #include "script/C4AulParse.h"
26 #include "script/C4AulScriptFunc.h"
27 #include "object/C4Def.h"
28 #include "script/C4AulScriptFunc.h"
29 #include "script/C4Effect.h"
30 
31 /*--- C4ScriptHost ---*/
32 
34  // prepare lists
35  Prev(nullptr), Next(nullptr),
36  Engine(nullptr),
37  State(ASS_NONE) // not compiled
38 {
39  Script = nullptr;
40  stringTable = 0;
41  SourceScripts.push_back(this);
42  // prepare include list
43  IncludesResolved = false;
44  Resolving=false;
45  Includes.clear();
46  Appends.clear();
47 }
49 {
50  Unreg();
51  Clear();
52 }
53 
55 {
58  ast.reset();
59  Script.Clear();
62  SourceScripts.clear();
63  SourceScripts.push_back(this);
64  if (stringTable)
65  {
67  stringTable = nullptr;
68  }
69  // remove includes
70  Includes.clear();
71  Appends.clear();
72  // reset flags
73  State = ASS_NONE;
74  enabledWarnings.clear();
75 }
76 
78 {
79  // Remove owned functions from their parents. This solves a problem
80  // where overloading a definition would unload the C4ScriptHost, but
81  // keep around global functions, which then contained dangling pointers.
82  for (const auto &box : ownedFunctions)
83  {
84  assert(box.GetType() == C4V_Function);
85  C4AulScriptFunc *func = box._getFunction()->SFunc();
86  C4PropList *parent = func->Parent;
87  if (parent == GetPropList())
88  continue;
89  assert(parent == &::ScriptEngine);
90  C4Value v;
91  parent->GetPropertyByS(func->Name, &v);
92  if (v.getFunction() == func)
93  {
94  // If the function we're deleting is the top-level function in
95  // the inheritance chain, promote the next one in its stead;
96  // if there is no overloaded function, remove the property.
97  parent->Thaw();
98  if (func->OwnerOverloaded)
99  parent->SetPropertyByS(func->Name, C4VFunction(func->OwnerOverloaded));
100  else
101  parent->ResetProperty(func->Name);
102  }
103  else
104  {
105  C4AulScriptFunc *func_chain = v.getFunction()->SFunc();
106  assert(func_chain != func);
107  while (func_chain)
108  {
109  // Unlink the removed function from the inheritance chain
110  if (func_chain->OwnerOverloaded == func)
111  {
112  func_chain->OwnerOverloaded = func->OwnerOverloaded;
113  break;
114  }
115  assert(func_chain->OwnerOverloaded && "Removed function not found in inheritance chain");
116  func_chain = func_chain->OwnerOverloaded->SFunc();
117  }
118  }
119  }
120  ownedFunctions.clear();
121 }
122 
124 {
125  // delete all static proplists associated to this script host.
126  // Note that just clearing the vector is not enough in case of
127  // cyclic references.
128  for (C4Value& value: ownedPropLists)
129  {
130  C4PropList* plist = value.getPropList();
131  if (plist)
132  {
133  if (plist->Delete()) delete plist;
134  else plist->Clear();
135  }
136  }
137  ownedPropLists.clear();
138 }
139 
141 {
142  // remove from list
143  if (Prev) Prev->Next = Next; else if (Engine) Engine->Child0 = Next;
144  if (Next) Next->Prev = Prev; else if (Engine) Engine->ChildL = Prev;
145  Prev = Next = nullptr;
146  Engine = nullptr;
147 }
148 
150 {
151  // already regged? (def reloaded)
152  if (Engine) return;
153  // reg to list
154  if ((Engine = pEngine))
155  {
156  if ((Prev = Engine->ChildL))
157  Prev->Next = this;
158  else
159  Engine->Child0 = this;
160  Engine->ChildL = this;
161  }
162  else
163  Prev = nullptr;
164  Next = nullptr;
165 }
166 
167 bool C4ScriptHost::Load(C4Group &hGroup, const char *szFilename,
168  const char *szLanguage, class C4LangStringTable *pLocalTable)
169 {
170  // Base load
171  bool fSuccess = C4ComponentHost::Load(hGroup,szFilename,szLanguage);
172  // String Table
173  if (stringTable != pLocalTable)
174  {
176  stringTable = pLocalTable;
178  }
179  // set name
181  // preparse script
182  MakeScript();
183  // Success
184  return fSuccess;
185 }
186 
187 bool C4ScriptHost::LoadData(const char *szFilename, const char *szData, class C4LangStringTable *pLocalTable)
188 {
189  // String Table
190  if (stringTable != pLocalTable)
191  {
193  stringTable = pLocalTable;
195  }
196  ScriptName.Copy(szFilename);
197 
198  StdStrBuf tempScript;
199  tempScript.Copy(szData);
200 
201  Script.Clear();
202  if(stringTable)
203  stringTable->ReplaceStrings(tempScript, Script);
204  else
205  Script.Take(tempScript);
206 
207  Preparse();
208  return true;
209 }
210 
212 {
213  // clear prev
214  Script.Clear();
215 
216  // create script
217  if (stringTable)
218  {
220  }
221  else
222  {
223  Script.Ref(GetDataBuf());
224  }
225 
226  // preparse script
227  Preparse();
228 }
229 
230 bool C4ScriptHost::ReloadScript(const char *szPath, const char *szLanguage)
231 {
232  // this?
233  if (SEqualNoCase(szPath, GetFilePath()) || (stringTable && SEqualNoCase(szPath, stringTable->GetFilePath())))
234  {
235  // try reload
236  char szParentPath[_MAX_PATH + 1]; C4Group ParentGrp;
237  if (GetParentPath(szPath, szParentPath))
238  if (ParentGrp.Open(szParentPath))
239  if (Load(ParentGrp, nullptr, szLanguage, stringTable))
240  return true;
241  }
242  return false;
243 }
244 
245 std::string C4ScriptHost::Translate(const std::string &text) const
246 {
247  if (stringTable)
248  return stringTable->Translate(text);
250 }
251 
252 /*--- C4ExtraScriptHost ---*/
253 
255  ParserPropList(C4PropList::NewStatic(nullptr, nullptr, parent_key_name))
256 {
257 }
258 
260 {
261  Clear();
262 }
263 
265 {
267  ParserPropList._getPropList()->Clear();
268 }
269 
271 {
272  return ParserPropList._getPropList()->IsStatic();
273 }
274 
275 
276 /*--- C4ScenarioObjectsScriptHost ---*/
277 
279 {
280  // Note that "ScenarioObjects" is a fake key name under which you cannot access this prop list from script.
281  // It's just given to have a proper name when script errors are reported.
282 }
283 
284 /*--- C4DefScriptHost ---*/
285 
287 {
288  bool r = C4ScriptHost::Parse();
289  assert(Def);
290 
291  // Check category
292  if (!Def->GetPlane() && Def->Category & C4D_SortLimit)
293  {
294  int Plane; bool gotplane = true;
295  switch (Def->Category & C4D_SortLimit)
296  {
297  case C4D_StaticBack: Plane = 100; break;
298  case C4D_Structure: Plane = C4Plane_Structure; break;
299  case C4D_Vehicle: Plane = 300; break;
300  case C4D_Living: Plane = 400; break;
301  case C4D_Object: Plane = 500; break;
302  case C4D_StaticBack | C4D_Background: Plane = -500; break;
303  case C4D_Structure | C4D_Background: Plane = -400; break;
304  case C4D_Vehicle | C4D_Background: Plane = -300; break;
305  case C4D_Living | C4D_Background: Plane = -200; break;
306  case C4D_Object | C4D_Background: Plane = -100; break;
307  case C4D_StaticBack | C4D_Foreground: Plane = 1100; break;
308  case C4D_Structure | C4D_Foreground: Plane = 1200; break;
309  case C4D_Vehicle | C4D_Foreground: Plane = 1300; break;
310  case C4D_Living | C4D_Foreground: Plane = 1400; break;
311  case C4D_Object | C4D_Foreground: Plane = 1500; break;
312  default:
313  Warn("Def %s (%s) has invalid category", Def->GetName(), Def->GetDataString().getData());
314  gotplane = false;
315  break;
316  }
317  if (gotplane) Def->SetProperty(P_Plane, C4VInt(Plane));
318  }
319  if (!Def->GetPlane())
320  {
321  Warn("Def %s (%s) has invalid Plane", Def->GetName(), Def->GetDataString().getData());
323  }
324  return r;
325 }
326 
328 
330 {
331 public:
332  C4PropListScen(const C4PropListStatic * parent, C4String * key): C4PropListStatic(nullptr, parent, key)
333  {
336  }
337  virtual void SetPropertyByS(C4String * k, const C4Value & to)
338  {
339  if (k == &Strings.P[P_Prototype])
340  {
341  DebugLog("ERROR: Attempt to set Scenario.Prototype.");
342  return;
343  }
345  }
346 };
347 
348 /*--- C4GameScriptHost ---*/
349 
350 C4GameScriptHost::C4GameScriptHost(): ScenPrototype(0), ScenPropList(0) { }
352 
353 bool C4GameScriptHost::Load(C4Group & g, const char * f, const char * l, C4LangStringTable * t)
354 {
355  assert(ScriptEngine.GetPropList());
356  C4PropListStatic * pScen = new C4PropListScen(nullptr, &::Strings.P[P_Scenario]);
357  ScenPropList.SetPropList(pScen);
359  ScenPrototype.SetPropList(pScen->GetPrototype());
361  return C4ScriptHost::Load(g, f, l, t);
362 }
363 
364 bool C4GameScriptHost::LoadData(const char * f, const char * d, C4LangStringTable * t)
365 {
366  assert(ScriptEngine.GetPropList());
367  C4PropListStatic * pScen = new C4PropListScen(nullptr, &::Strings.P[P_Scenario]);
368  ScenPropList.SetPropList(pScen);
370  ScenPrototype.SetPropList(pScen->GetPrototype());
372  return C4ScriptHost::LoadData(f, d, t);
373 }
374 
376 {
378  ScenPropList.Set0();
380  delete pScenarioEffects; pScenarioEffects=nullptr;
381 }
382 
384 {
386  return p ? p->IsStatic() : 0;
387 }
388 
390 {
391  ScenPropList.Denumerate(numbers);
393 }
394 
395 C4Value C4GameScriptHost::Call(const char *szFunction, C4AulParSet *Pars, bool fPassError)
396 {
397  return ScenPropList._getPropList()->Call(szFunction, Pars, fPassError);
398 }
399 
virtual void ResetProperty(C4String *k)
Definition: C4PropList.cpp:950
const char * getData() const
Definition: StdBuf.h:450
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 Parse()
virtual bool ReloadScript(const char *szPath, const char *szLanguage)
void Thaw()
Definition: C4PropList.h:131
virtual const char * GetName() const
Definition: C4PropList.cpp:267
const int32_t C4D_Vehicle
Definition: C4Def.h:44
C4PropListStatic * GetPropList()
Definition: C4Aul.h:153
bool Load(C4Group &hGroup, const char *szFilename, const char *szLanguage=nullptr)
const int32_t C4Plane_Structure
Definition: C4Def.h:62
C4GameScriptHost GameScript
C4AulScriptEngine ScriptEngine
Definition: C4Globals.cpp:43
void Clear()
Definition: StdBuf.h:474
int32_t GetPlane()
Definition: C4Def.h:214
std::list< StdCopyStrBuf > Appends
Definition: C4ScriptHost.h:80
bool DebugLog(const char *strMessage)
Definition: C4Log.cpp:273
C4Value C4VInt(int32_t i)
Definition: C4Value.h:242
void SetProperty(C4PropertyName k, const C4Value &to)
Definition: C4PropList.h:122
bool SEqualNoCase(const char *szStr1, const char *szStr2, int iLen)
Definition: Standard.cpp:177
virtual C4PropListStatic * GetPropList()
C4Value Call(const char *szFunction, C4AulParSet *pPars=0, bool fPassError=false)
void Set0()
Definition: C4Value.h:336
virtual class C4PropListStatic * IsStatic()
Definition: C4PropList.h:87
virtual C4PropListStatic * GetPropList()
C4AulScriptEngine * Engine
Definition: C4ScriptHost.h:76
void Clear()
#define _MAX_PATH
virtual C4PropListStatic * GetPropList()
Definition: C4ScriptHost.h:50
virtual bool Load(C4Group &, const char *, const char *, C4LangStringTable *)
C4AulFunc * OwnerOverloaded
void Clear()
Definition: C4PropList.h:68
const StdStrBuf & GetDataBuf() const
bool GetParentPath(const char *szFilename, char *szBuffer)
Definition: StdFile.cpp:199
void Reg2List(C4AulScriptEngine *pEngine)
const int32_t C4D_Object
Definition: C4Def.h:46
void Denumerate(C4ValueNumbers *)
Definition: C4Value.cpp:253
C4AulScriptFunc * SFunc()
void UnlinkOwnedFunctions()
C4PropListScen(const C4PropListStatic *parent, C4String *key)
C4StringTable Strings
Definition: C4Globals.cpp:42
virtual bool GetPropertyByS(const C4String *k, C4Value *pResult) const
Definition: C4PropList.cpp:734
C4Value C4VPropList(C4PropList *p)
Definition: C4Value.h:245
void DeleteOwnedPropLists()
bool Open(const char *szGroupName, bool fCreate=false)
Definition: C4Group.cpp:514
C4Value ScenPropList
Definition: C4ScriptHost.h:163
void Take(char *pnData)
Definition: StdBuf.h:465
std::list< StdCopyStrBuf > Includes
Definition: C4ScriptHost.h:79
virtual void SetPropertyByS(C4String *k, const C4Value &to)
const int32_t C4D_Background
Definition: C4Def.h:52
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:42
static C4PropListStatic * NewStatic(C4PropList *prototype, const C4PropListStatic *parent, C4String *key)
Definition: C4PropList.cpp:70
void Ref(const char *pnData)
Definition: StdBuf.h:463
C4Set< C4Property > LocalValues
Definition: C4ScriptHost.h:92
const int32_t C4D_Structure
Definition: C4Def.h:43
void Warn(const char *pMsg,...) GNUC_FORMAT_ATTRIBUTE_O
Definition: C4AulParse.cpp:132
bool Preparse()
Definition: C4AulParse.cpp:688
void Denumerate(C4ValueNumbers *)
Definition: C4Effect.cpp:176
const int32_t C4D_Living
Definition: C4Def.h:45
std::string Translate(const std::string &text) const
virtual C4PropListStatic * GetPropList()
virtual bool Delete()
Definition: C4PropList.h:92
int32_t Category
Definition: C4Def.h:119
C4Effect * pScenarioEffects
Definition: C4ScriptHost.h:165
C4ExtraScriptHost(C4String *parent_key_name=nullptr)
C4ScriptHost * ChildL
Definition: C4Aul.h:123
virtual bool LoadData(const char *, const char *, C4LangStringTable *)
virtual ~C4ScriptHost()
C4Value C4VFunction(C4AulFunc *pFn)
Definition: C4Value.h:250
virtual void SetPropertyByS(C4String *k, const C4Value &to)
Definition: C4PropList.cpp:929
void SetPropList(C4PropList *PropList)
Definition: C4Value.h:141
std::list< C4ScriptHost * > SourceScripts
Definition: C4ScriptHost.h:56
C4PropList * _getPropList() const
Definition: C4Value.h:129
C4Value Call(C4PropertyName k, C4AulParSet *pPars=0, bool fPassErrors=false)
Definition: C4PropList.h:112
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:59
C4LangStringTable * stringTable
Definition: C4ScriptHost.h:91
void Copy()
Definition: StdBuf.h:475
StdCopyStrBuf ScriptName
Definition: C4ScriptHost.h:57
C4AulScriptState State
Definition: C4ScriptHost.h:93
C4AulFunc * getFunction() const
Definition: C4Value.h:119
C4ScriptHost * Next
Definition: C4ScriptHost.h:77
C4ScriptHost * Prev
Definition: C4ScriptHost.h:77
C4ScriptHost * Child0
Definition: C4Aul.h:123
const int32_t C4D_Foreground
Definition: C4Def.h:55
StdStrBuf Script
Definition: C4ScriptHost.h:90
StdStrBuf GetDataString() const
Definition: C4PropList.cpp:253
std::vector< C4Value > ownedPropLists
Definition: C4ScriptHost.h:101