1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
5  * Copyright (c) 2009-2016, The OpenClonk Team and contributors
6  *
7  * Distributed under the terms of the ISC license; see accompanying file
8  * "COPYING" for details.
9  *
10  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
11  * See accompanying file "TRADEMARK" for details.
12  *
13  * To redistribute this file separately, substitute the full license texts
14  * for the above references.
15  */
16 
17 #ifndef INC_C4Aul
18 #define INC_C4Aul
19 
20 #include "object/C4Id.h"
21 #include "script/C4StringTable.h"
22 #include "script/C4Value.h"
23 #include "script/C4ValueMap.h"
24 
25 // consts
26 #define C4AUL_MAX_Identifier  100 // max length of function identifiers
27 
28 // warning flags
29 enum class C4AulWarningId
30 {
31 #define DIAG(id, text, enabled) id,
32 #include "C4AulWarnings.h"
33 #undef DIAG
34 	WarningCount
35 };
36 
37 extern const char *C4AulWarningIDs[];
38 extern const char *C4AulWarningMessages[];
39 
40 // generic C4Aul error class
41 class C4AulError : public std::exception
42 {
43 protected:
44 	StdCopyStrBuf sMessage;
45 
46 public:
47 	~C4AulError() override = default; // destructor
48 	const char *what() const noexcept override;
49 };
50 
51 // parse error
52 class C4AulParseError : public C4AulError
53 {
54 	C4AulParseError() = default;
55 public:
56 	C4AulParseError(C4ScriptHost *pScript, const char *pMsg); // constructor
57 	C4AulParseError(class C4AulParse * state, const char *pMsg); // constructor
58 	C4AulParseError(C4AulScriptFunc * Fn, const char *SPos, const char *pMsg);
59 };
60 
61 // execution error
62 class C4AulExecError : public C4AulError
63 {
64 public:
65 	C4AulExecError(const char *szError);
66 };
67 
68 class C4AulFuncMap
69 {
70 public:
71 	C4AulFuncMap();
72 	~C4AulFuncMap();
73 	C4AulFunc * GetFirstFunc(const char * Name);
74 	C4AulFunc * GetNextSNFunc(const C4AulFunc * After);
75 private:
76 	enum { HashSize = 1025 };
77 	C4AulFunc * Funcs[HashSize];
78 	int FuncCnt{0};
79 	static unsigned int Hash(const char * Name);
80 protected:
81 	void Add(C4AulFunc * func);
82 	void Remove(C4AulFunc * func);
83 	friend class C4AulFunc;
84 	friend class C4ScriptHost;
85 };
86 
87 // user text file to which scripts can write using FileWrite().
88 // actually just writes to an internal buffer
89 class C4AulUserFile
90 {
91 	StdCopyStrBuf sContents;
92 	int32_t handle;
93 
94 public:
C4AulUserFile(int32_t handle)95 	C4AulUserFile(int32_t handle) : handle(handle) {}
Write(const char * data,size_t data_length)96 	void Write(const char *data, size_t data_length) { sContents.Append(data, data_length); }
97 
GetFileContents()98 	const char *GetFileContents() { return sContents.getData(); }
GrabFileContents()99 	StdStrBuf GrabFileContents() { StdStrBuf r; r.Take(sContents); return r; }
GetFileLength()100 	size_t GetFileLength() { return sContents.getLength(); }
GetHandle()101 	int32_t GetHandle() const { return handle; }
102 };
103 
104 class C4AulErrorHandler
105 {
106 public:
107 	virtual ~C4AulErrorHandler();
108 	virtual void OnError(const char *msg) = 0;
109 	virtual void OnWarning(const char *msg) = 0;
110 };
111 
112 // holds all C4AulScripts
113 class C4AulScriptEngine: public C4PropListStaticMember
114 {
115 protected:
116 	C4AulFuncMap FuncLookUp;
GetFirstFunc(const char * Name)117 	C4AulFunc * GetFirstFunc(const char * Name)
118 	{ return FuncLookUp.GetFirstFunc(Name); }
GetNextSNFunc(const C4AulFunc * After)119 	C4AulFunc * GetNextSNFunc(const C4AulFunc * After)
120 	{ return FuncLookUp.GetNextSNFunc(After); }
121 	C4ScriptHost *Child0, *ChildL; // tree structure
122 
123 	// all open user files
124 	// user files aren't saved - they are just open temporary e.g. during game saving
125 	std::list<C4AulUserFile> UserFiles;
126 	std::vector<C4Value> OwnedPropLists;
127 
128 	C4AulErrorHandler *ErrorHandler;
129 
130 public:
131 	int warnCnt{0}, errCnt{0}; // number of warnings/errors
132 	int lineCnt{0}; // line count parsed
133 
134 	C4ValueMapNames GlobalNamedNames;
135 	C4ValueMapData GlobalNamed;
136 
137 	// global constants (such as "static const C4D_Structure = 2;")
138 	// cannot share var lists, because it's so closely tied to the data lists
139 	// constants are used by the Parser only, anyway, so it's not
140 	// necessary to pollute the global var list here
141 	C4ValueMapNames GlobalConstNames;
142 	C4ValueMapData GlobalConsts;
143 
144 	C4Effect * pGlobalEffects = nullptr;
145 
146 	C4AulScriptEngine(); // constructor
147 	~C4AulScriptEngine() override; // destructor
148 	void Clear(); // clear data
149 	void Link(C4DefList *rDefs); // link and parse all scripts
150 	void ReLink(C4DefList *rDefs); // unlink, link and parse all scripts
GetPropList()151 	C4PropListStatic * GetPropList() { return this; }
152 	bool ReloadScript(const char *szScript, const char *szLanguage); // search script and reload, if found
153 
154 	// For the list of functions in the PropertyDlg
155 	std::list<const char*> GetFunctionNames(C4PropList *);
156 
157 	void RegisterGlobalConstant(const char *szName, const C4Value &rValue); // creates a new constants or overwrites an old one
158 	bool GetGlobalConstant(const char *szName, C4Value *pTargetValue); // check if a constant exists; assign value to pTargetValue if not nullptr
159 
160 	void Denumerate(C4ValueNumbers *) override;
161 	void UnLink(); // called when a script is being reloaded (clears string table)
162 
163 	// Compile scenario script data (without strings and constants)
164 	void CompileFunc(StdCompiler *pComp, bool fScenarioSection, C4ValueNumbers * numbers);
165 
166 	// Handle user files
167 	int32_t CreateUserFile(); // create new file and return handle
168 	void CloseUserFile(int32_t handle); // close user file given by handle
169 	C4AulUserFile *GetUserFile(int32_t handle); // get user file given by handle
170 
171 	void RegisterErrorHandler(C4AulErrorHandler *handler);
172 	void UnregisterErrorHandler(C4AulErrorHandler *handler);
GetErrorHandler()173 	C4AulErrorHandler *GetErrorHandler() const
174 	{
175 		return ErrorHandler;
176 	}
177 
178 	friend class C4AulFunc;
179 	friend class C4AulProfiler;
180 	friend class C4ScriptHost;
181 	friend class C4AulParse;
182 	friend class C4AulCompiler;
183 	friend class C4AulDebug;
184 };
185 
186 extern C4AulScriptEngine ScriptEngine;
187 void InitCoreFunctionMap(C4AulScriptEngine *pEngine);
188 
189 #endif
190