understand "warning" directive in parser
[lqt.git] / common / lqt_common.cpp
blobc0cdd872d3048bb93b83fa0e92db3b9bfe9cefdb
1 /*
2 * Copyright (c) 2007-2008 Mauro Iazzi
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use,
8 * copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following
11 * conditions:
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 * OTHER DEALINGS IN THE SOFTWARE.
27 #include "lqt_common.hpp"
28 #include <cstring>
30 #include <QDebug>
32 static void lqtL_getenumtable (lua_State *L) {
33 lua_getfield(L, LUA_REGISTRYINDEX, LQT_ENUMS);
34 if (lua_isnil(L, -1)) {
35 lua_pop(L, 1);
36 lua_newtable(L);
37 lua_pushvalue(L, -1);
38 lua_setfield(L, LUA_REGISTRYINDEX, LQT_ENUMS);
42 static void lqtL_getpointertable (lua_State *L) {
43 lua_getfield(L, LUA_REGISTRYINDEX, LQT_POINTERS); // (1) get storage for pointers
44 if (lua_isnil(L, -1)) { // (1) if there is not
45 lua_pop(L, 1); // (0) pop the nil value
46 lua_newtable(L); // (1) create a new one
47 lua_newtable(L); // (2) create an empty metatable
48 lua_pushstring(L, "v"); // (3) push the mode value: weak values are enough
49 lua_setfield(L, -2, "__mode"); // (2) set the __mode field
50 lua_setmetatable(L, -2); // (1) set it as the metatable
51 lua_pushvalue(L, -1); // (2) duplicate the new pointer table
52 lua_setfield(L, LUA_REGISTRYINDEX, LQT_POINTERS); // (1) put one copy as storage
56 static void lqtL_getreftable (lua_State *L) {
57 lua_getfield(L, LUA_REGISTRYINDEX, LQT_REFS); // (1) get storage for pointers
58 if (lua_isnil(L, -1)) { // (1) if there is not
59 lua_pop(L, 1); // (0) pop the nil value
60 lua_newtable(L); // (1) create a new one
61 lua_newtable(L); // (2) create an empty metatable
62 lua_pushstring(L, "kv"); // (3) push the mode value: weak values are enough
63 lua_setfield(L, -2, "__mode"); // (2) set the __mode field
64 lua_setmetatable(L, -2); // (1) set it as the metatable
65 lua_pushvalue(L, -1); // (2) duplicate the new pointer table
66 lua_setfield(L, LUA_REGISTRYINDEX, LQT_REFS); // (1) put one copy as storage
70 void * lqtL_getref (lua_State *L, size_t sz) {
71 void *ret = NULL;
72 lqtL_getreftable(L); // (1)
73 ret = lua_newuserdata(L, sz); // (2)
74 lua_rawseti(L, -2, 1+lua_objlen(L, -2)); // (1)
75 return ret;
78 bool * lqtL_toboolref (lua_State *L, int index) {
79 bool tmp = lua_toboolean(L, index);
80 bool *ret = (bool*)lqtL_getref(L, sizeof(bool));
81 *ret = tmp;
82 return ret;
85 int * lqtL_tointref (lua_State *L, int index) {
86 int tmp = lua_tointeger(L, index);
87 int *ret = (int*)lqtL_getref(L, sizeof(int));
88 *ret = tmp;
89 return ret;
92 void lqtL_pusharguments (lua_State *L, char **argv) {
93 int i = 0;
94 lua_newtable(L);
95 for (i=0;*argv /* fix the maximum number? */;argv++,i++) {
96 lua_pushstring(L, *argv);
97 lua_rawseti(L, -2, i+1);
99 return;
102 char ** lqtL_toarguments (lua_State *L, int index) {
103 char ** ret = (char**)lqtL_getref(L, sizeof(char*)*(lua_objlen(L, index)+1));
104 const char *str = NULL;
105 size_t strlen = 0;
106 int i = 0;
107 for (i=0;;i++) {
108 lua_rawgeti(L, index, i+1);
109 if (!lua_isstring(L, -1)) {
110 str = NULL; strlen = 0;
111 ret[i] = NULL;
112 lua_pop(L, 1);
113 break;
114 } else {
115 str = lua_tolstring(L, -1, &strlen);
116 ret[i] = (char*)lqtL_getref(L, sizeof(char)*(strlen+1));
117 strncpy(ret[i], str, strlen+1);
118 lua_pop(L, 1);
121 return ret;
124 static int lqtL_createenum (lua_State *L, lqt_Enum e[], const char *n) {
125 lqt_Enum *l = e;
126 lqtL_getenumtable(L); // (1)
127 lua_newtable(L); // (2)
128 lua_pushvalue(L, -1); // (3)
129 lua_setfield(L, -3, n); // (2)
130 while ( (l->name!=0) ) { // (2)
131 lua_pushstring(L, l->name); // (3)
132 lua_pushinteger(L, l->value); // (4)
133 lua_settable(L, -3); // (2)
134 lua_pushinteger(L, l->value); // (3)
135 lua_pushstring(L, l->name); // (4)
136 lua_settable(L, -3); // (2)
137 l++; // (2)
139 lua_pop(L, 2); // (0)
140 return 0;
143 int lqtL_createenumlist (lua_State *L, lqt_Enumlist list[]) {
144 while (list->enums!=0 && list->name!=0) {
145 lqtL_createenum(L, list->enums, list->name); // (0)
146 list++;
148 return 0;
151 static int lqtL_gcfunc (lua_State *L) {
152 if (!lua_isuserdata(L, 1) && lua_islightuserdata(L, 1)) return 0;
153 lua_getfenv(L, 1); // (1)
154 if (!lua_istable(L, -1)) {
155 lua_pop(L, 1); // (0)
156 return 0;
158 lua_getfield(L, -1, "__gc"); // (2)
159 lua_remove(L, -2); // (1)
160 if (!lua_isfunction(L, -1)) {
161 lua_pop(L, 1); // (0)
162 return 0;
164 lua_pushvalue(L, 1); // (2)
165 if (lua_pcall(L, 1, 0, 0)) { // (-2;+1/+0)
166 // (1)
167 return lua_error(L);
169 return 0; // (+0)
172 static int lqtL_newindexfunc (lua_State *L) {
173 lua_settop(L, 3); // (=3)
174 if (!lua_isuserdata(L, 1) && lua_islightuserdata(L, 1)) return 0;
175 lua_getfenv(L, 1); // (+1)
176 if (!lua_istable(L, -1)) {
177 lua_pop(L, 1); // (+0)
178 return 0;
180 lua_remove(L, 1); // (+0)
181 lua_insert(L, 1); // (+0)
182 lua_rawset(L, 1); // (-2)
183 return 0;
185 static int lqtL_indexfunc (lua_State *L) {
186 int i = 1;
187 if (lua_isuserdata(L, 1) && !lua_islightuserdata(L, 1)) {
188 lua_getfenv(L, 1); // (1)
189 lua_pushvalue(L, 2); // (2)
190 lua_gettable(L, -2); // (2)
191 if (!lua_isnil(L, -1)) {
192 lua_remove(L, -2);
193 return 1;
195 lua_pop(L, 2); // (0)
197 lua_pushnil(L); // (+1)
198 while (!lua_isnone(L, lua_upvalueindex(i))) { // (+1)
199 lua_pop(L, 1); // (+0)
200 lua_pushvalue(L, 2); // (+1)
201 if (i==1) {
202 lua_rawget(L, lua_upvalueindex(i)); // (+1)
203 } else {
204 lua_gettable(L, lua_upvalueindex(i)); // (+1)
206 if (!lua_isnil(L, -1)) break;
207 i++;
209 return 1; // (+1)
212 static int lqtL_pushindexfunc (lua_State *L, const char *name, lqt_Base *bases) {
213 int upnum = 1;
214 luaL_newmetatable(L, name); // (1)
215 while (bases->basename!=NULL) {
216 luaL_newmetatable(L, bases->basename); // (upnum)
217 upnum++;
218 bases++;
220 lua_pushcclosure(L, lqtL_indexfunc, upnum); // (1)
221 return 1;
224 static int lqtL_ctor_helper(lua_State*L) {
225 lua_getfield(L, 1, "new");
226 lua_replace(L, 1);
227 lua_call(L, lua_gettop(L)-1, LUA_MULTRET);
228 return lua_gettop(L);
231 static int lqtL_local_ctor(lua_State*L) {
232 lua_pushvalue(L, lua_upvalueindex(1)); // (+1)
233 lua_getfield(L, -1, "new"); // (+2)
234 lua_insert(L, 1); // (+2)
235 lua_pop(L, 1); // (+1)
236 lua_call(L, lua_gettop(L)-1, LUA_MULTRET); // (X)
237 lua_getfield(L, 1, "delete"); // (X+1)
238 lua_setfield(L, 1, "__gc"); // (X)
239 return lua_gettop(L);
242 int lqtL_createclass (lua_State *L, const char *name, luaL_Reg *mt, lqt_Base *bases) {
243 int len = 0;
244 char *new_name = NULL;
245 lqt_Base *bi = bases;
246 luaL_newmetatable(L, name); // (1)
247 luaL_register(L, NULL, mt); // (1)
248 // setup offsets
249 lua_pushstring(L, name); // (2) FIXME: remove
250 lua_pushinteger(L, 0); // (3) FIXME: remove
251 lua_settable(L, -3); // (1) FIXME: remove
252 while (bi->basename!=NULL) {
253 lua_pushstring(L, bi->basename); // (2) FIXME: remove
254 lua_pushinteger(L, bi->offset); // (3) FIXME: remove
255 lua_settable(L, -3); // (1) FIXME: remove
256 bi++;
258 // set metafunctions
259 lqtL_pushindexfunc(L, name, bases); // (2)
260 lua_setfield(L, -2, "__index"); // (1)
261 lua_pushcfunction(L, lqtL_newindexfunc); // (2)
262 lua_setfield(L, -2, "__newindex"); // (1)
263 lua_pushcfunction(L, lqtL_gcfunc); // (2)
264 lua_setfield(L, -2, "__gc"); // (1)
266 // set it as its own metatable
267 lua_pushvalue(L, -1); // (2)
268 lua_setmetatable(L, -2); // (1)
269 lua_pop(L, 1); // (0)
270 len = strlen(name);
271 new_name = (char*)malloc(len*sizeof(char));
272 strncpy(new_name, name, len);
273 new_name[len-1] = '\0';
274 luaL_register(L, new_name, mt); // (1)
275 free(new_name);
276 new_name = NULL;
277 lua_newtable(L); // (2)
278 lua_pushcfunction(L, lqtL_ctor_helper); // (3)
279 lua_setfield(L, -2, "__call"); // (2)
280 lua_setmetatable(L, -2); // (1)
281 lua_pushvalue(L, -1); // (2)
282 lua_pushcclosure(L, lqtL_local_ctor, 1); // (2)
283 lua_setfield(L, -2, "new_local");
284 lua_pop(L, 1); // (0)
286 lua_pushlstring(L, name, strlen(name)-1); // (1)
287 lua_newtable(L); // (2)
288 luaL_newmetatable(L, name); // (3)
289 lua_setmetatable(L, -2); // (2)
290 // don't register again but use metatable
291 //luaL_register(L, NULL, mt); // (2)
292 lua_settable(L, LUA_GLOBALSINDEX); // (0)
294 return 0;
297 int lqtL_createclasses (lua_State *L, lqt_Class *list) {
298 while (list->name!=0) { // (0)
299 luaL_newmetatable(L, list->name); // (1)
300 luaL_register(L, NULL, list->mt); // (1)
301 lua_pushstring(L, list->name); // (2)
302 lua_pushboolean(L, 1); // (3)
303 lua_settable(L, -3); // (1)
304 lqtL_pushindexfunc(L, list->name, list->bases); // (2)
305 lua_setfield(L, -2, "__index"); // (1)
306 lua_pushcfunction(L, lqtL_newindexfunc); // (2)
307 lua_setfield(L, -2, "__newindex"); // (1)
308 lua_pushcfunction(L, lqtL_gcfunc); // (2)
309 lua_setfield(L, -2, "__gc"); // (1)
310 lua_pushvalue(L, -1); // (2)
311 lua_setmetatable(L, -2); // (1)
312 lua_pop(L, 1); // (0)
313 lua_pushlstring(L, list->name, strlen(list->name)-1); // (1)
314 lua_newtable(L); // (2)
315 luaL_register(L, NULL, list->mt); // (2)
316 lua_settable(L, LUA_GLOBALSINDEX); // (0)
317 list++;
319 return 0;
322 bool lqtL_isinteger (lua_State *L, int i) {
323 if (lua_type(L, i)==LUA_TNUMBER)
324 return lua_tointeger(L, i)==lua_tonumber(L, i);
325 else
326 return false;
328 bool lqtL_isnumber (lua_State *L, int i) {
329 return lua_type(L, i)==LUA_TNUMBER;
331 bool lqtL_isstring (lua_State *L, int i) {
332 return lua_type(L, i)==LUA_TSTRING;
334 bool lqtL_isboolean (lua_State *L, int i) {
335 return lua_type(L, i)==LUA_TBOOLEAN;
337 bool lqtL_missarg (lua_State *L, int index, int n) {
338 bool ret = true;
339 int i = 0;
340 for (i=index;i<index+n;i++) {
341 if (!lua_isnoneornil(L, i)) {
342 ret = false;
343 break;
346 return ret;
349 static void CS(lua_State *L) {
350 qDebug() << "++++++++++";
351 for (int i=1;i<=lua_gettop(L);i++) {
352 qDebug() << luaL_typename(L, i) << lua_touserdata(L, i);
354 qDebug() << "----------";
357 static void lqtL_ensurepointer (lua_State *L, const void *p) { // (+1)
358 lqtL_getpointertable(L); // (1)
359 lua_pushlightuserdata(L, const_cast<void*>(p)); // (2)
360 lua_gettable(L, -2); // (2)
361 if (lua_isnil(L, -1)) { // (2)
362 lua_pop(L, 1); // (1)
363 const void **pp = static_cast<const void**>(lua_newuserdata(L, sizeof(void*))); // (2)
364 *pp = p; // (2)
365 lua_newtable(L); // (3)
366 lua_setfenv(L, -2); // (2)
367 lua_pushlightuserdata(L, const_cast<void*>(p)); // (3)
368 lua_pushvalue(L, -2); // (4)
369 lua_settable(L, -4); // (2)
370 } else {
371 //const void **pp = static_cast<const void**>(lua_touserdata(L, -1)); // (2)
372 //if (pp!=NULL) *pp = p; // (2)
374 // (2)
375 lua_remove(L, -2); // (1)
378 void lqtL_register (lua_State *L, const void *p) { // (+0)
379 lqtL_ensurepointer(L, p);
380 lua_pop(L, 1);
383 void lqtL_unregister (lua_State *L, const void *p) {
384 lqtL_getpointertable(L); // (1)
385 lua_pushlightuserdata(L, const_cast<void*>(p)); // (2)
386 lua_gettable(L, -2); // (2)
387 if (lua_isuserdata(L, -1)) {
388 const void **pp = static_cast<const void**>(lua_touserdata(L, -1)); // (2)
389 *pp = 0;
391 lua_pop(L, 1); // (1)
392 lua_pushlightuserdata(L, const_cast<void*>(p)); // (2)
393 lua_pushnil(L); // (3)
394 lua_settable(L, -3); // (1)
395 lua_pop(L, 1); // (0)
398 void lqtL_pushudata (lua_State *L, const void *p, const char *name) {
399 bool already = false;
400 lqtL_ensurepointer(L, p); // (1)
401 if (lua_getmetatable(L, -1)) {
402 // (2)
403 lua_pop(L, 1); // (1)
404 lua_getfield(L, -1, name); // (2)
405 already = lua_toboolean(L, -1); // (2)
406 lua_pop(L, 1); // (1)
407 } else {
408 // (1)
410 if (!already) {
411 luaL_newmetatable(L, name); // (2)
412 lua_setmetatable(L, -2); // (1)
414 return;
417 void lqtL_passudata (lua_State *L, const void *p, const char *name) {
418 lqtL_pushudata(L, p, name);
419 // FIXME: these should be added, but it is not safe for now
420 //lua_getfield(L, -1, "delete");
421 //lua_setfield(L, -2, "__gc");
422 return;
425 void lqtL_copyudata (lua_State *L, const void *p, const char *name) {
426 luaL_newmetatable(L, name);
427 lua_pushstring(L, "new");
428 lua_rawget(L, -2);
429 if (lua_isnil(L, -1)) {
430 qDebug() << "cannot copy" << name;
431 lua_pop(L, 2);
432 lua_pushnil(L);
433 } else {
434 lua_remove(L, -2);
435 lqtL_pushudata(L, p, name);
436 if (lua_pcall(L, 1, 1, 0)) {
437 qDebug() << "error copying" << name;
438 lua_pop(L, 1);
439 lua_pushnil(L);
442 return;
445 void *lqtL_toudata (lua_State *L, int index, const char *name) {
446 void *ret = 0;
447 if (!lqtL_testudata(L, index, name)) return 0;
448 void **pp = static_cast<void**>(lua_touserdata(L, index));
449 ret = *pp;
450 lua_getfield(L, index, name);
451 ret = (void*)(lua_tointeger(L, -1) + (char*)ret);
452 lua_pop(L, 1);
453 return ret;
456 void lqtL_eraseudata (lua_State *L, int index, const char *name) {
457 void *ret = 0;
458 if (name!=NULL && !lqtL_testudata(L, index, name)) return;
459 void **pp = static_cast<void**>(lua_touserdata(L, index));
460 void *p = *pp;
461 *pp = 0;
462 lqtL_getpointertable(L); // (1)
463 lua_pushlightuserdata(L, p); // (2)
464 lua_pushnil(L); // (3)
465 lua_settable(L, -3); // (1)
466 lua_pop(L, 1);
467 return;
470 bool lqtL_testudata (lua_State *L, int index, const char *name) {
471 if (!lua_isuserdata(L, index) || lua_islightuserdata(L, index)) return false;
472 lua_getfield(L, index, name);
473 if (lua_isnil(L, -1)) {
474 lua_pop(L, 1);
475 return false;
477 lua_pop(L, 1);
478 return true;
481 void lqtL_pushenum (lua_State *L, int value, const char *name) {
482 lqtL_getenumtable(L);
483 lua_getfield(L, -1, name);
484 lua_remove(L, -2);
485 if (!lua_istable(L, -1)) {
486 lua_pop(L, 1);
487 lua_pushnil(L);
488 return;
490 lua_pushnumber(L, value);
491 lua_gettable(L, -2);
492 lua_remove(L, -2);
495 bool lqtL_isenum (lua_State *L, int index, const char *name) {
496 bool ret = false;
497 if (!lua_isstring(L, index)) return false;
498 lqtL_getenumtable(L);
499 lua_getfield(L, -1, name);
500 if (!lua_istable(L, -1)) {
501 lua_pop(L, 2);
502 return false;
504 lua_remove(L, -2);
505 lua_pushvalue(L, index);
506 lua_gettable(L, -2);
507 ret = lua_isnumber(L, -1);
508 lua_pop(L, 2);
509 return ret;
512 int lqtL_toenum (lua_State *L, int index, const char *name) {
513 int ret = -1;
514 lqtL_getenumtable(L); // (1)
515 lua_getfield(L, -1, name); // (2)
516 if (lua_isnil(L, -1)) {
517 lua_pop(L, 2); //(0)
518 return 0;
520 lua_pushvalue(L, index); // (3)
521 lua_gettable(L, -2); // (3)
522 ret = lua_tointeger(L, -1); // (3)
523 lua_pop(L, 3); // (0)
524 return ret;
527 int lqtL_getflags (lua_State *L, int index, const char *name) {
528 int ret = 0;
529 int eindex = 0;
530 int i = 1;
531 if (!lua_istable(L, index)) return 0;
532 lqtL_getenumtable(L); // (1)
533 lua_getfield(L, -1, name); // (2)
534 if (!lua_istable(L, -1)) {
535 // (2)
536 lua_pop(L, 2);
537 return 0;
539 // (2)
540 lua_remove(L, -2); // (1)
541 eindex = lua_gettop(L);
542 for (i=1;;i++) { // (1)
543 lua_rawgeti(L, index, i); // (2)
544 if (lua_type(L, -1)!=LUA_TSTRING) {
545 lua_pop(L, 1); // (1)
546 break;
547 } else {
548 lua_gettable(L, eindex); // (2)
549 ret = ret | (int)lua_tointeger(L, -1);
550 lua_pop(L, 1); // (1)
553 // (1)
554 lua_pop(L, 1); // (0)
555 return ret;
558 void lqtL_pushflags (lua_State *L, int index, const char *name) {
559 // TODO
560 lua_pushnil(L);
561 return;
564 int lqtL_touintarray (lua_State *L) {
565 uint *p = NULL;
566 size_t i = 0;
567 size_t n, nb;
568 n = lua_objlen(L, -1);
569 nb = (n + 1) * sizeof(uint);
570 p = (uint*)lua_newuserdata(L, nb);
571 for (i=1;i<=n;i++) {
572 lua_rawgeti(L, -2, i);
573 p[i-1] = lua_tointeger(L, -1);
574 lua_pop(L, 1);
576 lua_remove(L, -2);
577 p[n] = 0;
578 return 1;