| [1129] | 1 | /* tolua: event functions | 
|---|
|  | 2 | ** Support code for Lua bindings. | 
|---|
|  | 3 | ** Written by Waldemar Celes | 
|---|
|  | 4 | ** TeCGraf/PUC-Rio | 
|---|
|  | 5 | ** Apr 2003 | 
|---|
|  | 6 | ** $Id: $ | 
|---|
|  | 7 | */ | 
|---|
|  | 8 |  | 
|---|
|  | 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. | 
|---|
|  | 13 | */ | 
|---|
|  | 14 |  | 
|---|
|  | 15 | #include <stdio.h> | 
|---|
|  | 16 |  | 
|---|
|  | 17 | #include "tolua++.h" | 
|---|
|  | 18 |  | 
|---|
|  | 19 | /* Store at ubox | 
|---|
|  | 20 | * It stores, creating the corresponding table if needed, | 
|---|
|  | 21 | * the pair key/value in the corresponding ubox table | 
|---|
|  | 22 | */ | 
|---|
|  | 23 | static void storeatubox (lua_State* L, int lo) | 
|---|
|  | 24 | { | 
|---|
|  | 25 | #ifdef LUA_VERSION_NUM | 
|---|
|  | 26 | lua_getfenv(L, lo); | 
|---|
|  | 27 | if (lua_rawequal(L, -1, TOLUA_NOPEER)) { | 
|---|
|  | 28 | lua_pop(L, 1); | 
|---|
|  | 29 | lua_newtable(L); | 
|---|
|  | 30 | lua_pushvalue(L, -1); | 
|---|
|  | 31 | lua_setfenv(L, lo);     /* stack: k,v,table  */ | 
|---|
|  | 32 | }; | 
|---|
|  | 33 | lua_insert(L, -3); | 
|---|
|  | 34 | lua_settable(L, -3); /* on lua 5.1, we trade the "tolua_peers" lookup for a settable call */ | 
|---|
|  | 35 | lua_pop(L, 1); | 
|---|
|  | 36 | #else | 
|---|
|  | 37 | /* stack: key value (to be stored) */ | 
|---|
|  | 38 | lua_pushstring(L,"tolua_peers"); | 
|---|
|  | 39 | lua_rawget(L,LUA_REGISTRYINDEX);        /* stack: k v ubox */ | 
|---|
|  | 40 | lua_pushvalue(L,lo); | 
|---|
|  | 41 | lua_rawget(L,-2);                       /* stack: k v ubox ubox[u] */ | 
|---|
|  | 42 | if (!lua_istable(L,-1)) | 
|---|
|  | 43 | { | 
|---|
|  | 44 | lua_pop(L,1);                          /* stack: k v ubox */ | 
|---|
|  | 45 | lua_newtable(L);                       /* stack: k v ubox table */ | 
|---|
|  | 46 | lua_pushvalue(L,1); | 
|---|
|  | 47 | lua_pushvalue(L,-2);                   /* stack: k v ubox table u table */ | 
|---|
|  | 48 | lua_rawset(L,-4);                      /* stack: k v ubox ubox[u]=table */ | 
|---|
|  | 49 | } | 
|---|
|  | 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] */ | 
|---|
|  | 54 | #endif | 
|---|
|  | 55 | } | 
|---|
|  | 56 |  | 
|---|
|  | 57 | /* Module index function | 
|---|
|  | 58 | */ | 
|---|
|  | 59 | static int module_index_event (lua_State* L) | 
|---|
|  | 60 | { | 
|---|
|  | 61 | lua_pushstring(L,".get"); | 
|---|
|  | 62 | lua_rawget(L,-3); | 
|---|
|  | 63 | if (lua_istable(L,-1)) | 
|---|
|  | 64 | { | 
|---|
|  | 65 | lua_pushvalue(L,2);  /* key */ | 
|---|
|  | 66 | lua_rawget(L,-2); | 
|---|
|  | 67 | if (lua_iscfunction(L,-1)) | 
|---|
|  | 68 | { | 
|---|
|  | 69 | lua_call(L,0,1); | 
|---|
|  | 70 | return 1; | 
|---|
|  | 71 | } | 
|---|
|  | 72 | else if (lua_istable(L,-1)) | 
|---|
|  | 73 | return 1; | 
|---|
|  | 74 | } | 
|---|
|  | 75 | /* call old index meta event */ | 
|---|
|  | 76 | if (lua_getmetatable(L,1)) | 
|---|
|  | 77 | { | 
|---|
|  | 78 | lua_pushstring(L,"__index"); | 
|---|
|  | 79 | lua_rawget(L,-2); | 
|---|
|  | 80 | lua_pushvalue(L,1); | 
|---|
|  | 81 | lua_pushvalue(L,2); | 
|---|
|  | 82 | if (lua_isfunction(L,-1)) | 
|---|
|  | 83 | { | 
|---|
|  | 84 | lua_call(L,2,1); | 
|---|
|  | 85 | return 1; | 
|---|
|  | 86 | } | 
|---|
|  | 87 | else if (lua_istable(L,-1)) | 
|---|
|  | 88 | { | 
|---|
|  | 89 | lua_gettable(L,-3); | 
|---|
|  | 90 | return 1; | 
|---|
|  | 91 | } | 
|---|
|  | 92 | } | 
|---|
|  | 93 | lua_pushnil(L); | 
|---|
|  | 94 | return 1; | 
|---|
|  | 95 | } | 
|---|
|  | 96 |  | 
|---|
|  | 97 | /* Module newindex function | 
|---|
|  | 98 | */ | 
|---|
|  | 99 | static int module_newindex_event (lua_State* L) | 
|---|
|  | 100 | { | 
|---|
|  | 101 | lua_pushstring(L,".set"); | 
|---|
|  | 102 | lua_rawget(L,-4); | 
|---|
|  | 103 | if (lua_istable(L,-1)) | 
|---|
|  | 104 | { | 
|---|
|  | 105 | lua_pushvalue(L,2);  /* key */ | 
|---|
|  | 106 | lua_rawget(L,-2); | 
|---|
|  | 107 | if (lua_iscfunction(L,-1)) | 
|---|
|  | 108 | { | 
|---|
|  | 109 | lua_pushvalue(L,1); /* only to be compatible with non-static vars */ | 
|---|
|  | 110 | lua_pushvalue(L,3); /* value */ | 
|---|
|  | 111 | lua_call(L,2,0); | 
|---|
|  | 112 | return 0; | 
|---|
|  | 113 | } | 
|---|
|  | 114 | } | 
|---|
|  | 115 | /* call old newindex meta event */ | 
|---|
|  | 116 | if (lua_getmetatable(L,1) && lua_getmetatable(L,-1)) | 
|---|
|  | 117 | { | 
|---|
|  | 118 | lua_pushstring(L,"__newindex"); | 
|---|
|  | 119 | lua_rawget(L,-2); | 
|---|
|  | 120 | if (lua_isfunction(L,-1)) | 
|---|
|  | 121 | { | 
|---|
|  | 122 | lua_pushvalue(L,1); | 
|---|
|  | 123 | lua_pushvalue(L,2); | 
|---|
|  | 124 | lua_pushvalue(L,3); | 
|---|
|  | 125 | lua_call(L,3,0); | 
|---|
|  | 126 | } | 
|---|
|  | 127 | } | 
|---|
|  | 128 | lua_settop(L,3); | 
|---|
|  | 129 | lua_rawset(L,-3); | 
|---|
|  | 130 | return 0; | 
|---|
|  | 131 | } | 
|---|
|  | 132 |  | 
|---|
|  | 133 | /* Class index function | 
|---|
|  | 134 | * If the object is a userdata (ie, an object), it searches the field in | 
|---|
|  | 135 | * the alternative table stored in the corresponding "ubox" table. | 
|---|
|  | 136 | */ | 
|---|
|  | 137 | static int class_index_event (lua_State* L) | 
|---|
|  | 138 | { | 
|---|
|  | 139 | int t = lua_type(L,1); | 
|---|
|  | 140 | if (t == LUA_TUSERDATA) | 
|---|
|  | 141 | { | 
|---|
|  | 142 | /* Access alternative table */ | 
|---|
|  | 143 | #ifdef LUA_VERSION_NUM /* new macro on version 5.1 */ | 
|---|
|  | 144 | lua_getfenv(L,1); | 
|---|
|  | 145 | if (!lua_rawequal(L, -1, TOLUA_NOPEER)) { | 
|---|
|  | 146 | lua_pushvalue(L, 2); /* key */ | 
|---|
|  | 147 | lua_gettable(L, -2); /* on lua 5.1, we trade the "tolua_peers" lookup for a gettable call */ | 
|---|
|  | 148 | if (!lua_isnil(L, -1)) | 
|---|
|  | 149 | return 1; | 
|---|
|  | 150 | }; | 
|---|
|  | 151 | #else | 
|---|
|  | 152 | lua_pushstring(L,"tolua_peers"); | 
|---|
|  | 153 | lua_rawget(L,LUA_REGISTRYINDEX);        /* stack: obj key ubox */ | 
|---|
|  | 154 | lua_pushvalue(L,1); | 
|---|
|  | 155 | lua_rawget(L,-2);                       /* stack: obj key ubox ubox[u] */ | 
|---|
|  | 156 | if (lua_istable(L,-1)) | 
|---|
|  | 157 | { | 
|---|
|  | 158 | lua_pushvalue(L,2);  /* key */ | 
|---|
|  | 159 | lua_rawget(L,-2);                      /* stack: obj key ubox ubox[u] value */ | 
|---|
|  | 160 | if (!lua_isnil(L,-1)) | 
|---|
|  | 161 | return 1; | 
|---|
|  | 162 | } | 
|---|
|  | 163 | #endif | 
|---|
|  | 164 | lua_settop(L,2);                        /* stack: obj key */ | 
|---|
|  | 165 | /* Try metatables */ | 
|---|
|  | 166 | lua_pushvalue(L,1);                     /* stack: obj key obj */ | 
|---|
|  | 167 | while (lua_getmetatable(L,-1)) | 
|---|
|  | 168 | {                                       /* stack: obj key obj mt */ | 
|---|
|  | 169 | lua_remove(L,-2);                      /* stack: obj key mt */ | 
|---|
|  | 170 | if (lua_isnumber(L,2))                 /* check if key is a numeric value */ | 
|---|
|  | 171 | { | 
|---|
|  | 172 | /* try operator[] */ | 
|---|
|  | 173 | lua_pushstring(L,".geti"); | 
|---|
|  | 174 | lua_rawget(L,-2);                      /* stack: obj key mt func */ | 
|---|
|  | 175 | if (lua_isfunction(L,-1)) | 
|---|
|  | 176 | { | 
|---|
|  | 177 | lua_pushvalue(L,1); | 
|---|
|  | 178 | lua_pushvalue(L,2); | 
|---|
|  | 179 | lua_call(L,2,1); | 
|---|
|  | 180 | return 1; | 
|---|
|  | 181 | } | 
|---|
|  | 182 | } | 
|---|
|  | 183 | else | 
|---|
|  | 184 | { | 
|---|
|  | 185 | lua_pushvalue(L,2);                    /* stack: obj key mt key */ | 
|---|
|  | 186 | lua_rawget(L,-2);                      /* stack: obj key mt value */ | 
|---|
|  | 187 | if (!lua_isnil(L,-1)) | 
|---|
|  | 188 | return 1; | 
|---|
|  | 189 | else | 
|---|
|  | 190 | lua_pop(L,1); | 
|---|
|  | 191 | /* try C/C++ variable */ | 
|---|
|  | 192 | lua_pushstring(L,".get"); | 
|---|
|  | 193 | lua_rawget(L,-2);                      /* stack: obj key mt tget */ | 
|---|
|  | 194 | if (lua_istable(L,-1)) | 
|---|
|  | 195 | { | 
|---|
|  | 196 | lua_pushvalue(L,2); | 
|---|
|  | 197 | lua_rawget(L,-2);                      /* stack: obj key mt value */ | 
|---|
|  | 198 | if (lua_iscfunction(L,-1)) | 
|---|
|  | 199 | { | 
|---|
|  | 200 | lua_pushvalue(L,1); | 
|---|
|  | 201 | lua_pushvalue(L,2); | 
|---|
|  | 202 | lua_call(L,2,1); | 
|---|
|  | 203 | return 1; | 
|---|
|  | 204 | } | 
|---|
|  | 205 | else if (lua_istable(L,-1)) | 
|---|
|  | 206 | { | 
|---|
|  | 207 | /* deal with array: create table to be returned and cache it in ubox */ | 
|---|
|  | 208 | void* u = *((void**)lua_touserdata(L,1)); | 
|---|
|  | 209 | lua_newtable(L);                /* stack: obj key mt value table */ | 
|---|
|  | 210 | lua_pushstring(L,".self"); | 
|---|
|  | 211 | lua_pushlightuserdata(L,u); | 
|---|
|  | 212 | lua_rawset(L,-3);               /* store usertype in ".self" */ | 
|---|
|  | 213 | lua_insert(L,-2);               /* stack: obj key mt table value */ | 
|---|
|  | 214 | lua_setmetatable(L,-2);         /* set stored value as metatable */ | 
|---|
|  | 215 | lua_pushvalue(L,-1);            /* stack: obj key met table table */ | 
|---|
|  | 216 | lua_pushvalue(L,2);             /* stack: obj key mt table table key */ | 
|---|
|  | 217 | lua_insert(L,-2);               /*  stack: obj key mt table key table */ | 
|---|
|  | 218 | storeatubox(L,1);               /* stack: obj key mt table */ | 
|---|
|  | 219 | return 1; | 
|---|
|  | 220 | } | 
|---|
|  | 221 | } | 
|---|
|  | 222 | } | 
|---|
|  | 223 | lua_settop(L,3); | 
|---|
|  | 224 | } | 
|---|
|  | 225 | lua_pushnil(L); | 
|---|
|  | 226 | return 1; | 
|---|
|  | 227 | } | 
|---|
|  | 228 | else if (t== LUA_TTABLE) | 
|---|
|  | 229 | { | 
|---|
|  | 230 | module_index_event(L); | 
|---|
|  | 231 | return 1; | 
|---|
|  | 232 | } | 
|---|
|  | 233 | lua_pushnil(L); | 
|---|
|  | 234 | return 1; | 
|---|
|  | 235 | } | 
|---|
|  | 236 |  | 
|---|
|  | 237 | /* Newindex function | 
|---|
|  | 238 | * It first searches for a C/C++ varaible to be set. | 
|---|
|  | 239 | * Then, it either stores it in the alternative ubox table (in the case it is | 
|---|
|  | 240 | * an object) or in the own table (that represents the class or module). | 
|---|
|  | 241 | */ | 
|---|
|  | 242 | static int class_newindex_event (lua_State* L) | 
|---|
|  | 243 | { | 
|---|
|  | 244 | int t = lua_type(L,1); | 
|---|
|  | 245 | if (t == LUA_TUSERDATA) | 
|---|
|  | 246 | { | 
|---|
|  | 247 | /* Try accessing a C/C++ variable to be set */ | 
|---|
|  | 248 | lua_getmetatable(L,1); | 
|---|
|  | 249 | while (lua_istable(L,-1))                /* stack: t k v mt */ | 
|---|
|  | 250 | { | 
|---|
|  | 251 | if (lua_isnumber(L,2))                 /* check if key is a numeric value */ | 
|---|
|  | 252 | { | 
|---|
|  | 253 | /* try operator[] */ | 
|---|
|  | 254 | lua_pushstring(L,".seti"); | 
|---|
|  | 255 | lua_rawget(L,-2);                      /* stack: obj key mt func */ | 
|---|
|  | 256 | if (lua_isfunction(L,-1)) | 
|---|
|  | 257 | { | 
|---|
|  | 258 | lua_pushvalue(L,1); | 
|---|
|  | 259 | lua_pushvalue(L,2); | 
|---|
|  | 260 | lua_pushvalue(L,3); | 
|---|
|  | 261 | lua_call(L,3,0); | 
|---|
|  | 262 | return 0; | 
|---|
|  | 263 | } | 
|---|
|  | 264 | } | 
|---|
|  | 265 | else | 
|---|
|  | 266 | { | 
|---|
|  | 267 | lua_pushstring(L,".set"); | 
|---|
|  | 268 | lua_rawget(L,-2);                      /* stack: t k v mt tset */ | 
|---|
|  | 269 | if (lua_istable(L,-1)) | 
|---|
|  | 270 | { | 
|---|
|  | 271 | lua_pushvalue(L,2); | 
|---|
|  | 272 | lua_rawget(L,-2);                     /* stack: t k v mt tset func */ | 
|---|
|  | 273 | if (lua_iscfunction(L,-1)) | 
|---|
|  | 274 | { | 
|---|
|  | 275 | lua_pushvalue(L,1); | 
|---|
|  | 276 | lua_pushvalue(L,3); | 
|---|
|  | 277 | lua_call(L,2,0); | 
|---|
|  | 278 | return 0; | 
|---|
|  | 279 | } | 
|---|
|  | 280 | lua_pop(L,1);                          /* stack: t k v mt tset */ | 
|---|
|  | 281 | } | 
|---|
|  | 282 | lua_pop(L,1);                           /* stack: t k v mt */ | 
|---|
|  | 283 | if (!lua_getmetatable(L,-1))            /* stack: t k v mt mt */ | 
|---|
|  | 284 | lua_pushnil(L); | 
|---|
|  | 285 | lua_remove(L,-2);                       /* stack: t k v mt */ | 
|---|
|  | 286 | } | 
|---|
|  | 287 | } | 
|---|
|  | 288 | lua_settop(L,3);                          /* stack: t k v */ | 
|---|
|  | 289 |  | 
|---|
|  | 290 | /* then, store as a new field */ | 
|---|
|  | 291 | storeatubox(L,1); | 
|---|
|  | 292 | } | 
|---|
|  | 293 | else if (t== LUA_TTABLE) | 
|---|
|  | 294 | { | 
|---|
|  | 295 | module_newindex_event(L); | 
|---|
|  | 296 | } | 
|---|
|  | 297 | return 0; | 
|---|
|  | 298 | } | 
|---|
|  | 299 |  | 
|---|
|  | 300 | static int class_call_event(lua_State* L) { | 
|---|
|  | 301 |  | 
|---|
|  | 302 | if (lua_istable(L, 1)) { | 
|---|
|  | 303 | lua_pushstring(L, ".call"); | 
|---|
|  | 304 | lua_rawget(L, 1); | 
|---|
|  | 305 | if (lua_isfunction(L, -1)) { | 
|---|
|  | 306 |  | 
|---|
|  | 307 | lua_insert(L, 1); | 
|---|
|  | 308 | lua_call(L, lua_gettop(L)-1, 1); | 
|---|
|  | 309 |  | 
|---|
|  | 310 | return 1; | 
|---|
|  | 311 | }; | 
|---|
|  | 312 | }; | 
|---|
|  | 313 | tolua_error(L,"Attempt to call a non-callable object.",NULL); | 
|---|
|  | 314 | return 0; | 
|---|
|  | 315 | }; | 
|---|
|  | 316 |  | 
|---|
|  | 317 | static int do_operator (lua_State* L, const char* op) | 
|---|
|  | 318 | { | 
|---|
|  | 319 | if (lua_isuserdata(L,1)) | 
|---|
|  | 320 | { | 
|---|
|  | 321 | /* Try metatables */ | 
|---|
|  | 322 | lua_pushvalue(L,1);                     /* stack: op1 op2 */ | 
|---|
|  | 323 | while (lua_getmetatable(L,-1)) | 
|---|
|  | 324 | {                                       /* stack: op1 op2 op1 mt */ | 
|---|
|  | 325 | lua_remove(L,-2);                      /* stack: op1 op2 mt */ | 
|---|
|  | 326 | lua_pushstring(L,op);                  /* stack: op1 op2 mt key */ | 
|---|
|  | 327 | lua_rawget(L,-2);                      /* stack: obj key mt func */ | 
|---|
|  | 328 | if (lua_isfunction(L,-1)) | 
|---|
|  | 329 | { | 
|---|
|  | 330 | lua_pushvalue(L,1); | 
|---|
|  | 331 | lua_pushvalue(L,2); | 
|---|
|  | 332 | lua_call(L,2,1); | 
|---|
|  | 333 | return 1; | 
|---|
|  | 334 | } | 
|---|
|  | 335 | lua_settop(L,3); | 
|---|
|  | 336 | } | 
|---|
|  | 337 | } | 
|---|
|  | 338 | tolua_error(L,"Attempt to perform operation on an invalid operand",NULL); | 
|---|
|  | 339 | return 0; | 
|---|
|  | 340 | } | 
|---|
|  | 341 |  | 
|---|
|  | 342 | static int class_add_event (lua_State* L) | 
|---|
|  | 343 | { | 
|---|
|  | 344 | return do_operator(L,".add"); | 
|---|
|  | 345 | } | 
|---|
|  | 346 |  | 
|---|
|  | 347 | static int class_sub_event (lua_State* L) | 
|---|
|  | 348 | { | 
|---|
|  | 349 | return do_operator(L,".sub"); | 
|---|
|  | 350 | } | 
|---|
|  | 351 |  | 
|---|
|  | 352 | static int class_mul_event (lua_State* L) | 
|---|
|  | 353 | { | 
|---|
|  | 354 | return do_operator(L,".mul"); | 
|---|
|  | 355 | } | 
|---|
|  | 356 |  | 
|---|
|  | 357 | static int class_div_event (lua_State* L) | 
|---|
|  | 358 | { | 
|---|
|  | 359 | return do_operator(L,".div"); | 
|---|
|  | 360 | } | 
|---|
|  | 361 |  | 
|---|
|  | 362 | static int class_lt_event (lua_State* L) | 
|---|
|  | 363 | { | 
|---|
|  | 364 | return do_operator(L,".lt"); | 
|---|
|  | 365 | } | 
|---|
|  | 366 |  | 
|---|
|  | 367 | static int class_le_event (lua_State* L) | 
|---|
|  | 368 | { | 
|---|
|  | 369 | return do_operator(L,".le"); | 
|---|
|  | 370 | } | 
|---|
|  | 371 |  | 
|---|
|  | 372 | static int class_eq_event (lua_State* L) | 
|---|
|  | 373 | { | 
|---|
|  | 374 | return do_operator(L,".eq"); | 
|---|
|  | 375 | } | 
|---|
|  | 376 |  | 
|---|
|  | 377 | /* | 
|---|
|  | 378 | static int class_gc_event (lua_State* L) | 
|---|
|  | 379 | { | 
|---|
|  | 380 | void* u = *((void**)lua_touserdata(L,1)); | 
|---|
|  | 381 | fprintf(stderr, "collecting: looking at %p\n", u); | 
|---|
|  | 382 | lua_pushstring(L,"tolua_gc"); | 
|---|
|  | 383 | lua_rawget(L,LUA_REGISTRYINDEX); | 
|---|
|  | 384 | lua_pushlightuserdata(L,u); | 
|---|
|  | 385 | lua_rawget(L,-2); | 
|---|
|  | 386 | if (lua_isfunction(L,-1)) | 
|---|
|  | 387 | { | 
|---|
|  | 388 | lua_pushvalue(L,1); | 
|---|
|  | 389 | lua_call(L,1,0); | 
|---|
|  | 390 | lua_pushlightuserdata(L,u); | 
|---|
|  | 391 | lua_pushnil(L); | 
|---|
|  | 392 | lua_rawset(L,-3); | 
|---|
|  | 393 | } | 
|---|
|  | 394 | lua_pop(L,2); | 
|---|
|  | 395 | return 0; | 
|---|
|  | 396 | } | 
|---|
|  | 397 | */ | 
|---|
|  | 398 | TOLUA_API int class_gc_event (lua_State* L) | 
|---|
|  | 399 | { | 
|---|
|  | 400 | void* u = *((void**)lua_touserdata(L,1)); | 
|---|
|  | 401 | int top; | 
|---|
|  | 402 | /*fprintf(stderr, "collecting: looking at %p\n", u);*/ | 
|---|
|  | 403 | /* | 
|---|
|  | 404 | lua_pushstring(L,"tolua_gc"); | 
|---|
|  | 405 | lua_rawget(L,LUA_REGISTRYINDEX); | 
|---|
|  | 406 | */ | 
|---|
|  | 407 | lua_pushvalue(L, lua_upvalueindex(1)); | 
|---|
|  | 408 | lua_pushlightuserdata(L,u); | 
|---|
|  | 409 | lua_rawget(L,-2);            /* stack: gc umt    */ | 
|---|
|  | 410 | lua_getmetatable(L,1);       /* stack: gc umt mt */ | 
|---|
|  | 411 | /*fprintf(stderr, "checking type\n");*/ | 
|---|
|  | 412 | top = lua_gettop(L); | 
|---|
|  | 413 | if (tolua_fast_isa(L,top,top-1, lua_upvalueindex(2))) /* make sure we collect correct type */ | 
|---|
|  | 414 | { | 
|---|
|  | 415 | /*fprintf(stderr, "Found type!\n");*/ | 
|---|
|  | 416 | /* get gc function */ | 
|---|
|  | 417 | lua_pushliteral(L,".collector"); | 
|---|
|  | 418 | lua_rawget(L,-2);           /* stack: gc umt mt collector */ | 
|---|
|  | 419 | if (lua_isfunction(L,-1)) { | 
|---|
|  | 420 | /*fprintf(stderr, "Found .collector!\n");*/ | 
|---|
|  | 421 | } | 
|---|
|  | 422 | else { | 
|---|
|  | 423 | lua_pop(L,1); | 
|---|
|  | 424 | /*fprintf(stderr, "Using default cleanup\n");*/ | 
|---|
|  | 425 | lua_pushcfunction(L,tolua_default_collect); | 
|---|
|  | 426 | } | 
|---|
|  | 427 |  | 
|---|
|  | 428 | lua_pushvalue(L,1);         /* stack: gc umt mt collector u */ | 
|---|
|  | 429 | lua_call(L,1,0); | 
|---|
|  | 430 |  | 
|---|
|  | 431 | lua_pushlightuserdata(L,u); /* stack: gc umt mt u */ | 
|---|
|  | 432 | lua_pushnil(L);             /* stack: gc umt mt u nil */ | 
|---|
|  | 433 | lua_rawset(L,-5);           /* stack: gc umt mt */ | 
|---|
|  | 434 | } | 
|---|
|  | 435 | lua_pop(L,3); | 
|---|
|  | 436 | return 0; | 
|---|
|  | 437 | } | 
|---|
|  | 438 |  | 
|---|
|  | 439 |  | 
|---|
|  | 440 | /* Register module events | 
|---|
|  | 441 | * It expects the metatable on the top of the stack | 
|---|
|  | 442 | */ | 
|---|
|  | 443 | TOLUA_API void tolua_moduleevents (lua_State* L) | 
|---|
|  | 444 | { | 
|---|
|  | 445 | lua_pushstring(L,"__index"); | 
|---|
|  | 446 | lua_pushcfunction(L,module_index_event); | 
|---|
|  | 447 | lua_rawset(L,-3); | 
|---|
|  | 448 | lua_pushstring(L,"__newindex"); | 
|---|
|  | 449 | lua_pushcfunction(L,module_newindex_event); | 
|---|
|  | 450 | lua_rawset(L,-3); | 
|---|
|  | 451 | } | 
|---|
|  | 452 |  | 
|---|
|  | 453 | /* Check if the object on the top has a module metatable | 
|---|
|  | 454 | */ | 
|---|
|  | 455 | TOLUA_API int tolua_ismodulemetatable (lua_State* L) | 
|---|
|  | 456 | { | 
|---|
|  | 457 | int r = 0; | 
|---|
|  | 458 | if (lua_getmetatable(L,-1)) | 
|---|
|  | 459 | { | 
|---|
|  | 460 | lua_pushstring(L,"__index"); | 
|---|
|  | 461 | lua_rawget(L,-2); | 
|---|
|  | 462 | r = (lua_tocfunction(L,-1) == module_index_event); | 
|---|
|  | 463 | lua_pop(L,2); | 
|---|
|  | 464 | } | 
|---|
|  | 465 | return r; | 
|---|
|  | 466 | } | 
|---|
|  | 467 |  | 
|---|
|  | 468 | /* Register class events | 
|---|
|  | 469 | * It expects the metatable on the top of the stack | 
|---|
|  | 470 | */ | 
|---|
|  | 471 | TOLUA_API void tolua_classevents (lua_State* L) | 
|---|
|  | 472 | { | 
|---|
|  | 473 | lua_pushstring(L,"__index"); | 
|---|
|  | 474 | lua_pushcfunction(L,class_index_event); | 
|---|
|  | 475 | lua_rawset(L,-3); | 
|---|
|  | 476 | lua_pushstring(L,"__newindex"); | 
|---|
|  | 477 | lua_pushcfunction(L,class_newindex_event); | 
|---|
|  | 478 | lua_rawset(L,-3); | 
|---|
|  | 479 |  | 
|---|
|  | 480 | lua_pushstring(L,"__add"); | 
|---|
|  | 481 | lua_pushcfunction(L,class_add_event); | 
|---|
|  | 482 | lua_rawset(L,-3); | 
|---|
|  | 483 | lua_pushstring(L,"__sub"); | 
|---|
|  | 484 | lua_pushcfunction(L,class_sub_event); | 
|---|
|  | 485 | lua_rawset(L,-3); | 
|---|
|  | 486 | lua_pushstring(L,"__mul"); | 
|---|
|  | 487 | lua_pushcfunction(L,class_mul_event); | 
|---|
|  | 488 | lua_rawset(L,-3); | 
|---|
|  | 489 | lua_pushstring(L,"__div"); | 
|---|
|  | 490 | lua_pushcfunction(L,class_div_event); | 
|---|
|  | 491 | lua_rawset(L,-3); | 
|---|
|  | 492 |  | 
|---|
|  | 493 | lua_pushstring(L,"__lt"); | 
|---|
|  | 494 | lua_pushcfunction(L,class_lt_event); | 
|---|
|  | 495 | lua_rawset(L,-3); | 
|---|
|  | 496 | lua_pushstring(L,"__le"); | 
|---|
|  | 497 | lua_pushcfunction(L,class_le_event); | 
|---|
|  | 498 | lua_rawset(L,-3); | 
|---|
|  | 499 | lua_pushstring(L,"__eq"); | 
|---|
|  | 500 | lua_pushcfunction(L,class_eq_event); | 
|---|
|  | 501 | lua_rawset(L,-3); | 
|---|
|  | 502 |  | 
|---|
|  | 503 | lua_pushstring(L,"__call"); | 
|---|
|  | 504 | lua_pushcfunction(L,class_call_event); | 
|---|
|  | 505 | lua_rawset(L,-3); | 
|---|
|  | 506 |  | 
|---|
|  | 507 | lua_pushstring(L,"__gc"); | 
|---|
|  | 508 | lua_pushstring(L, "tolua_gc_event"); | 
|---|
|  | 509 | lua_rawget(L, LUA_REGISTRYINDEX); | 
|---|
|  | 510 | /*lua_pushcfunction(L,class_gc_event);*/ | 
|---|
|  | 511 | lua_rawset(L,-3); | 
|---|
|  | 512 | } | 
|---|
|  | 513 |  | 
|---|