| [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 |  | 
|---|