diff options
Diffstat (limited to 'src/libraries/Runnr.c')
-rw-r--r-- | src/libraries/Runnr.c | 318 |
1 files changed, 318 insertions, 0 deletions
diff --git a/src/libraries/Runnr.c b/src/libraries/Runnr.c new file mode 100644 index 0000000..a24e7f5 --- /dev/null +++ b/src/libraries/Runnr.c | |||
@@ -0,0 +1,318 @@ | |||
1 | /* Runnr - a library that deals with running Lua scripts. | ||
2 | |||
3 | */ | ||
4 | |||
5 | |||
6 | #include "Runnr.h" | ||
7 | |||
8 | |||
9 | void dumpStack(lua_State *L, int i) | ||
10 | { | ||
11 | int type = lua_type(L, i); | ||
12 | |||
13 | switch (type) | ||
14 | { | ||
15 | case LUA_TNONE : printf("Stack %d is empty\n", i); break; | ||
16 | case LUA_TNIL : printf("Stack %d is a nil\n", i); break; | ||
17 | case LUA_TBOOLEAN : printf("Stack %d is a boolean - %d\n", i, lua_toboolean(L, i)); break; | ||
18 | case LUA_TNUMBER : printf("Stack %d is a number\n - %f", i, lua_tonumber(L, i)); break; | ||
19 | case LUA_TSTRING : printf("Stack %d is a string - %s\n", i, lua_tostring(L, i)); break; | ||
20 | case LUA_TFUNCTION : printf("Stack %d is a function\n", i); break; | ||
21 | case LUA_TTHREAD : printf("Stack %d is a thread\n", i); break; | ||
22 | case LUA_TTABLE : | ||
23 | { | ||
24 | int j; | ||
25 | |||
26 | printf("Stack %d is a table", i); | ||
27 | lua_getfield(L, i, "_NAME"); | ||
28 | j = lua_gettop(L); | ||
29 | if (lua_isstring(L, j)) | ||
30 | printf(" - %s", lua_tostring(L, j)); | ||
31 | lua_pop(L, 1); | ||
32 | printf("\n"); | ||
33 | break; | ||
34 | } | ||
35 | case LUA_TUSERDATA : printf("Stack %d is a userdata\n", i); break; | ||
36 | case LUA_TLIGHTUSERDATA : printf("Stack %d is a light userdata\n", i); break; | ||
37 | default : printf("Stack %d is unknown\n", i); break; | ||
38 | } | ||
39 | } | ||
40 | |||
41 | |||
42 | // These are what the various symbols are for each type - | ||
43 | // int % | ||
44 | // num # | ||
45 | // str $ | ||
46 | // bool ! | ||
47 | // C func & | ||
48 | // table.field @ Expects an integer and a string. | ||
49 | // nil ~ | ||
50 | // table {} Starts and stops filling up a new table. | ||
51 | // ( Just syntax sugar for call. | ||
52 | // call ) Expects an integer, the number of results left after the call. | ||
53 | // FIXME: Still to do, if we ever use them - | ||
54 | // stack = Get a value from the stack, expects a stack index. | ||
55 | // userdata + | ||
56 | // lightuserdata * | ||
57 | // thread ^ | ||
58 | |||
59 | static char *_push_name(lua_State *L, char *q, int *idx) // Stack usage [-0, +1, e or m] | ||
60 | { | ||
61 | char *p = q; | ||
62 | char temp = '\0'; | ||
63 | |||
64 | // A simplistic scan through an identifier, it's wrong, but it's quick, | ||
65 | // and we don't mind that it's wrong, coz this is only internal. | ||
66 | while (isalnum((int)*q)) | ||
67 | q++; | ||
68 | temp = *q; | ||
69 | *q = '\0'; | ||
70 | if (*idx > 0) | ||
71 | lua_getfield(L, *idx, p); // Stack usage [-0, +1, e] | ||
72 | else | ||
73 | { | ||
74 | if (p != q) | ||
75 | lua_pushstring(L, p); // Stack usage [-0, +1, m] | ||
76 | else | ||
77 | { | ||
78 | lua_pushnumber(L, (lua_Number) (0 - (*idx))); | ||
79 | (*idx)--; | ||
80 | } | ||
81 | } | ||
82 | *q = temp; | ||
83 | |||
84 | return q; | ||
85 | } | ||
86 | |||
87 | int pull_lua(lua_State *L, int i, char *params, ...) // Stack usage - | ||
88 | // if i is a table | ||
89 | // [-n, +n, e] | ||
90 | // else | ||
91 | // [-0, +0, -] | ||
92 | { | ||
93 | va_list vl; | ||
94 | char *f = strdup(params); | ||
95 | char *p = f; | ||
96 | int n = 0, j = i, count = 0; | ||
97 | Eina_Bool table = EINA_FALSE; | ||
98 | |||
99 | if (!f) return -1; | ||
100 | va_start(vl, params); | ||
101 | |||
102 | if (lua_istable(L, i)) // Stack usage [-0, +0, -] | ||
103 | { | ||
104 | j = -1; | ||
105 | table = EINA_TRUE; | ||
106 | } | ||
107 | |||
108 | while (*p) | ||
109 | { | ||
110 | char *q; | ||
111 | Eina_Bool get = EINA_TRUE; | ||
112 | |||
113 | while (isspace((int)*p)) | ||
114 | p++; | ||
115 | q = p + 1; | ||
116 | switch (*p) | ||
117 | { | ||
118 | case '%': | ||
119 | { | ||
120 | if (table) q = _push_name(L, q, &i); // Stack usage [-0, +1, e] | ||
121 | if (lua_isnumber(L, j)) // Stack usage [-0, +0, -] | ||
122 | { | ||
123 | int *v = va_arg(vl, int *); | ||
124 | *v = lua_tointeger(L, j); // Stack usage [-0, +0, -] | ||
125 | n++; | ||
126 | } | ||
127 | break; | ||
128 | } | ||
129 | case '#': | ||
130 | { | ||
131 | if (table) q = _push_name(L, q, &i); // Stack usage [-0, +1, e] | ||
132 | if (lua_isnumber(L, j)) // Stack usage [-0, +0, -] | ||
133 | { | ||
134 | double *v = va_arg(vl, double *); | ||
135 | *v = lua_tonumber(L, j); // Stack usage [-0, +0, -] | ||
136 | n++; | ||
137 | } | ||
138 | break; | ||
139 | } | ||
140 | case '$': | ||
141 | { | ||
142 | if (table) q = _push_name(L, q, &i); // Stack usage [-0, +1, e] | ||
143 | if (lua_isstring(L, j)) // Stack usage [-0, +0, -] | ||
144 | { | ||
145 | char **v = va_arg(vl, char **); | ||
146 | size_t len; | ||
147 | char *temp = (char *) lua_tolstring(L, j, &len); // Stack usage [-0, +0, m] | ||
148 | |||
149 | len++; // Cater for the null at the end. | ||
150 | *v = malloc(len); | ||
151 | if (*v) | ||
152 | { | ||
153 | memcpy(*v, temp, len); | ||
154 | n++; | ||
155 | } | ||
156 | } | ||
157 | break; | ||
158 | } | ||
159 | case '!': | ||
160 | { | ||
161 | if (table) q = _push_name(L, q, &i); // Stack usage [-0, +1, e] | ||
162 | if (lua_isboolean(L, j)) // Stack usage [-0, +0, -] | ||
163 | { | ||
164 | int *v = va_arg(vl, int *); | ||
165 | *v = lua_toboolean(L, j); // Stack usage [-0, +0, -] | ||
166 | n++; | ||
167 | } | ||
168 | break; | ||
169 | } | ||
170 | default: | ||
171 | { | ||
172 | get = EINA_FALSE; | ||
173 | break; | ||
174 | } | ||
175 | } | ||
176 | |||
177 | if (get) | ||
178 | { | ||
179 | if (table) | ||
180 | { | ||
181 | // If this is a table, then we pushed a value on the stack, pop it off. | ||
182 | lua_pop(L, 1); // Stack usage [-n, +0, -] | ||
183 | } | ||
184 | else | ||
185 | j++; | ||
186 | count++; | ||
187 | } | ||
188 | p = q; | ||
189 | } | ||
190 | |||
191 | va_end(vl); | ||
192 | free(f); | ||
193 | if (count > n) | ||
194 | n = 0; | ||
195 | else if (table) | ||
196 | n = 1; | ||
197 | return n; | ||
198 | } | ||
199 | |||
200 | int push_lua(lua_State *L, char *params, ...) // Stack usage [-0, +n, em] | ||
201 | { | ||
202 | va_list vl; | ||
203 | char *f = strdup(params); | ||
204 | char *p = f; | ||
205 | int n = 0, table = 0, i = -1; | ||
206 | |||
207 | if (!f) return -1; | ||
208 | |||
209 | va_start(vl, params); | ||
210 | |||
211 | while (*p) | ||
212 | { | ||
213 | char *q; | ||
214 | Eina_Bool set = EINA_TRUE; | ||
215 | |||
216 | while (isspace((int)*p)) | ||
217 | p++; | ||
218 | q = p + 1; | ||
219 | switch (*p) | ||
220 | { | ||
221 | case '%': | ||
222 | { | ||
223 | if (table) q = _push_name(L, q, &i); // Stack usage [-0, +1, m] | ||
224 | lua_pushinteger(L, va_arg(vl, int)); // Stack usage [-0, +1, -] | ||
225 | break; | ||
226 | } | ||
227 | case '#': | ||
228 | { | ||
229 | if (table) q = _push_name(L, q, &i); // Stack usage [-0, +1, m] | ||
230 | lua_pushnumber(L, va_arg(vl, double)); // Stack usage [-0, +1, -] | ||
231 | break; | ||
232 | } | ||
233 | case '$': | ||
234 | { | ||
235 | if (table) q = _push_name(L, q, &i); // Stack usage [-0, +1, m] | ||
236 | lua_pushstring(L, va_arg(vl, char *)); // Stack usage [-0, +1, m] | ||
237 | break; | ||
238 | } | ||
239 | case '!': | ||
240 | { | ||
241 | if (table) q = _push_name(L, q, &i); // Stack usage [-0, +1, m] | ||
242 | lua_pushboolean(L, va_arg(vl, int)); // Stack usage [-0, +1, -] | ||
243 | break; | ||
244 | } | ||
245 | case '=': | ||
246 | { | ||
247 | if (table) q = _push_name(L, q, &i); // Stack usage [-0, +1, m] | ||
248 | lua_pushvalue(L, va_arg(vl, int)); // Stack usage [-0, +1, -] | ||
249 | break; | ||
250 | } | ||
251 | case '@': | ||
252 | { | ||
253 | int tabl = va_arg(vl, int); | ||
254 | char *field = va_arg(vl, char *); | ||
255 | |||
256 | if (table) q = _push_name(L, q, &i); // Stack usage [-0, +1, m] | ||
257 | lua_getfield(L, tabl, field); // Stack usage [-0, +1, e] | ||
258 | break; | ||
259 | } | ||
260 | case '&': | ||
261 | { | ||
262 | if (table) q = _push_name(L, q, &i); // Stack usage [-0, +1, m] | ||
263 | lua_pushcfunction(L, va_arg(vl, void *)); // Stack usage [-0, +1, m] | ||
264 | break; | ||
265 | } | ||
266 | case '~': | ||
267 | { | ||
268 | if (table) q = _push_name(L, q, &i); // Stack usage [-0, +1, m] | ||
269 | lua_pushnil(L); // Stack usage [-0, +1, -] | ||
270 | break; | ||
271 | } | ||
272 | case '(': // Just syntax sugar. | ||
273 | { | ||
274 | set = EINA_FALSE; | ||
275 | break; | ||
276 | } | ||
277 | case ')': | ||
278 | { | ||
279 | lua_call(L, n - 1, va_arg(vl, int)); | ||
280 | n = 0; | ||
281 | set = EINA_FALSE; | ||
282 | break; | ||
283 | } | ||
284 | case '{': | ||
285 | { | ||
286 | lua_newtable(L); | ||
287 | table++; | ||
288 | n++; | ||
289 | set = EINA_FALSE; | ||
290 | break; | ||
291 | } | ||
292 | case '}': | ||
293 | { | ||
294 | table--; | ||
295 | set = EINA_FALSE; | ||
296 | break; | ||
297 | } | ||
298 | default: | ||
299 | { | ||
300 | set = EINA_FALSE; | ||
301 | break; | ||
302 | } | ||
303 | } | ||
304 | |||
305 | if (set) | ||
306 | { | ||
307 | if (table > 0) | ||
308 | lua_settable(L, -3); // Stack usage [-2, +0, e] | ||
309 | else | ||
310 | n++; | ||
311 | } | ||
312 | p = q; | ||
313 | } | ||
314 | |||
315 | va_end(vl); | ||
316 | free(f); | ||
317 | return n; | ||
318 | } | ||