Line data Source code
1 : #ifndef CS_H_
2 : #define CS_H_
3 :
4 : /**
5 : * @file Internal CubeScript functionality
6 : *
7 : * low level cubescript functionality beyond script binding in command.h
8 : */
9 :
10 : enum
11 : {
12 : Max_Args = 25,
13 : Max_Results = 7,
14 : Max_CommandArgs = 12
15 : };
16 :
17 : enum CubeScriptCodes
18 : {
19 : Code_Start = 0, //0
20 : Code_Offset,
21 : Code_Null,
22 : Code_True,
23 : Code_False,
24 : Code_Not, //5
25 : Code_Pop,
26 : Code_Enter,
27 : Code_EnterResult,
28 : Code_Exit,
29 : Code_ResultArg, //10
30 : Code_Val,
31 : Code_ValI,
32 : Code_Dup,
33 : Code_Macro,
34 : Code_Bool, //15 (unused)
35 : Code_Block,
36 : Code_Empty,
37 : Code_Compile,
38 : Code_Cond,
39 : Code_Force, //20
40 : Code_Result,
41 : Code_Ident,
42 : Code_IdentU,
43 : Code_IdentArg,
44 : Code_Com, //25
45 : Code_ComD,
46 : Code_ComC,
47 : Code_ComV,
48 : Code_ConC,
49 : Code_ConCW, //30
50 : Code_ConCM,
51 : Code_Down, // (unused)
52 : Code_StrVar,
53 : Code_StrVarM,
54 : Code_StrVar1, //35
55 : Code_IntVar,
56 : Code_IntVar1,
57 : Code_IntVar2,
58 : Code_IntVar3,
59 : Code_FloatVar, //40
60 : Code_FloatVar1,
61 : Code_Lookup,
62 : Code_LookupU,
63 : Code_LookupArg,
64 : Code_LookupM, //45
65 : Code_LookupMU,
66 : Code_LookupMArg,
67 : Code_Alias,
68 : Code_AliasU,
69 : Code_AliasArg, //50
70 : Code_Call,
71 : Code_CallU,
72 : Code_CallArg,
73 : Code_Print,
74 : Code_Local, //55
75 : Code_Do,
76 : Code_DoArgs,
77 : Code_Jump,
78 : Code_JumpTrue,
79 : Code_JumpFalse,
80 : Code_JumpResultTrue, //60
81 : Code_JumpResultFalse,
82 :
83 : Code_OpMask = 0x3F,
84 : Code_Ret = 6,
85 : Code_RetMask = 0xC0,
86 :
87 : /* return type flags */
88 : Ret_Null = Value_Null<<Code_Ret,
89 : Ret_String = Value_String<<Code_Ret,
90 : Ret_Integer = Value_Integer<<Code_Ret,
91 : Ret_Float = Value_Float<<Code_Ret,
92 : };
93 :
94 : struct stringslice final
95 : {
96 : const char *str;
97 : int len;
98 4481 : stringslice() {}
99 1 : stringslice(const char *newstr, int newlen) : str(newstr), len(newlen) {}
100 0 : stringslice(const char *newstr, const char *newend) : str(newstr), len(static_cast<int>(newend-newstr)) {}
101 :
102 50 : const char *end() const
103 : {
104 50 : return &str[len];
105 : }
106 : };
107 :
108 0 : inline char *copystring(char *d, const stringslice &s, size_t len)
109 : {
110 0 : size_t slen = min(size_t(s.len), len-1);
111 0 : std::memcpy(d, s.str, slen);
112 0 : d[slen] = 0;
113 0 : return d;
114 : }
115 :
116 : template<size_t N>
117 0 : inline char *copystring(char (&d)[N], const stringslice &s)
118 : {
119 0 : return copystring(d, s, N);
120 : }
121 :
122 : // not all platforms (windows) can parse hexadecimal integers via strtod
123 276 : inline float parsefloat(const char *s)
124 : {
125 : char *end;
126 276 : double val = std::strtod(s, &end);
127 : return val
128 44 : || end==s
129 320 : || (*end!='x' && *end!='X') ? static_cast<float>(val) : static_cast<float>(parseint(s));
130 : }
131 :
132 2 : inline double parsenumber(const char *s)
133 : {
134 : char *end;
135 2 : double val = std::strtod(s, &end);
136 : return val
137 1 : || end==s
138 3 : || (*end!='x' && *end!='X') ? static_cast<double>(val) : static_cast<double>(parseint(s));
139 : }
140 :
141 68 : inline void intformat(char *buf, int v, int len = 20)
142 : {
143 68 : nformatstring(buf, len, "%d", v);
144 68 : }
145 :
146 116 : inline void floatformat(char *buf, float v, int len = 20)
147 : {
148 116 : nformatstring(buf, len, v==static_cast<int>(v) ? "%.1f" : "%.7g", v);
149 116 : }
150 :
151 : extern const char *intstr(int v);
152 :
153 354 : inline const char *getstr(const identval &v, int type)
154 : {
155 354 : switch(type)
156 : {
157 247 : case Value_String:
158 : case Value_Macro:
159 : case Value_CString:
160 : {
161 247 : return v.s;
162 : }
163 60 : case Value_Integer:
164 : {
165 60 : return intstr(v.i);
166 : }
167 0 : case Value_Float:
168 : {
169 0 : return floatstr(v.f);
170 : }
171 47 : default:
172 : {
173 47 : return "";
174 : }
175 : }
176 : }
177 :
178 247 : inline const char *tagval::getstr() const
179 : {
180 247 : return ::getstr(*this, type);
181 : }
182 :
183 107 : inline const char *ident::getstr() const
184 : {
185 107 : return ::getstr(alias.val, valtype);
186 : }
187 :
188 0 : inline void getval(const identval &v, int type, tagval &r)
189 : {
190 0 : switch(type)
191 : {
192 0 : case Value_String:
193 : case Value_Macro:
194 : case Value_CString:
195 : {
196 0 : r.setstr(newstring(v.s));
197 0 : break;
198 : }
199 0 : case Value_Integer:
200 : {
201 0 : r.setint(v.i);
202 0 : break;
203 : }
204 0 : case Value_Float:
205 : {
206 0 : r.setfloat(v.f);
207 0 : break;
208 : }
209 0 : default:
210 : {
211 0 : r.setnull();
212 0 : break;
213 : }
214 : }
215 0 : }
216 :
217 0 : inline void tagval::getval(tagval &r) const
218 : {
219 0 : ::getval(*this, type, r);
220 0 : }
221 :
222 : struct NullVal final : tagval
223 : {
224 29 : NullVal()
225 29 : {
226 29 : setnull();
227 29 : }
228 : };
229 :
230 : struct IdentLink final
231 : {
232 : ident *id;
233 : IdentLink *next;
234 : int usedargs;
235 : identstack *argstack;
236 : };
237 :
238 : extern const char *sourcefile,
239 : *sourcestr;
240 :
241 : extern std::array<std::vector<char>, 4> strbuf;
242 : extern int stridx;
243 :
244 : extern tagval *commandret;
245 : extern void executeret(const uint *code, tagval &result = *commandret);
246 :
247 : /**
248 : * @brief Executes a given string, returning a tagval by reference parameter
249 : *
250 : * @param p a string to execute
251 : * @param result tagval containing result metadata
252 : */
253 : extern void executeret(const char *p, tagval &result = *commandret);
254 :
255 : /**
256 : * @brief Executes a given ident, returning a tagval by reference parameter
257 : *
258 : * @param id the ident to execute
259 : * @param args an array of arguments
260 : * @param numargs size of args array
261 : * @param lookup whether to lookup (dereference) args (?)
262 : * @param result tagval containing result metadata
263 : */
264 : extern void executeret(ident *id, tagval *args, int numargs, bool lookup = false, tagval &result = *commandret);
265 :
266 : extern void poparg(ident &id);
267 : extern void pusharg(ident &id, const tagval &v, identstack &stack);
268 : extern bool getbool(const tagval &v);
269 : extern void cleancode(ident &id);
270 : extern char *conc(const tagval *v, int n, bool space);
271 : extern char *conc(const tagval *v, int n, bool space, const char *prefix);
272 : extern void freearg(tagval &v);
273 : extern int unescapestring(char *dst, const char *src, const char *end);
274 : extern const char *parsestring(const char *p);
275 : extern void setarg(ident &id, tagval &v);
276 : extern void setalias(ident &id, tagval &v);
277 : extern void undoarg(ident &id, identstack &stack);
278 : extern void redoarg(ident &id, const identstack &stack);
279 : extern const char *parseword(const char *p);
280 :
281 : extern bool validateblock(const char *s);
282 : extern std::unordered_map<std::string, ident> idents;
283 :
284 : extern void setvarchecked(ident *id, int val);
285 : extern void setfvarchecked(ident *id, float val);
286 : extern void setsvarchecked(ident *id, const char *val);
287 :
288 : extern void printvar(const ident *id);
289 : extern void printvar(const ident *id, int i);
290 :
291 : extern void clearoverrides();
292 :
293 : /**
294 : * @brief Drops sleep commands, optionally only dropping sleeps with override bit set.
295 : *
296 : * If clearoverrides is `false`, drops every element in the sleepcmds vector.
297 : *
298 : * If clearoverrides is `true`, keeps elements where Idf_Overridden bit is not set
299 : * and discards elements where Idf_Overridden bit is set.
300 : *
301 : * Idf_Overridden is an enum element in command.h.
302 : *
303 : * @param clearoverrides whether to drop elements with Idf_Overridden bit set.
304 : */
305 : extern void clearsleep(bool clearoverrides = true);
306 :
307 : extern char *executestr(ident *id, tagval *args, int numargs, bool lookup = false);
308 : extern uint *compilecode(const char *p);
309 : extern void freecode(uint *p);
310 : extern int execute(ident *id, tagval *args, int numargs, bool lookup = false);
311 : extern bool executebool(ident *id, tagval *args, int numargs, bool lookup = false);
312 : extern void alias(const char *name, const char *action);
313 :
314 : /**
315 : * @brief Converts a list of delimited strings into a vector of elements.
316 : *
317 : * List elements in the input string are added to the vector of strings passed
318 : * as elems.
319 : *
320 : * The list is parsed according to the CubeScript list formatting.
321 : * Tokens in the list are delimited by spaces, unless those tokens are themselves
322 : * delimited by [] "" or () characters.
323 : *
324 : * Existing elements in the elems vector will not be modified. The limit parameter
325 : * sets the maximum number of elements in the vector, regardless of whether they
326 : * were added by this function.
327 : *
328 : * Elements added to this vector are all heap-allocated raw character strings and
329 : * therefore must be delete[]'d after they are no longer being used
330 : *
331 : * @param s the list to explode
332 : * @param elems the vector to fill with elements
333 : * @param limit maximum size of the elems vector allowed
334 : */
335 : extern void explodelist(const char *s, std::vector<char *> &elems, int limit = -1);
336 : extern void explodelist(const char *s, std::vector<std::string> &elems, int limit = -1);
337 :
338 : extern void result(tagval &v);
339 : extern const char *numberstr(double v);
340 : extern float clampfvar(std::string name, float val, float minval, float maxval);
341 :
342 : #endif
|