aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/Runnr.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/Runnr.c')
-rw-r--r--libraries/Runnr.c318
1 files changed, 318 insertions, 0 deletions
diff --git a/libraries/Runnr.c b/libraries/Runnr.c
new file mode 100644
index 0000000..a24e7f5
--- /dev/null
+++ b/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
9void 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
59static 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
87int 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
200int 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}