~ubuntu-branches/debian/squeeze/freeciv/squeeze

« back to all changes in this revision

Viewing changes to dependencies/toluaxx/src/lib/tolua_event.c

  • Committer: Bazaar Package Importer
  • Author(s): Clint Adams, Karl Goetz, Clint Adams
  • Date: 2010-02-23 22:09:02 UTC
  • mfrom: (1.2.13 upstream)
  • Revision ID: james.westby@ubuntu.com-20100223220902-kiyrmr9i4152cka5
Tags: 2.2.0-1
[ Karl Goetz ]
* Remove civserver files in /etc/ggzd/ (Closes: 523772, 517787)
* Adding ${misc:Depends} to all binary packages (lintian warnings)

[ Clint Adams ]
* New upstream version.
  - Drop data_dsc_use_bindir.diff (binary pathnames have changed).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* tolua: event functions
 
2
** Support code for Lua bindings.
 
3
** Written by Waldemar Celes
 
4
** TeCGraf/PUC-Rio
 
5
** Apr 2003
 
6
** $Id: tolua_event.c 14589 2008-04-15 21:40:53Z cazfi $
 
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 "toluaxx.h"
 
18
#include "tolua_event.h"
 
19
 
 
20
/* Store at ubox
 
21
 * It stores, creating the corresponding table if needed,
 
22
 * the pair key/value in the corresponding ubox table
 
23
 */
 
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 */
 
32
  }
 
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 */
 
37
#else
 
38
  /* stack: key value (to be stored) */
 
39
  lua_pushstring(L,"tolua_peers");
 
40
  lua_rawget(L,LUA_REGISTRYINDEX);        /* stack: k v ubox */
 
41
  lua_pushvalue(L,lo);
 
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 */
 
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
  lua_pushstring(L,".get");
 
61
  lua_rawget(L,-3);
 
62
  if (lua_istable(L,-1)){
 
63
    lua_pushvalue(L,2);  /* key */
 
64
    lua_rawget(L,-2);
 
65
    if (lua_iscfunction(L,-1)){
 
66
      lua_call(L,0,1);
 
67
      return 1;
 
68
    }else if (lua_istable(L,-1))
 
69
      return 1;
 
70
  }
 
71
  /* call old index meta event */
 
72
  if (lua_getmetatable(L,1)){
 
73
    lua_pushstring(L,"__index");
 
74
    lua_rawget(L,-2);
 
75
    lua_pushvalue(L,1);
 
76
    lua_pushvalue(L,2);
 
77
    if (lua_isfunction(L,-1)){
 
78
      lua_call(L,2,1);
 
79
      return 1;
 
80
    }else if (lua_istable(L,-1)){
 
81
      lua_gettable(L,-3);
 
82
      return 1;
 
83
    }
 
84
  }
 
85
  lua_pushnil(L);
 
86
  return 1;
 
87
}
 
88
 
 
89
/* Module newindex function
 
90
 */
 
91
static int module_newindex_event (lua_State* L){
 
92
  lua_pushstring(L,".set");
 
93
  lua_rawget(L,-4);
 
94
  if (lua_istable(L,-1)){
 
95
    lua_pushvalue(L,2);  /* key */
 
96
    lua_rawget(L,-2);
 
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 */
 
100
      lua_call(L,2,0);
 
101
      return 0;
 
102
    }
 
103
  }
 
104
  /* call old newindex meta event */
 
105
  if (lua_getmetatable(L,1) && lua_getmetatable(L,-1)){
 
106
    lua_pushstring(L,"__newindex");
 
107
    lua_rawget(L,-2);
 
108
    if (lua_isfunction(L,-1)){
 
109
      lua_pushvalue(L,1);
 
110
      lua_pushvalue(L,2);
 
111
      lua_pushvalue(L,3);
 
112
      lua_call(L,3,0);
 
113
    }
 
114
  }
 
115
  lua_settop(L,3);
 
116
  lua_rawset(L,-3);
 
117
  return 0;
 
118
}
 
119
 
 
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.
 
123
 */
 
124
 
 
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 */
 
132
    lua_getfenv(L,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;
 
137
    };
 
138
#else
 
139
    lua_pushstring(L,"tolua_peers");
 
140
    lua_rawget(L,LUA_REGISTRYINDEX);         /* stack: obj key ubox */
 
141
    lua_pushvalue(L,1);
 
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;
 
147
    }
 
148
#endif
 
149
    lua_settop(L,2);                         /* stack: obj key */
 
150
    /* Try metatables */
 
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 */
 
155
        /* try operator[] */
 
156
        lua_pushstring(L,".geti");
 
157
        lua_rawget(L,-2);                    /* stack: obj key mt func */
 
158
        if (lua_isfunction(L,-1)) {
 
159
          lua_pushvalue(L,1);
 
160
          lua_pushvalue(L,2);
 
161
          lua_call(L,2,1);
 
162
          return 1;
 
163
        }
 
164
      }else{
 
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;
 
168
        else lua_pop(L,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)){
 
173
          lua_pushvalue(L,2);
 
174
          lua_rawget(L,-2);                 /* stack: obj key mt value */
 
175
          if (lua_iscfunction(L,-1)){
 
176
            lua_pushvalue(L,1);
 
177
            lua_pushvalue(L,2);
 
178
            lua_call(L,2,1);
 
179
            return 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 */
 
193
            return 1;
 
194
          }
 
195
        }
 
196
      }
 
197
      lua_settop(L,3);
 
198
    }
 
199
    lua_pushnil(L);
 
200
    return 1;
 
201
  }else if (t== LUA_TTABLE){
 
202
    module_index_event(L);
 
203
    return 1;
 
204
  }
 
205
  lua_pushnil(L);
 
206
  return 1;
 
207
}
 
208
 
 
209
/* Newindex function
 
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).
 
213
 */
 
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 */
 
221
        /* try operator[] */
 
222
        lua_pushstring(L,".seti");
 
223
        lua_rawget(L,-2);                      /* stack: obj key mt func */
 
224
        if (lua_isfunction(L,-1)) {
 
225
          lua_pushvalue(L,1);
 
226
          lua_pushvalue(L,2);
 
227
          lua_pushvalue(L,3);
 
228
          lua_call(L,3,0);
 
229
          return 0;
 
230
        }
 
231
      } else {
 
232
        lua_pushstring(L,".set");
 
233
        lua_rawget(L,-2);                      /* stack: t k v mt tset */
 
234
        if (lua_istable(L,-1)) {
 
235
          lua_pushvalue(L,2);
 
236
          lua_rawget(L,-2);                     /* stack: t k v mt tset func */
 
237
          if (lua_iscfunction(L,-1)) {
 
238
            lua_pushvalue(L,1);
 
239
            lua_pushvalue(L,3);
 
240
            lua_call(L,2,0);
 
241
            return 0;
 
242
          }
 
243
          lua_pop(L,1);                          /* stack: t k v mt tset */
 
244
        }
 
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 */
 
248
      }
 
249
    }
 
250
    lua_settop(L,3);                          /* stack: t k v */
 
251
    /* then, store as a new field */
 
252
    storeatubox(L,1);
 
253
  } else if (t== LUA_TTABLE) {
 
254
    module_newindex_event(L);
 
255
  }
 
256
  return 0;
 
257
}
 
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 */
 
263
    /* Try metatables */
 
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 */
 
275
        }
 
276
      }else{
 
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 */
 
308
          }
 
309
        }
 
310
      }
 
311
      lua_settop(L,3);                       /* stack: obj key mt */
 
312
    }
 
313
    /* For operator[](string) */
 
314
    lua_settop(L,2);                         /* stack: obj key */
 
315
    lua_pushvalue(L,1);                      /* stack: obj key obj */
 
316
    /* Try metatables */
 
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 */
 
332
          }
 
333
        }
 
334
      }
 
335
      lua_settop(L,3);                       /* stack: obj key mt */
 
336
    }
 
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 */
 
346
    }
 
347
#else
 
348
    lua_pushstring(L,"tolua_peers");
 
349
    lua_rawget(L,LUA_REGISTRYINDEX);         /* stack: obj key ubox */
 
350
    lua_pushvalue(L,1);
 
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;
 
356
    }
 
357
#endif
 
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);
 
363
    return 1;
 
364
  }
 
365
  lua_pushnil(L);                            /* stack: obj key mt nil */
 
366
  return 1;                                  /* stack: nil */
 
367
}
 
368
 
 
369
/* Newindex function
 
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).
 
373
 */
 
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 */
 
393
          }
 
394
          return 0;                          /* stack: no value */
 
395
        }
 
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: */
 
411
          }
 
412
          lua_pop(L,1);                      /* stack: obj key val mt tset */
 
413
        }
 
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 */
 
418
      }
 
419
    }
 
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 */
 
443
          }else{
 
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 */
 
447
            }
 
448
            return 0;                        /* stack: no value */
 
449
          }
 
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 */
 
454
        }
 
455
                                             /* stack: obj key val next_mt */
 
456
      }
 
457
    }
 
458
    lua_settop(L,3);                         /* stack: obj key val */
 
459
    /* then, store as a new field */
 
460
    storeatubox(L,1);
 
461
  } else if (t==LUA_TTABLE) {
 
462
    module_newindex_event(L);
 
463
  }
 
464
  return 0;
 
465
}
 
466
#endif
 
467
 
 
468
 
 
469
/*
 
470
 *  .... obj tab
 
471
 *    next with tab
 
472
 *  .... obj tab key val
 
473
 *    if val isn't table
 
474
 *    set to obj
 
475
 *  .... obj tab 
 
476
 *    else
 
477
 *    get from obj field with key
 
478
 *  .... obj tab key val fld
 
479
 *    swap fld and val
 
480
 *  .... obj tab key fld val
 
481
 *    recursive call this function
 
482
 *  .... obj tab key fld val
 
483
 *    remove key, fld and val
 
484
 *  .... obj tab
 
485
 *    repeat it
 
486
 */
 
487
 
 
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;
 
491
                                            /* stack: obj tab */
 
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 */
 
502
    }else{
 
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 */
 
507
    }
 
508
  }
 
509
  //DEBUG_STACK(lua_next(L,-1)!=0 end);
 
510
  return 1;                                 /* stack: obj tab */
 
511
}
 
512
 
 
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 */
 
534
      }else{
 
535
                                            /* stack: func obj <args> */
 
536
        lua_call(L,lua_gettop(L)-1,1);      /* stack: func ret */
 
537
        return 1;                           /* stack: ret */
 
538
      }
 
539
    }
 
540
  }
 
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 */
 
545
      return 0;
 
546
    }else{
 
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} */
 
562
        }
 
563
        lua_settop(L,3);                 /* stack: obj {args} mt */
 
564
      }
 
565
    }
 
566
  }
 
567
  tolua_error(L,"Attempt to call a non-callable object.",NULL);
 
568
  return 0;
 
569
};
 
570
 
 
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 */
 
583
      }
 
584
      lua_settop(L,3);                /* stack: op1 op2 mt */
 
585
    }
 
586
  }
 
587
  tolua_error(L,"Attempt to perform operation on an invalid operand",NULL);
 
588
  return 0;
 
589
}
 
590
/// +++ <<<
 
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 */
 
594
    /* Try metatables */
 
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 */
 
603
      }
 
604
      lua_settop(L,2);               /* stack: op mt */
 
605
    }
 
606
  }
 
607
  tolua_error(L,"Attempt to perform operation on an invalid operand",NULL);
 
608
  return 0;
 
609
}
 
610
/// +++ >>>
 
611
 
 
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 */
 
615
    /* Try metatables */
 
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 */
 
624
      }
 
625
      lua_settop(L,2);               /* stack: op mt */
 
626
    }
 
627
  }
 
628
  {
 
629
    void* p;
 
630
    char b[50];
 
631
    p=lua_touserdata(L,1);        /* get address pointer */
 
632
    sprintf(b,"userdata: 0x%p", p);/* print pointer */
 
633
    lua_pushstring(L,b);
 
634
    return 1;
 
635
  }
 
636
  tolua_error(L,"Attempt to perform operation .string on an invalid operand",NULL);
 
637
  return 0;
 
638
}
 
639
 
 
640
static int class_add_event (lua_State* L){
 
641
  return do_twin_operator(L,".add");
 
642
}
 
643
 
 
644
static int class_sub_event (lua_State* L){
 
645
  return do_twin_operator(L,".sub");
 
646
}
 
647
 
 
648
static int class_mul_event (lua_State* L){
 
649
  return do_twin_operator(L,".mul");
 
650
}
 
651
 
 
652
static int class_pow_event (lua_State* L){
 
653
  return do_twin_operator(L,".pow");
 
654
}
 
655
 
 
656
static int class_len_event (lua_State* L){
 
657
  return do_unary_operator(L,".len");
 
658
}
 
659
 
 
660
static int class_unm_event (lua_State* L){
 
661
  return do_unary_operator(L,".unm");
 
662
}
 
663
 
 
664
static int class_mod_event (lua_State* L){
 
665
  return do_twin_operator(L,".mod");
 
666
}
 
667
 
 
668
static int class_div_event (lua_State* L){
 
669
  return do_twin_operator(L,".div");
 
670
}
 
671
 
 
672
static int class_concat_event (lua_State* L){
 
673
  return do_twin_operator(L,".concat");
 
674
}
 
675
 
 
676
static int class_lt_event (lua_State* L){
 
677
  return do_twin_operator(L,".lt");
 
678
}
 
679
 
 
680
static int class_le_event (lua_State* L){
 
681
  return do_twin_operator(L,".le");
 
682
}
 
683
 
 
684
static int class_eq_event (lua_State* L){
 
685
  return do_twin_operator(L,".eq");
 
686
}
 
687
 
 
688
/*
 
689
static int class_gc_event (lua_State* L)
 
690
{
 
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);
 
696
        lua_rawget(L,-2);
 
697
        if (lua_isfunction(L,-1))
 
698
        {
 
699
                lua_pushvalue(L,1);
 
700
                lua_call(L,1,0);
 
701
                lua_pushlightuserdata(L,u);
 
702
                lua_pushnil(L);
 
703
                lua_rawset(L,-3);
 
704
        }
 
705
        lua_pop(L,2);
 
706
        return 0;
 
707
}
 
708
*/
 
709
TOLUA_API int class_gc_event (lua_State* L){
 
710
  void* u = *((void**)lua_touserdata(L,1));
 
711
  int top;
 
712
  /*fprintf(stderr, "collecting: looking at %p\n", u);*/
 
713
  /*
 
714
    lua_pushstring(L,"tolua_gc");
 
715
    lua_rawget(L,LUA_REGISTRYINDEX);
 
716
  */
 
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");*/
 
722
  top = lua_gettop(L);
 
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");*/
 
730
    } else {
 
731
      lua_pop(L,1);
 
732
      /*fprintf(stderr, "Using default cleanup\n");*/
 
733
      lua_pushcfunction(L,tolua_default_collect);
 
734
    }
 
735
 
 
736
    lua_pushvalue(L,1);         /* stack: gc umt mt collector u */
 
737
    lua_call(L,1,0);
 
738
    
 
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 */
 
742
  }
 
743
  lua_pop(L,3);
 
744
  return 0;
 
745
}
 
746
 
 
747
 
 
748
/* Register module events
 
749
        * It expects the metatable on the top of the stack
 
750
*/
 
751
TOLUA_API void tolua_moduleevents (lua_State* L){
 
752
  lua_pushstring(L,"__index");
 
753
  lua_pushcfunction(L,module_index_event);
 
754
  lua_rawset(L,-3);
 
755
  lua_pushstring(L,"__newindex");
 
756
  lua_pushcfunction(L,module_newindex_event);
 
757
  lua_rawset(L,-3);
 
758
}
 
759
 
 
760
/* Check if the object on the top has a module metatable
 
761
*/
 
762
TOLUA_API int tolua_ismodulemetatable (lua_State* L){
 
763
  int r = 0;
 
764
  if (lua_getmetatable(L,-1)) {
 
765
    lua_pushstring(L,"__index");
 
766
    lua_rawget(L,-2);
 
767
    r = (lua_tocfunction(L,-1) == module_index_event);
 
768
    lua_pop(L,2);
 
769
  }
 
770
  return r;
 
771
}
 
772
 
 
773
/* Register class events
 
774
        * It expects the metatable on the top of the stack
 
775
*/
 
776
TOLUA_API void tolua_classevents (lua_State* L) {
 
777
  lua_pushstring(L,"__index");
 
778
  lua_pushcfunction(L,class_index_event);
 
779
  lua_rawset(L,-3);
 
780
  lua_pushstring(L,"__newindex");
 
781
  lua_pushcfunction(L,class_newindex_event);
 
782
  lua_rawset(L,-3);
 
783
  
 
784
  lua_pushstring(L,"__add");
 
785
  lua_pushcfunction(L,class_add_event);
 
786
  lua_rawset(L,-3);
 
787
  lua_pushstring(L,"__sub");
 
788
  lua_pushcfunction(L,class_sub_event);
 
789
  lua_rawset(L,-3);
 
790
  lua_pushstring(L,"__mul");
 
791
  lua_pushcfunction(L,class_mul_event);
 
792
  lua_rawset(L,-3);
 
793
  lua_pushstring(L,"__div");
 
794
  lua_pushcfunction(L,class_div_event);
 
795
  lua_rawset(L,-3);
 
796
  // toluaxx new operators
 
797
  lua_pushstring(L,"__pow");
 
798
  lua_pushcfunction(L,class_pow_event);
 
799
  lua_rawset(L,-3);
 
800
  lua_pushstring(L,"__mod");
 
801
  lua_pushcfunction(L,class_mod_event);
 
802
  lua_rawset(L,-3);
 
803
  lua_pushstring(L,"__len");
 
804
  lua_pushcfunction(L,class_len_event);
 
805
  lua_rawset(L,-3);
 
806
  lua_pushstring(L,"__concat");
 
807
  lua_pushcfunction(L,class_concat_event);
 
808
  lua_rawset(L,-3);
 
809
  lua_pushstring(L,"__unm");
 
810
  lua_pushcfunction(L,class_unm_event);
 
811
  lua_rawset(L,-3);
 
812
  lua_pushstring(L,"__tostring");
 
813
  lua_pushcfunction(L,class_tostring_event);
 
814
  lua_rawset(L,-3);
 
815
  // end toluaxx operators
 
816
  lua_pushstring(L,"__lt");
 
817
  lua_pushcfunction(L,class_lt_event);
 
818
  lua_rawset(L,-3);
 
819
  lua_pushstring(L,"__le");
 
820
  lua_pushcfunction(L,class_le_event);
 
821
  lua_rawset(L,-3);
 
822
  lua_pushstring(L,"__eq");
 
823
  lua_pushcfunction(L,class_eq_event);
 
824
  lua_rawset(L,-3);
 
825
  
 
826
  lua_pushstring(L,"__call");
 
827
  lua_pushcfunction(L,class_call_event);
 
828
  lua_rawset(L,-3);
 
829
  
 
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);*/
 
834
  lua_rawset(L,-3);
 
835
}
 
836