1
/* tolua: event functions
2
** Support code for Lua bindings.
3
** Written by Waldemar Celes
6
** $Id: tolua_event.c 14589 2008-04-15 21:40:53Z cazfi $
9
/* This code is free software; you can redistribute it and/or modify it.
10
** The software provided hereunder is on an "as is" basis, and
11
** the author has no obligation to provide maintenance, support, updates,
12
** enhancements, or modifications.
18
#include "tolua_event.h"
21
* It stores, creating the corresponding table if needed,
22
* the pair key/value in the corresponding ubox table
24
static void storeatubox (lua_State* L, int lo){
25
#ifdef LUA_VERSION_NUM /* stack: obj key val */
26
lua_getfenv(L, lo); /* stack: obj key val ?peer? */
27
if (lua_rawequal(L, -1, TOLUA_NOPEER)) { /* check if ?peer? is no peer really */ /* create peer table */
28
lua_pop(L, 1); /* stack: obj key val */
29
lua_newtable(L); /* stack: obj key val peer */
30
lua_pushvalue(L, -1); /* stack: obj key val peer peer */
31
lua_setfenv(L, lo); /* stack: obj key val peer */
33
lua_insert(L, -3); /* stack: obj peer key val */
34
lua_settable(L, -3); /* stack: obj peer */
35
lua_pop(L, 1); /* stack: obj */
36
/* on lua 5.1, we trade the "tolua_peers" lookup for a settable call */
38
/* stack: key value (to be stored) */
39
lua_pushstring(L,"tolua_peers");
40
lua_rawget(L,LUA_REGISTRYINDEX); /* stack: k v ubox */
42
lua_rawget(L,-2); /* stack: k v ubox ubox[u] */
43
if (!lua_istable(L,-1)) {
44
lua_pop(L,1); /* stack: k v ubox */
45
lua_newtable(L); /* stack: k v ubox table */
47
lua_pushvalue(L,-2); /* stack: k v ubox table u table */
48
lua_rawset(L,-4); /* stack: k v ubox ubox[u]=table */
50
lua_insert(L,-4); /* put table before k */
51
lua_pop(L,1); /* pop ubox */
52
lua_rawset(L,-3); /* store at table */
53
lua_pop(L,1); /* pop ubox[u] */
57
/* Module index function
59
static int module_index_event (lua_State* L){
60
lua_pushstring(L,".get");
62
if (lua_istable(L,-1)){
63
lua_pushvalue(L,2); /* key */
65
if (lua_iscfunction(L,-1)){
68
}else if (lua_istable(L,-1))
71
/* call old index meta event */
72
if (lua_getmetatable(L,1)){
73
lua_pushstring(L,"__index");
77
if (lua_isfunction(L,-1)){
80
}else if (lua_istable(L,-1)){
89
/* Module newindex function
91
static int module_newindex_event (lua_State* L){
92
lua_pushstring(L,".set");
94
if (lua_istable(L,-1)){
95
lua_pushvalue(L,2); /* key */
97
if (lua_iscfunction(L,-1)){
98
lua_pushvalue(L,1); /* only to be compatible with non-static vars */
99
lua_pushvalue(L,3); /* value */
104
/* call old newindex meta event */
105
if (lua_getmetatable(L,1) && lua_getmetatable(L,-1)){
106
lua_pushstring(L,"__newindex");
108
if (lua_isfunction(L,-1)){
120
/* Class index function
121
* If the object is a userdata (ie, an object), it searches the field in
122
* the alternative table stored in the corresponding "ubox" table.
125
//#define TOLUA_OLD_INDEX_METHODS
126
#ifdef TOLUA_OLD_INDEX_METHODS
127
static int class_index_event (lua_State* L){
128
int t = lua_type(L,1);
129
if (t == LUA_TUSERDATA) {
130
/* Access alternative table */
131
#ifdef LUA_VERSION_NUM /* new macro on version 5.1 */
133
if (!lua_rawequal(L, -1, TOLUA_NOPEER)) {
134
lua_pushvalue(L, 2); /* key */
135
lua_gettable(L, -2); /* on lua 5.1, we trade the "tolua_peers" lookup for a gettable call */
136
if (!lua_isnil(L, -1)) return 1;
139
lua_pushstring(L,"tolua_peers");
140
lua_rawget(L,LUA_REGISTRYINDEX); /* stack: obj key ubox */
142
lua_rawget(L,-2); /* stack: obj key ubox ubox[u] */
143
if (lua_istable(L,-1)){
144
lua_pushvalue(L,2); /* key */
145
lua_rawget(L,-2); /* stack: obj key ubox ubox[u] value */
146
if (!lua_isnil(L,-1)) return 1;
149
lua_settop(L,2); /* stack: obj key */
151
lua_pushvalue(L,1); /* stack: obj key obj */
152
while (lua_getmetatable(L,-1)) { /* stack: obj key obj mt */
153
lua_remove(L,-2); /* stack: obj key mt */
154
if (lua_isnumber(L,2)) { /* check if key is a numeric value */
156
lua_pushstring(L,".geti");
157
lua_rawget(L,-2); /* stack: obj key mt func */
158
if (lua_isfunction(L,-1)) {
165
lua_pushvalue(L,2); /* stack: obj key mt key */
166
lua_rawget(L,-2); /* stack: obj key mt value */
167
if (!lua_isnil(L,-1))return 1;
169
/* try C/C++ variable */
170
lua_pushstring(L,".get");
171
lua_rawget(L,-2); /* stack: obj key mt tget */
172
if (lua_istable(L,-1)){
174
lua_rawget(L,-2); /* stack: obj key mt value */
175
if (lua_iscfunction(L,-1)){
180
}else if (lua_istable(L,-1)){
181
/* deal with array: create table to be returned and cache it in ubox */
182
void* u = *((void**)lua_touserdata(L,1));
183
lua_newtable(L); /* stack: obj key mt value table */
184
lua_pushstring(L,".self");
185
lua_pushlightuserdata(L,u);
186
lua_rawset(L,-3); /* store usertype in ".self" */
187
lua_insert(L,-2); /* stack: obj key mt table value */
188
lua_setmetatable(L,-2); /* set stored value as metatable */
189
lua_pushvalue(L,-1); /* stack: obj key met table table */
190
lua_pushvalue(L,2); /* stack: obj key mt table table key */
191
lua_insert(L,-2); /* stack: obj key mt table key table */
192
storeatubox(L,1); /* stack: obj key mt table */
201
}else if (t== LUA_TTABLE){
202
module_index_event(L);
210
* It first searches for a C/C++ varaible to be set.
211
* Then, it either stores it in the alternative ubox table (in the case it is
212
* an object) or in the own table (that represents the class or module).
214
static int class_newindex_event (lua_State* L){
215
int t = lua_type(L,1);
216
if (t == LUA_TUSERDATA){
217
/* Try accessing a C/C++ variable to be set */
218
lua_getmetatable(L,1);
219
while (lua_istable(L,-1)) { /* stack: t k v mt */
220
if (lua_isnumber(L,2)) { /* check if key is a numeric value */
222
lua_pushstring(L,".seti");
223
lua_rawget(L,-2); /* stack: obj key mt func */
224
if (lua_isfunction(L,-1)) {
232
lua_pushstring(L,".set");
233
lua_rawget(L,-2); /* stack: t k v mt tset */
234
if (lua_istable(L,-1)) {
236
lua_rawget(L,-2); /* stack: t k v mt tset func */
237
if (lua_iscfunction(L,-1)) {
243
lua_pop(L,1); /* stack: t k v mt tset */
245
lua_pop(L,1); /* stack: t k v mt */
246
if (!lua_getmetatable(L,-1))lua_pushnil(L); /* stack: t k v mt mt */
247
lua_remove(L,-2); /* stack: t k v mt */
250
lua_settop(L,3); /* stack: t k v */
251
/* then, store as a new field */
253
} else if (t== LUA_TTABLE) {
254
module_newindex_event(L);
258
#else // ifndef TOLUA_OLD_INDEX_METHODS
259
static int class_index_event (lua_State* L){ // method with operator[](string)
260
int t = lua_type(L,1);
261
if (t == LUA_TUSERDATA) {
262
lua_pushvalue(L,1); /* stack: obj key obj */
264
while (lua_getmetatable(L,-1)) { /* stack: obj key obj mt */
265
lua_remove(L,-2); /* stack: obj key mt */
266
if (lua_isnumber(L,2)) { /* check if key is a numeric value */
267
/* try operator[](number) */
268
lua_pushstring(L,".geti"); /* stack: obj key mt ".geti" */
269
lua_rawget(L,-2); /* stack: obj key mt ?func? */
270
if (lua_isfunction(L,-1)) { /* check if func is function? */
271
lua_pushvalue(L,1); /* stack: obj key mt func obj */
272
lua_pushvalue(L,2); /* stack: obj key mt func obj key */
273
lua_call(L,2,1); /* stack: obj key mt ret */
274
return 1; /* stack: ret */
277
lua_pushvalue(L,2); /* stack: obj key mt key */
278
lua_rawget(L,-2); /* stack: obj key mt value */
279
if (!lua_isnil(L,-1))return 1; /* value is nil? */
280
else lua_pop(L,1); /* stack: obj key mt */
281
/* try C/C++ variable */
282
lua_pushstring(L,".get"); /* stack: obj key mt ".get" */
283
lua_rawget(L,-2); /* stack: obj key mt tget */
284
if (lua_istable(L,-1)){ /* tget is table? */
285
lua_pushvalue(L,2); /* stack: obj key mt tget key */
286
lua_rawget(L,-2); /* stack: obj key mt tget value */
287
if (lua_iscfunction(L,-1)){ /* value is cfunction? */
288
lua_pushvalue(L,1); /* stack: obj key mt tget value obj */
289
lua_pushvalue(L,2); /* stack: obj key mt tget value obj key */
290
lua_call(L,2,1); /* stack: obj key mt tget value ret */
291
return 1; /* stack: ret */
292
}else if (lua_istable(L,-1)){ /* value is table? */
293
/* deal with array: create table to be returned and cache it in ubox */
294
void* u = *((void**)lua_touserdata(L,1));
295
lua_newtable(L); /* stack: obj key mt tget value table */
296
lua_pushstring(L,".self"); /* stack: obj key mt tget value table ".self" */
297
lua_pushlightuserdata(L,u); /* stack: obj key mt tget value table ".self" usertype */
298
/* store usertype in ".self" field table */
299
lua_rawset(L,-3); /* stack: obj key mt tget value table */
300
lua_insert(L,-2); /* stack: obj key mt tget table value */
301
/* set stored value as metatable */
302
lua_setmetatable(L,-2); /* stack: obj key mt tget table */
303
lua_pushvalue(L,-1); /* stack: obj key mt tget table table */
304
lua_pushvalue(L,2); /* stack: obj key mt tget table table key */
305
lua_insert(L,-2); /* stack: obj key mt tget table key table */
306
storeatubox(L,1); /* stack: obj key mt tget table */
307
return 1; /* stack: table */
311
lua_settop(L,3); /* stack: obj key mt */
313
/* For operator[](string) */
314
lua_settop(L,2); /* stack: obj key */
315
lua_pushvalue(L,1); /* stack: obj key obj */
317
while (lua_getmetatable(L,-1)) { /* stack: obj key obj mt */
318
lua_remove(L,-2); /* stack: obj key mt */
319
if (lua_isstring(L,2)) { /* check if key is a string value */
320
/* try operator[](string) */
321
lua_pushstring(L,".gets"); /* stack: obj key mt ".gets" */
322
lua_rawget(L,-2); /* stack: obj key mt ?func? */
323
if (lua_isfunction(L,-1)) { /* check if func is function? */
324
lua_pushvalue(L,1); /* stack: obj key mt func obj */
325
lua_pushvalue(L,2); /* stack: obj key mt func obj key */
326
/*--lua_call(L,2,1);*/ /* stack: obj key mt ret--*/
327
lua_call(L,2,1); /* stack: obj key mt ?ret? */
328
if(lua_isnil(L,-1)){ /* check if .gets not passed */
329
/* stack: obj key mt nil */
330
}else{ /* stack: obj key mt ret novalue */
331
return 1; /* stack: ret */
335
lua_settop(L,3); /* stack: obj key mt */
337
lua_settop(L,2); /* stack: obj key */
338
/* Access alternative table */
339
#ifdef LUA_VERSION_NUM /* new macro on version 5.1 */
340
lua_getfenv(L,1); /* stack: obj key ?peer? */
341
if (!lua_rawequal(L, -1, TOLUA_NOPEER)) {/* check if ?peer? is peer */
342
lua_pushvalue(L, 2); /* stack: obj key peer key */
343
lua_gettable(L, -2); /* stack: obj key val */
344
/* on lua 5.1, we trade the "tolua_peers" lookup for a gettable call */
345
if (!lua_isnil(L, -1)) return 1; /* stack: val */
348
lua_pushstring(L,"tolua_peers");
349
lua_rawget(L,LUA_REGISTRYINDEX); /* stack: obj key ubox */
351
lua_rawget(L,-2); /* stack: obj key ubox ubox[u] */
352
if (lua_istable(L,-1)) {
353
lua_pushvalue(L,2); /* key */
354
lua_rawget(L,-2); /* stack: obj key ubox ubox[u] value */
355
if (!lua_isnil(L,-1)) return 1;
358
lua_settop(L,2); /* stack: obj key */
359
lua_pushnil(L); /* stack: obj key nil */
360
return 1; /* stack: nil */
361
}else if (t == LUA_TTABLE) {
362
module_index_event(L);
365
lua_pushnil(L); /* stack: obj key mt nil */
366
return 1; /* stack: nil */
370
* It first searches for a C/C++ varaible to be set.
371
* Then, it either stores it in the alternative ubox table (in the case it is
372
* an object) or in the own table (that represents the class or module).
374
static int class_newindex_event (lua_State* L){
375
//DEBUG_STACK(class_newindex_event init);
376
int t = lua_type(L,1);
377
if (t == LUA_TUSERDATA){ /* stack: obj key val */
378
/* Try accessing a C/C++ variable to be set */
379
lua_getmetatable(L,1); /* stack: obj key val ?mt? */
380
while (lua_istable(L,-1)) { /* check if ?mt? is a table */
381
if (lua_isnumber(L,2)) { /* check if key is a numeric value */
382
/* try operator[](number) */
383
lua_pushstring(L,".seti"); /* stack: obj key val mt ".seti" */
384
lua_rawget(L,-2); /* stack: obj key val mt ?func? */
385
if (lua_isfunction(L,-1)) { /* check if ?func? is a function */
386
lua_pushvalue(L,1); /* stack: obj key val mt func obj */
387
lua_pushvalue(L,2); /* stack: obj key val mt func obj key */
388
lua_pushvalue(L,3); /* stack: obj key val mt func obj key val */
389
lua_call(L,3,0); /* stack: obj key val mt */
390
lua_settop(L,3); /* stack: obj key val */
391
if (lua_isuserdata(L,-1) || lua_isnil(L,-1)) { /* check if val is userdata or nil */ /* therefor garbage collector not collect userdata store it into peer */
392
storeatubox(L,1); /* stack: obj */
394
return 0; /* stack: no value */
396
lua_pop(L,1); /* stack: obj key val mt */
397
if (!lua_getmetatable(L,-1)) /* stack: obj key val mt ?next_mt? */
398
lua_pushnil(L); /* stack: obj key val mt nil */
399
lua_remove(L,-2); /* stack: obj key val next_mt */
400
} else { /* check if key is a not numeric value */
401
lua_pushstring(L,".set"); /* stack: obj key val mt ".set" */
402
lua_rawget(L,-2); /* stack: obj key val mt tset */
403
if (lua_istable(L,-1)) { /* check if tset if table */
404
lua_pushvalue(L,2); /* stack: obj key val mt tset key */
405
lua_rawget(L,-2); /* stack: obj key val mt tset ?func? */
406
if (lua_iscfunction(L,-1)) { /* check if ?func? is a function */
407
lua_pushvalue(L,1); /* stack: obj key val mt tset func obj */
408
lua_pushvalue(L,3); /* stack: obj key val mt tset func obj val */
409
lua_call(L,2,0); /* stack: obj key val mt tset */
410
return 0; /* stack: */
412
lua_pop(L,1); /* stack: obj key val mt tset */
414
lua_pop(L,1); /* stack: obj key val mt */
415
if (!lua_getmetatable(L,-1)) /* stack: obj key val mt ?next_mt? */
416
lua_pushnil(L); /* stack: obj key val mt nil */
417
lua_remove(L,-2); /* stack: obj key val next_mt */
420
lua_settop(L,3); /* stack: obj key val */
421
if (lua_isstring(L,2)) { /* check if key is a string value */
422
/* try operator[](string) */
423
//DEBUG_STACK(class_newindex_event try operator[](string));
424
lua_getmetatable(L,1); /* stack: obj key val mt */
425
while (lua_istable(L,-1)) { /* check if mt is table */
426
//DEBUG_STACK(class_newindex_event while (lua_istable(L,-1)));
427
lua_pushstring(L,".sets"); /* stack: obj key val mt ".sets" */
428
lua_rawget(L,-2); /* stack: obj key val mt ?func? */
429
if (lua_isfunction(L,-1)) { /* check if ?func? is a function */
430
lua_pushvalue(L,1); /* stack: obj key val mt func obj */
431
lua_pushvalue(L,2); /* stack: obj key val mt func obj key */
432
lua_pushvalue(L,3); /* stack: obj key val mt func obj key val */
433
/*--lua_call(L,3,0);--*/ /*-- stack: obj key val mt --*/
434
int t=lua_gettop(L)-1;
435
//DEBUG_STACK(class_newindex_event call .sets);
436
lua_call(L,3,3); /* stack: obj key val mt <?obj? ?key? ?val?> */
437
if (lua_isuserdata(L,t-2) &&
438
lua_isstring(L,t-1)) { /* check if .sets not passed */
439
/* stack: obj key val mt obj key val */
440
lua_remove(L,-1); /* stack: obj key val mt obj key */
441
lua_remove(L,-1); /* stack: obj key val mt obj */
442
lua_remove(L,-1); /* stack: obj key val mt */
444
lua_settop(L,3); /* stack: obj key val */
445
if (lua_isuserdata(L,-1) || lua_isnil(L,-1)) { /* check if val is userdata or nil */ /* therefor garbage collector not collect userdata store it into peer */
446
storeatubox(L,1); /* stack: obj */
448
return 0; /* stack: no value */
450
}else lua_remove(L,-1);
451
if (!lua_getmetatable(L,-1)){ /* stack: obj key val mt ?next_mt? */
452
lua_pushnil(L); /* stack: obj key val mt ?next_mt? nil */
453
lua_remove(L,-2); /* stack: obj key val nil */
455
/* stack: obj key val next_mt */
458
lua_settop(L,3); /* stack: obj key val */
459
/* then, store as a new field */
461
} else if (t==LUA_TTABLE) {
462
module_newindex_event(L);
472
* .... obj tab key val
477
* get from obj field with key
478
* .... obj tab key val fld
480
* .... obj tab key fld val
481
* recursive call this function
482
* .... obj tab key fld val
483
* remove key, fld and val
488
/* extended table construstor */
489
static int tolua_class_attribs_from_table(lua_State* L){
490
if(!lua_isuserdata(L,-2) || !lua_istable(L,-1))return 0;
492
lua_pushnil(L); /* stack: obj tab nil */
493
for(;lua_next(L,-2)!=0;){ /* stack: obj tab key val */
494
//DEBUG_STACK(lua_next(L,-1)!=0);
495
if(lua_istable(L,-1)){ /* check if val is table */
496
lua_pushvalue(L,-2); /* stack: obj tab key val key */
497
lua_gettable(L,-5); /* stack: obj tab key val fld */
498
lua_insert(L,-2); /* stack: obj tab key fld val */
499
tolua_class_attribs_from_table(L); /* stack: obj tab key fld val */
500
lua_remove(L,-1); /* stack: obj tab key fld */
501
lua_remove(L,-1); /* stack: obj tab key */
503
/* stack: obj tab key val */
504
lua_pushvalue(L,-2); /* stack: obj tab key val key */
505
lua_insert(L,-2); /* stack: obj tab key key val */
506
lua_settable(L,-5); /* stack: obj tab key */
509
//DEBUG_STACK(lua_next(L,-1)!=0 end);
510
return 1; /* stack: obj tab */
513
static int class_call_event(lua_State* L) {
514
if (lua_istable(L,1)) { /* stack: obj <args> */
515
lua_pushstring(L,".call"); /* stack: obj <args> ".call" */
516
lua_rawget(L,1); /* stack: obj <args> ?func? */
517
if (lua_isfunction(L,-1)) { /* chack if ?func? is function */
518
lua_insert(L,1); /* stack: func obj <args> */
519
DEBUG_STACK(lua_isfunction(L,-1) lua_insert(L,1));
520
if(lua_gettop(L)>2 && lua_istable(L,-1)){ /* chack if last arg is lua table */
521
DEBUG_STACK(lua_gettop(L)>2 && lua_istable(L,-1));
522
/* stack: func obj <args> table */
523
lua_insert(L,1); /* stack: table func obj <args> */
524
DEBUG_STACK(lua_insert(L,1));
525
lua_call(L,lua_gettop(L)-2,1); /* stack: table ret */
526
DEBUG_STACK(lua_call(L,lua_gettop(L)-2,1));
527
lua_insert(L,-2); /* stack: ret table */
528
DEBUG_STACK(lua_insert(L,-2));
529
tolua_class_attribs_from_table(L); /* stack: ret table */
530
DEBUG_STACK(tolua_class_attribs_from_table(L));
531
lua_remove(L,-1); /* stack: ret */
532
DEBUG_STACK(tolua_class_attribs_from_table(L) lua_remove(L,-1));
533
return 1; /* stack: ret */
535
/* stack: func obj <args> */
536
lua_call(L,lua_gettop(L)-1,1); /* stack: func ret */
537
return 1; /* stack: ret */
541
if (lua_isuserdata(L,1)) { /* stack: obj {args} */
542
/* for sub object calling: obj{prop1=val1, ...., propN=valN} */
543
if(lua_istable(L,2)&&(lua_gettop(L)==2||lua_isnil(L,3))){ /* check if two arg is lua table */
544
tolua_class_attribs_from_table(L); /* stack: obj tab */
547
lua_pushvalue(L,1); /* stack: obj {args} obj */
548
while (lua_getmetatable(L,-1)) { /* stack: obj {args} obj mt */ /* Try metatables */
549
lua_remove(L,-2); /* stack: obj {args} mt */
550
lua_pushstring(L,".callself"); /* stack: obj {args} mt name */
551
lua_rawget(L,-2); /* stack: obj {args} mt func */
552
if (lua_isfunction(L,-1)) { /* func is function? */
553
lua_insert(L,1); /* stack: func obj {args} mt */
554
lua_settop(L,lua_gettop(L)-1); /* stack: func obj {args} */ /* args ={ nil key } */
555
/*DEBUG_STACK("prepare");*/
556
if(lua_gettop(L)==4&&lua_isnil(L,3))lua_insert(L,3); /* args ={ key nil } */
557
/*DEBUG_STACK("prep call");*/
558
lua_call(L,lua_gettop(L)-1,-1); /* stack: {rets} */ /* rets ={ nil key } */
559
/*if(lua_gettop(L)==2&&lua_isnil(L,2))lua_insert(L,1);*/ /* rets ={ key nil } */
560
/*DEBUG_STACK("post call");*/
561
return lua_gettop(L); /* stack: {rets} */
563
lua_settop(L,3); /* stack: obj {args} mt */
567
tolua_error(L,"Attempt to call a non-callable object.",NULL);
571
static int do_twin_operator (lua_State* L, const char* op) {
572
if (lua_isuserdata(L,1)) { /* stack: op1 op2 */
573
lua_pushvalue(L,1); /* stack: op1 op2 op1 */
574
while (lua_getmetatable(L,-1)) { /* stack: op1 op2 op1 mt */ /* Try metatables */
575
lua_remove(L,-2); /* stack: op1 op2 mt */
576
lua_pushstring(L,op); /* stack: op1 op2 mt key */
577
lua_rawget(L,-2); /* stack: op1 op2 mt ?func? */
578
if (lua_isfunction(L,-1)) { /* func is function? */
579
lua_pushvalue(L,1); /* stack: op1 op2 mt func op1 */
580
lua_pushvalue(L,2); /* stack: op1 op2 mt func op1 op2 */
581
lua_call(L,2,1); /* stack: op1 op2 mt func ret */
582
return 1; /* stack: ret */
584
lua_settop(L,3); /* stack: op1 op2 mt */
587
tolua_error(L,"Attempt to perform operation on an invalid operand",NULL);
591
static int do_unary_operator (lua_State* L, const char* op) {
592
if (lua_isuserdata(L,1)) { /* stack: op */
593
lua_pushvalue(L,1); /* stack: op op */
595
while (lua_getmetatable(L,-1)) { /* stack: op op mt */
596
lua_remove(L,-2); /* stack: op mt */
597
lua_pushstring(L,op); /* stack: op mt key */
598
lua_rawget(L,-2); /* stack: op mt ?func? */
599
if (lua_isfunction(L,-1)) { /* check if ?func? is function */
600
lua_pushvalue(L,1); /* stack: op mt func op */
601
lua_call(L,1,1); /* stack: op mt func ret */
602
return 1; /* stack: ret */
604
lua_settop(L,2); /* stack: op mt */
607
tolua_error(L,"Attempt to perform operation on an invalid operand",NULL);
612
static int class_tostring_event (lua_State* L){
613
if (lua_isuserdata(L,1)) { /* stack: op */
614
lua_pushvalue(L,1); /* stack: op op */
616
while (lua_getmetatable(L,-1)) { /* stack: op op mt */
617
lua_remove(L,-2); /* stack: op mt */
618
lua_pushstring(L,".string"); /* stack: op mt key */
619
lua_rawget(L,-2); /* stack: op mt ?func? */
620
if (lua_isfunction(L,-1)) { /* check if ?func? is function */
621
lua_pushvalue(L,1); /* stack: op mt func op */
622
lua_call(L,1,1); /* stack: op mt func ret */
623
return 1; /* stack: ret */
625
lua_settop(L,2); /* stack: op mt */
631
p=lua_touserdata(L,1); /* get address pointer */
632
sprintf(b,"userdata: 0x%p", p);/* print pointer */
636
tolua_error(L,"Attempt to perform operation .string on an invalid operand",NULL);
640
static int class_add_event (lua_State* L){
641
return do_twin_operator(L,".add");
644
static int class_sub_event (lua_State* L){
645
return do_twin_operator(L,".sub");
648
static int class_mul_event (lua_State* L){
649
return do_twin_operator(L,".mul");
652
static int class_pow_event (lua_State* L){
653
return do_twin_operator(L,".pow");
656
static int class_len_event (lua_State* L){
657
return do_unary_operator(L,".len");
660
static int class_unm_event (lua_State* L){
661
return do_unary_operator(L,".unm");
664
static int class_mod_event (lua_State* L){
665
return do_twin_operator(L,".mod");
668
static int class_div_event (lua_State* L){
669
return do_twin_operator(L,".div");
672
static int class_concat_event (lua_State* L){
673
return do_twin_operator(L,".concat");
676
static int class_lt_event (lua_State* L){
677
return do_twin_operator(L,".lt");
680
static int class_le_event (lua_State* L){
681
return do_twin_operator(L,".le");
684
static int class_eq_event (lua_State* L){
685
return do_twin_operator(L,".eq");
689
static int class_gc_event (lua_State* L)
691
void* u = *((void**)lua_touserdata(L,1));
692
fprintf(stderr, "collecting: looking at %p\n", u);
693
lua_pushstring(L,"tolua_gc");
694
lua_rawget(L,LUA_REGISTRYINDEX);
695
lua_pushlightuserdata(L,u);
697
if (lua_isfunction(L,-1))
701
lua_pushlightuserdata(L,u);
709
TOLUA_API int class_gc_event (lua_State* L){
710
void* u = *((void**)lua_touserdata(L,1));
712
/*fprintf(stderr, "collecting: looking at %p\n", u);*/
714
lua_pushstring(L,"tolua_gc");
715
lua_rawget(L,LUA_REGISTRYINDEX);
717
lua_pushvalue(L, lua_upvalueindex(1));
718
lua_pushlightuserdata(L,u);
719
lua_rawget(L,-2); /* stack: gc umt */
720
lua_getmetatable(L,1); /* stack: gc umt mt */
721
/*fprintf(stderr, "checking type\n");*/
723
if (tolua_fast_isa(L,top,top-1, lua_upvalueindex(2))) { /* make sure we collect correct type */
724
/*fprintf(stderr, "Found type!\n");*/
725
/* get gc function */
726
lua_pushliteral(L,".collector");
727
lua_rawget(L,-2); /* stack: gc umt mt collector */
728
if (lua_isfunction(L,-1)) {
729
/*fprintf(stderr, "Found .collector!\n");*/
732
/*fprintf(stderr, "Using default cleanup\n");*/
733
lua_pushcfunction(L,tolua_default_collect);
736
lua_pushvalue(L,1); /* stack: gc umt mt collector u */
739
lua_pushlightuserdata(L,u); /* stack: gc umt mt u */
740
lua_pushnil(L); /* stack: gc umt mt u nil */
741
lua_rawset(L,-5); /* stack: gc umt mt */
748
/* Register module events
749
* It expects the metatable on the top of the stack
751
TOLUA_API void tolua_moduleevents (lua_State* L){
752
lua_pushstring(L,"__index");
753
lua_pushcfunction(L,module_index_event);
755
lua_pushstring(L,"__newindex");
756
lua_pushcfunction(L,module_newindex_event);
760
/* Check if the object on the top has a module metatable
762
TOLUA_API int tolua_ismodulemetatable (lua_State* L){
764
if (lua_getmetatable(L,-1)) {
765
lua_pushstring(L,"__index");
767
r = (lua_tocfunction(L,-1) == module_index_event);
773
/* Register class events
774
* It expects the metatable on the top of the stack
776
TOLUA_API void tolua_classevents (lua_State* L) {
777
lua_pushstring(L,"__index");
778
lua_pushcfunction(L,class_index_event);
780
lua_pushstring(L,"__newindex");
781
lua_pushcfunction(L,class_newindex_event);
784
lua_pushstring(L,"__add");
785
lua_pushcfunction(L,class_add_event);
787
lua_pushstring(L,"__sub");
788
lua_pushcfunction(L,class_sub_event);
790
lua_pushstring(L,"__mul");
791
lua_pushcfunction(L,class_mul_event);
793
lua_pushstring(L,"__div");
794
lua_pushcfunction(L,class_div_event);
796
// toluaxx new operators
797
lua_pushstring(L,"__pow");
798
lua_pushcfunction(L,class_pow_event);
800
lua_pushstring(L,"__mod");
801
lua_pushcfunction(L,class_mod_event);
803
lua_pushstring(L,"__len");
804
lua_pushcfunction(L,class_len_event);
806
lua_pushstring(L,"__concat");
807
lua_pushcfunction(L,class_concat_event);
809
lua_pushstring(L,"__unm");
810
lua_pushcfunction(L,class_unm_event);
812
lua_pushstring(L,"__tostring");
813
lua_pushcfunction(L,class_tostring_event);
815
// end toluaxx operators
816
lua_pushstring(L,"__lt");
817
lua_pushcfunction(L,class_lt_event);
819
lua_pushstring(L,"__le");
820
lua_pushcfunction(L,class_le_event);
822
lua_pushstring(L,"__eq");
823
lua_pushcfunction(L,class_eq_event);
826
lua_pushstring(L,"__call");
827
lua_pushcfunction(L,class_call_event);
830
lua_pushstring(L,"__gc");
831
lua_pushstring(L, "tolua_gc_event");
832
lua_rawget(L, LUA_REGISTRYINDEX);
833
/*lua_pushcfunction(L,class_gc_event);*/