aboutsummaryrefslogtreecommitdiff
path: root/src/tools.c
diff options
context:
space:
mode:
authorPeter Drahoš <drahosp@gmail.com>2010-10-01 03:22:32 +0200
committerPeter Drahoš <drahosp@gmail.com>2010-10-01 03:22:32 +0200
commit89d9c98af1ac352ba4d49d660e61b0853d6e1a86 (patch)
tree15c56d2ce66b4ab147171c0f674cdb4a435ff13f /src/tools.c
downloadlanes-89d9c98af1ac352ba4d49d660e61b0853d6e1a86.tar.gz
lanes-89d9c98af1ac352ba4d49d660e61b0853d6e1a86.tar.bz2
lanes-89d9c98af1ac352ba4d49d660e61b0853d6e1a86.zip
Import to git
Diffstat (limited to 'src/tools.c')
-rw-r--r--src/tools.c1198
1 files changed, 1198 insertions, 0 deletions
diff --git a/src/tools.c b/src/tools.c
new file mode 100644
index 0000000..a2ec517
--- /dev/null
+++ b/src/tools.c
@@ -0,0 +1,1198 @@
1/*
2 * TOOLS.C Copyright (c) 2002-08, Asko Kauppi
3 *
4 * Lua tools to support Lanes.
5*/
6
7/*
8===============================================================================
9
10Copyright (C) 2002-08 Asko Kauppi <akauppi@gmail.com>
11
12Permission is hereby granted, free of charge, to any person obtaining a copy
13of this software and associated documentation files (the "Software"), to deal
14in the Software without restriction, including without limitation the rights
15to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16copies of the Software, and to permit persons to whom the Software is
17furnished to do so, subject to the following conditions:
18
19The above copyright notice and this permission notice shall be included in
20all copies or substantial portions of the Software.
21
22THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
28THE SOFTWARE.
29
30===============================================================================
31*/
32
33#include "tools.h"
34
35#include "lualib.h"
36#include "lauxlib.h"
37
38#include <stdio.h>
39#include <string.h>
40#include <ctype.h>
41#include <stdlib.h>
42
43static volatile lua_CFunction hijacked_tostring; // = NULL
44
45MUTEX_T deep_lock;
46MUTEX_T mtid_lock;
47
48/*---=== luaG_dump ===---*/
49
50void luaG_dump( lua_State* L ) {
51
52 int top= lua_gettop(L);
53 int i;
54
55 fprintf( stderr, "\n\tDEBUG STACK:\n" );
56
57 if (top==0)
58 fprintf( stderr, "\t(none)\n" );
59
60 for( i=1; i<=top; i++ ) {
61 int type= lua_type( L, i );
62
63 fprintf( stderr, "\t[%d]= (%s) ", i, lua_typename(L,type) );
64
65 // Print item contents here...
66 //
67 // Note: this requires 'tostring()' to be defined. If it is NOT,
68 // enable it for more debugging.
69 //
70 STACK_CHECK(L)
71 STACK_GROW( L, 2 )
72
73 lua_getglobal( L, "tostring" );
74 //
75 // [-1]: tostring function, or nil
76
77 if (!lua_isfunction(L,-1)) {
78 fprintf( stderr, "('tostring' not available)" );
79 } else {
80 lua_pushvalue( L, i );
81 lua_call( L, 1 /*args*/, 1 /*retvals*/ );
82
83 // Don't trust the string contents
84 //
85 fprintf( stderr, "%s", lua_tostring(L,-1) );
86 }
87 lua_pop(L,1);
88 STACK_END(L,0)
89 fprintf( stderr, "\n" );
90 }
91 fprintf( stderr, "\n" );
92}
93
94
95/*---=== luaG_openlibs ===---*/
96
97static const luaL_Reg libs[] = {
98 { LUA_LOADLIBNAME, luaopen_package },
99 { LUA_TABLIBNAME, luaopen_table },
100 { LUA_IOLIBNAME, luaopen_io },
101 { LUA_OSLIBNAME, luaopen_os },
102 { LUA_STRLIBNAME, luaopen_string },
103 { LUA_MATHLIBNAME, luaopen_math },
104 { LUA_DBLIBNAME, luaopen_debug },
105 //
106 { "base", NULL }, // ignore "base" (already acquired it)
107 { "coroutine", NULL }, // part of Lua 5.1 base package
108 { NULL, NULL }
109};
110
111static bool_t openlib( lua_State *L, const char *name, size_t len ) {
112
113 unsigned i;
114 bool_t all= strncmp( name, "*", len ) == 0;
115
116 for( i=0; libs[i].name; i++ ) {
117 if (all || (strncmp(name, libs[i].name, len) ==0)) {
118 if (libs[i].func) {
119 STACK_GROW(L,2);
120 lua_pushcfunction( L, libs[i].func );
121 lua_pushstring( L, libs[i].name );
122 lua_call( L, 1, 0 );
123 }
124 if (!all) return TRUE;
125 }
126 }
127 return all;
128}
129
130/*
131* Like 'luaL_openlibs()' but allows the set of libraries be selected
132*
133* NULL no libraries, not even base
134* "" base library only
135* "io,string" named libraries
136* "*" all libraries
137*
138* Base ("unpack", "print" etc.) is always added, unless 'libs' is NULL.
139*
140* Returns NULL for ok, position of error within 'libs' on failure.
141*/
142#define is_name_char(c) (isalpha(c) || (c)=='*')
143
144const char *luaG_openlibs( lua_State *L, const char *libs ) {
145 const char *p;
146 unsigned len;
147
148 if (!libs) return NULL; // no libs, not even 'base'
149
150 // 'lua.c' stops GC during initialization so perhaps its a good idea. :)
151 //
152 lua_gc(L, LUA_GCSTOP, 0);
153
154 // Anything causes 'base' to be taken in
155 //
156 STACK_GROW(L,2);
157 lua_pushcfunction( L, luaopen_base );
158 lua_pushliteral( L, "" );
159 lua_call( L, 1, 0 );
160
161 for( p= libs; *p; p+=len ) {
162 len=0;
163 while (*p && !is_name_char(*p)) p++; // bypass delimiters
164 while (is_name_char(p[len])) len++; // bypass name
165 if (len && (!openlib( L, p, len )))
166 break;
167 }
168 lua_gc(L, LUA_GCRESTART, 0);
169
170 return *p ? p : NULL;
171}
172
173
174
175/*---=== Deep userdata ===---*/
176
177/* The deep portion must be allocated separately of any Lua state's; it's
178* lifespan may be longer than that of the creating state.
179*/
180#define DEEP_MALLOC malloc
181#define DEEP_FREE free
182
183/*
184* 'registry[REGKEY]' is a two-way lookup table for 'idfunc's and those type's
185* metatables:
186*
187* metatable -> idfunc
188* idfunc -> metatable
189*/
190#define DEEP_LOOKUP_KEY ((void*)set_deep_lookup)
191 // any unique light userdata
192
193static void push_registry_subtable( lua_State *L, void *token );
194
195/*
196* Sets up [-1]<->[-2] two-way lookups, and ensures the lookup table exists.
197* Pops the both values off the stack.
198*/
199void set_deep_lookup( lua_State *L ) {
200
201 STACK_GROW(L,3);
202
203 STACK_CHECK(L)
204#if 1
205 push_registry_subtable( L, DEEP_LOOKUP_KEY );
206#else
207 /* ..to be removed.. */
208 lua_pushlightuserdata( L, DEEP_LOOKUP_KEY );
209 lua_rawget( L, LUA_REGISTRYINDEX );
210
211 if (lua_isnil(L,-1)) {
212 // First time here; let's make the lookup
213 //
214 lua_pop(L,1);
215
216 lua_newtable(L);
217 lua_pushlightuserdata( L, DEEP_LOOKUP_KEY );
218 lua_pushvalue(L,-2);
219 //
220 // [-3]: {} (2nd ref)
221 // [-2]: DEEP_LOOKUP_KEY
222 // [-1]: {}
223
224 lua_rawset( L, LUA_REGISTRYINDEX );
225 //
226 // [-1]: lookup table (empty)
227 }
228#endif
229 STACK_MID(L,1)
230
231 lua_insert(L,-3);
232
233 // [-3]: lookup table
234 // [-2]: A
235 // [-1]: B
236
237 lua_pushvalue( L,-1 ); // B
238 lua_pushvalue( L,-3 ); // A
239 lua_rawset( L, -5 ); // B->A
240 lua_rawset( L, -3 ); // A->B
241 lua_pop( L,1 );
242
243 STACK_END(L,-2)
244}
245
246/*
247* Pops the key (metatable or idfunc) off the stack, and replaces with the
248* deep lookup value (idfunc/metatable/nil).
249*/
250void get_deep_lookup( lua_State *L ) {
251
252 STACK_GROW(L,1);
253
254 STACK_CHECK(L)
255 lua_pushlightuserdata( L, DEEP_LOOKUP_KEY );
256 lua_rawget( L, LUA_REGISTRYINDEX );
257
258 if (!lua_isnil(L,-1)) {
259 // [-2]: key (metatable or idfunc)
260 // [-1]: lookup table
261
262 lua_insert( L, -2 );
263 lua_rawget( L, -2 );
264
265 // [-2]: lookup table
266 // [-1]: value (metatable / idfunc / nil)
267 }
268 lua_remove(L,-2);
269 // remove lookup, or unused key
270 STACK_END(L,0)
271}
272
273/*
274* Return the registered ID function for 'index' (deep userdata proxy),
275* or NULL if 'index' is not a deep userdata proxy.
276*/
277static
278lua_CFunction get_idfunc( lua_State *L, int index ) {
279 lua_CFunction ret;
280
281 index= STACK_ABS(L,index);
282
283 STACK_GROW(L,1);
284
285 STACK_CHECK(L)
286 if (!lua_getmetatable( L, index ))
287 return NULL; // no metatable
288
289 // [-1]: metatable of [index]
290
291 get_deep_lookup(L);
292 //
293 // [-1]: idfunc/nil
294
295 ret= lua_tocfunction(L,-1);
296 lua_pop(L,1);
297 STACK_END(L,0)
298 return ret;
299}
300
301
302/*
303* void= mt.__gc( proxy_ud )
304*
305* End of life for a proxy object; reduce the deep reference count and clean
306* it up if reaches 0.
307*/
308static
309int deep_userdata_gc( lua_State *L ) {
310 DEEP_PRELUDE **proxy= (DEEP_PRELUDE**)lua_touserdata( L, 1 );
311 DEEP_PRELUDE *p= *proxy;
312 int v;
313
314 *proxy= 0; // make sure we don't use it any more
315
316 MUTEX_LOCK( &deep_lock );
317 v= --(p->refcount);
318 MUTEX_UNLOCK( &deep_lock );
319
320 if (v==0) {
321 int pushed;
322
323 // Call 'idfunc( "delete", deep_ptr )' to make deep cleanup
324 //
325 lua_CFunction idfunc= get_idfunc(L,1);
326 ASSERT_L(idfunc);
327
328 lua_settop(L,0); // clean stack so we can call 'idfunc' directly
329
330 // void= idfunc( "delete", lightuserdata )
331 //
332 lua_pushliteral( L, "delete" );
333 lua_pushlightuserdata( L, p->deep );
334 pushed= idfunc(L);
335
336 if (pushed)
337 luaL_error( L, "Bad idfunc on \"delete\": returned something" );
338
339 DEEP_FREE( (void*)p );
340 }
341 return 0;
342}
343
344
345/*
346* Push a proxy userdata on the stack.
347*
348* Initializes necessary structures if it's the first time 'idfunc' is being
349* used in this Lua state (metatable, registring it). Otherwise, increments the
350* reference count.
351*/
352void luaG_push_proxy( lua_State *L, lua_CFunction idfunc, DEEP_PRELUDE *prelude ) {
353 DEEP_PRELUDE **proxy;
354
355 MUTEX_LOCK( &deep_lock );
356 ++(prelude->refcount); // one more proxy pointing to this deep data
357 MUTEX_UNLOCK( &deep_lock );
358
359 STACK_GROW(L,4);
360
361 STACK_CHECK(L)
362
363 proxy= lua_newuserdata( L, sizeof( DEEP_PRELUDE* ) );
364 ASSERT_L(proxy);
365 *proxy= prelude;
366
367 // Get/create metatable for 'idfunc' (in this state)
368 //
369 lua_pushcfunction( L, idfunc ); // key
370 get_deep_lookup(L);
371 //
372 // [-2]: proxy
373 // [-1]: metatable / nil
374
375 if (lua_isnil(L,-1)) {
376 // No metatable yet; make one and register it
377 //
378 lua_pop(L,1);
379
380 // tbl= idfunc( "metatable" )
381 //
382 lua_pushcfunction( L, idfunc );
383 lua_pushliteral( L, "metatable" );
384 lua_call( L, 1 /*args*/, 1 /*results*/ );
385 //
386 // [-2]: proxy
387 // [-1]: metatable (returned by 'idfunc')
388
389 if (!lua_istable(L,-1))
390 luaL_error( L, "Bad idfunc on \"metatable\": did not return one" );
391
392 // Add '__gc' method
393 //
394 lua_pushcfunction( L, deep_userdata_gc );
395 lua_setfield( L, -2, "__gc" );
396
397 // Memorize for later rounds
398 //
399 lua_pushvalue( L,-1 );
400 lua_pushcfunction( L, idfunc );
401 //
402 // [-4]: proxy
403 // [-3]: metatable (2nd ref)
404 // [-2]: metatable
405 // [-1]: idfunc
406
407 set_deep_lookup(L);
408 }
409 STACK_MID(L,2)
410 ASSERT_L( lua_isuserdata(L,-2) );
411 ASSERT_L( lua_istable(L,-1) );
412
413 // [-2]: proxy userdata
414 // [-1]: metatable to use
415
416 lua_setmetatable( L, -2 );
417
418 STACK_END(L,1)
419 // [-1]: proxy userdata
420}
421
422
423/*
424* Create a deep userdata
425*
426* proxy_ud= deep_userdata( idfunc [, ...] )
427*
428* Creates a deep userdata entry of the type defined by 'idfunc'.
429* Other parameters are passed on to the 'idfunc' "new" invocation.
430*
431* 'idfunc' must fulfill the following features:
432*
433* lightuserdata= idfunc( "new" [, ...] ) -- creates a new deep data instance
434* void= idfunc( "delete", lightuserdata ) -- releases a deep data instance
435* tbl= idfunc( "metatable" ) -- gives metatable for userdata proxies
436*
437* Reference counting and true userdata proxying are taken care of for the
438* actual data type.
439*
440* Types using the deep userdata system (and only those!) can be passed between
441* separate Lua states via 'luaG_inter_move()'.
442*
443* Returns: 'proxy' userdata for accessing the deep data via 'luaG_todeep()'
444*/
445int luaG_deep_userdata( lua_State *L ) {
446 lua_CFunction idfunc= lua_tocfunction( L,1 );
447 int pushed;
448
449 DEEP_PRELUDE *prelude= DEEP_MALLOC( sizeof(DEEP_PRELUDE) );
450 ASSERT_L(prelude);
451
452 prelude->refcount= 0; // 'luaG_push_proxy' will lift it to 1
453
454 STACK_GROW(L,1);
455 STACK_CHECK(L)
456
457 // Replace 'idfunc' with "new" in the stack (keep possible other params)
458 //
459 lua_remove(L,1);
460 lua_pushliteral( L, "new" );
461 lua_insert(L,1);
462
463 // lightuserdata= idfunc( "new" [, ...] )
464 //
465 pushed= idfunc(L);
466
467 if ((pushed!=1) || lua_type(L,-1) != LUA_TLIGHTUSERDATA)
468 luaL_error( L, "Bad idfunc on \"new\": did not return light userdata" );
469
470 prelude->deep= lua_touserdata(L,-1);
471 ASSERT_L(prelude->deep);
472
473 lua_pop(L,1); // pop deep data
474
475 luaG_push_proxy( L, idfunc, prelude );
476 //
477 // [-1]: proxy userdata
478
479 STACK_END(L,1)
480 return 1;
481}
482
483
484/*
485* Access deep userdata through a proxy.
486*
487* Reference count is not changed, and access to the deep userdata is not
488* serialized. It is the module's responsibility to prevent conflicting usage.
489*/
490void *luaG_todeep( lua_State *L, lua_CFunction idfunc, int index ) {
491 DEEP_PRELUDE **proxy;
492
493 STACK_CHECK(L)
494 if (get_idfunc(L,index) != idfunc)
495 return NULL; // no metatable, or wrong kind
496
497 proxy= (DEEP_PRELUDE**)lua_touserdata( L, index );
498 STACK_END(L,0)
499
500 return (*proxy)->deep;
501}
502
503
504/*
505* Copy deep userdata between two separate Lua states.
506*
507* Returns:
508* the id function of the copied value, or NULL for non-deep userdata
509* (not copied)
510*/
511static
512lua_CFunction luaG_copydeep( lua_State *L, lua_State *L2, int index ) {
513 DEEP_PRELUDE **proxy;
514 DEEP_PRELUDE *p;
515
516 lua_CFunction idfunc;
517
518 idfunc= get_idfunc( L, index );
519 if (!idfunc) return NULL; // not a deep userdata
520
521 // Increment reference count
522 //
523 proxy= (DEEP_PRELUDE**)lua_touserdata( L, index );
524 p= *proxy;
525
526 luaG_push_proxy( L2, idfunc, p );
527 //
528 // L2 [-1]: proxy userdata
529
530 return idfunc;
531}
532
533
534
535/*---=== Inter-state copying ===---*/
536
537/*-- Metatable copying --*/
538
539/*
540 * 'reg[ REG_MT_KNOWN ]'= {
541 * [ table ]= id_uint,
542 * ...
543 * [ id_uint ]= table,
544 * ...
545 * }
546 */
547
548/*
549* Push a registry subtable (keyed by unique 'token') onto the stack.
550* If the subtable does not exist, it is created and chained.
551*/
552static
553void push_registry_subtable( lua_State *L, void *token ) {
554
555 STACK_GROW(L,3);
556
557 STACK_CHECK(L)
558
559 lua_pushlightuserdata( L, token );
560 lua_rawget( L, LUA_REGISTRYINDEX );
561 //
562 // [-1]: nil/subtable
563
564 if (lua_isnil(L,-1)) {
565 lua_pop(L,1);
566 lua_newtable(L); // value
567 lua_pushlightuserdata( L, token ); // key
568 lua_pushvalue(L,-2);
569 //
570 // [-3]: value (2nd ref)
571 // [-2]: key
572 // [-1]: value
573
574 lua_rawset( L, LUA_REGISTRYINDEX );
575 }
576 STACK_END(L,1)
577
578 ASSERT_L( lua_istable(L,-1) );
579}
580
581#define REG_MTID ( (void*) get_mt_id )
582
583/*
584* Get a unique ID for metatable at [i].
585*/
586static
587uint_t get_mt_id( lua_State *L, int i ) {
588 static uint_t last_id= 0;
589 uint_t id;
590
591 i= STACK_ABS(L,i);
592
593 STACK_GROW(L,3);
594
595 STACK_CHECK(L)
596 push_registry_subtable( L, REG_MTID );
597 lua_pushvalue(L, i);
598 lua_rawget( L, -2 );
599 //
600 // [-2]: reg[REG_MTID]
601 // [-1]: nil/uint
602
603 id= lua_tointeger(L,-1); // 0 for nil
604 lua_pop(L,1);
605 STACK_MID(L,1)
606
607 if (id==0) {
608 MUTEX_LOCK( &mtid_lock );
609 id= ++last_id;
610 MUTEX_UNLOCK( &mtid_lock );
611
612 /* Create two-way references: id_uint <-> table
613 */
614 lua_pushvalue(L,i);
615 lua_pushinteger(L,id);
616 lua_rawset( L, -3 );
617
618 lua_pushinteger(L,id);
619 lua_pushvalue(L,i);
620 lua_rawset( L, -3 );
621 }
622 lua_pop(L,1); // remove 'reg[REG_MTID]' reference
623
624 STACK_END(L,0)
625
626 return id;
627}
628
629
630static int buf_writer( lua_State *L, const void* b, size_t n, void* B ) {
631 (void)L;
632 luaL_addlstring((luaL_Buffer*) B, (const char *)b, n);
633 return 0;
634}
635
636
637/*
638 * Check if we've already copied the same table from 'L', and
639 * reuse the old copy. This allows table upvalues shared by multiple
640 * local functions to point to the same table, also in the target.
641 *
642 * Always pushes a table to 'L2'.
643 *
644 * Returns TRUE if the table was cached (no need to fill it!); FALSE if
645 * it's a virgin.
646 */
647static
648bool_t push_cached_table( lua_State *L2, uint_t L2_cache_i, lua_State *L, uint_t i ) {
649 bool_t ret;
650
651 ASSERT_L( hijacked_tostring );
652 ASSERT_L( L2_cache_i != 0 );
653
654 STACK_GROW(L,2);
655 STACK_GROW(L2,3);
656
657 // Create an identity string for table at [i]; it should stay unique at
658 // least during copying of the data (then we can clear the caches).
659 //
660 STACK_CHECK(L)
661 lua_pushcfunction( L, hijacked_tostring );
662 lua_pushvalue( L, i );
663 lua_call( L, 1 /*args*/, 1 /*retvals*/ );
664 //
665 // [-1]: "table: 0x...."
666
667 STACK_END(L,1)
668 ASSERT_L( lua_type(L,-1) == LUA_TSTRING );
669
670 // L2_cache[id_str]= [{...}]
671 //
672 STACK_CHECK(L2)
673
674 // We don't need to use the from state ('L') in ID since the life span
675 // is only for the duration of a copy (both states are locked).
676 //
677 lua_pushstring( L2, lua_tostring(L,-1) );
678 lua_pop(L,1); // remove the 'tostring(tbl)' value (in L!)
679
680//fprintf( stderr, "<< ID: %s >>\n", lua_tostring(L2,-1) );
681
682 lua_pushvalue( L2, -1 );
683 lua_rawget( L2, L2_cache_i );
684 //
685 // [-2]: identity string ("table: 0x...")
686 // [-1]: table|nil
687
688 if (lua_isnil(L2,-1)) {
689 lua_pop(L2,1);
690 lua_newtable(L2);
691 lua_pushvalue(L2,-1);
692 lua_insert(L2,-3);
693 //
694 // [-3]: new table (2nd ref)
695 // [-2]: identity string
696 // [-1]: new table
697
698 lua_rawset(L2, L2_cache_i);
699 //
700 // [-1]: new table (tied to 'L2_cache' table')
701
702 ret= FALSE; // brand new
703
704 } else {
705 lua_remove(L2,-2);
706 ret= TRUE; // from cache
707 }
708 STACK_END(L2,1)
709 //
710 // L2 [-1]: table to use as destination
711
712 ASSERT_L( lua_istable(L2,-1) );
713 return ret;
714}
715
716
717/*
718 * Check if we've already copied the same function from 'L', and reuse the old
719 * copy.
720 *
721 * Always pushes a function to 'L2'.
722 */
723static void inter_copy_func( lua_State *L2, uint_t L2_cache_i, lua_State *L, uint_t i );
724
725static
726void push_cached_func( lua_State *L2, uint_t L2_cache_i, lua_State *L, uint_t i ) {
727 // TBD: Merge this and same code for tables
728
729 ASSERT_L( hijacked_tostring );
730 ASSERT_L( L2_cache_i != 0 );
731
732 STACK_GROW(L,2);
733 STACK_GROW(L2,3);
734
735 STACK_CHECK(L)
736 lua_pushcfunction( L, hijacked_tostring );
737 lua_pushvalue( L, i );
738 lua_call( L, 1 /*args*/, 1 /*retvals*/ );
739 //
740 // [-1]: "function: 0x...."
741
742 STACK_END(L,1)
743 ASSERT_L( lua_type(L,-1) == LUA_TSTRING );
744
745 // L2_cache[id_str]= function
746 //
747 STACK_CHECK(L2)
748
749 // We don't need to use the from state ('L') in ID since the life span
750 // is only for the duration of a copy (both states are locked).
751 //
752 lua_pushstring( L2, lua_tostring(L,-1) );
753 lua_pop(L,1); // remove the 'tostring(tbl)' value (in L!)
754
755//fprintf( stderr, "<< ID: %s >>\n", lua_tostring(L2,-1) );
756
757 lua_pushvalue( L2, -1 );
758 lua_rawget( L2, L2_cache_i );
759 //
760 // [-2]: identity string ("function: 0x...")
761 // [-1]: function|nil|true (true means: we're working on it; recursive)
762
763 if (lua_isnil(L2,-1)) {
764 lua_pop(L2,1);
765
766 // Set to 'true' for the duration of creation; need to find self-references
767 // via upvalues
768 //
769 lua_pushboolean(L2,TRUE);
770 lua_setfield( L2, L2_cache_i, lua_tostring(L2,-2) );
771
772 inter_copy_func( L2, L2_cache_i, L, i ); // pushes a copy of the func
773
774 lua_pushvalue(L2,-1);
775 lua_insert(L2,-3);
776 //
777 // [-3]: function (2nd ref)
778 // [-2]: identity string
779 // [-1]: function
780
781 lua_rawset(L2,L2_cache_i);
782 //
783 // [-1]: function (tied to 'L2_cache' table')
784
785 } else if (lua_isboolean(L2,-1)) {
786 // Loop in preparing upvalues; either direct or via a table
787 //
788 // Note: This excludes the case where a function directly addresses
789 // itself as an upvalue (recursive lane creation).
790 //
791 luaL_error( L, "Recursive use of upvalues; cannot copy the function" );
792
793 } else {
794 lua_remove(L2,-2);
795 }
796 STACK_END(L2,1)
797 //
798 // L2 [-1]: function
799
800 ASSERT_L( lua_isfunction(L2,-1) );
801}
802
803
804/*
805* Copy a function over, which has not been found in the cache.
806*/
807enum e_vt {
808 VT_NORMAL, VT_KEY, VT_METATABLE
809};
810static bool_t inter_copy_one_( lua_State *L2, uint_t L2_cache_i, lua_State *L, uint_t i, enum e_vt value_type );
811
812static void inter_copy_func( lua_State *L2, uint_t L2_cache_i, lua_State *L, uint_t i ) {
813
814 lua_CFunction cfunc= lua_tocfunction( L,i );
815 unsigned n;
816
817 ASSERT_L( L2_cache_i != 0 );
818
819 STACK_GROW(L,2);
820
821 STACK_CHECK(L)
822 if (!cfunc) { // Lua function
823 luaL_Buffer b;
824 const char *s;
825 size_t sz;
826 int tmp;
827 const char *name= NULL;
828
829#if 0
830 // "To get information about a function you push it onto the
831 // stack and start the what string with the character '>'."
832 //
833 { lua_Debug ar;
834 lua_pushvalue( L, i );
835 lua_getinfo(L, ">n", &ar); // fills 'name' and 'namewhat', pops function
836 name= ar.namewhat;
837
838 fprintf( stderr, "NAME: %s\n", name ); // just gives NULL
839 }
840#endif
841 // 'lua_dump()' needs the function at top of stack
842 //
843 if (i!=-1) lua_pushvalue( L, i );
844
845 luaL_buffinit(L,&b);
846 tmp= lua_dump(L, buf_writer, &b);
847 ASSERT_L(tmp==0);
848 //
849 // "value returned is the error code returned by the last call
850 // to the writer" (and we only return 0)
851
852 luaL_pushresult(&b); // pushes dumped string on 'L'
853 s= lua_tolstring(L,-1,&sz);
854 ASSERT_L( s && sz );
855
856 if (i!=-1) lua_remove( L, -2 );
857
858 // Note: Line numbers seem to be taken precisely from the
859 // original function. 'name' is not used since the chunk
860 // is precompiled (it seems...).
861 //
862 // TBD: Can we get the function's original name through, as well?
863 //
864 if (luaL_loadbuffer(L2, s, sz, name) != 0) {
865 // chunk is precompiled so only LUA_ERRMEM can happen
866 // "Otherwise, it pushes an error message"
867 //
868 STACK_GROW( L,1 );
869 luaL_error( L, "%s", lua_tostring(L2,-1) );
870 }
871 lua_pop(L,1); // remove the dumped string
872 STACK_MID(L,0)
873 }
874
875 /* push over any upvalues; references to this function will come from
876 * cache so we don't end up in eternal loop.
877 */
878 for( n=0; lua_getupvalue( L, i, 1+n ) != NULL; n++ ) {
879 if ((!cfunc) && lua_equal(L,i,-1)) {
880 /* Lua closure that has a (recursive) upvalue to itself
881 */
882 lua_pushvalue( L2, -((int)n)-1 );
883 } else {
884 if (!inter_copy_one_( L2, L2_cache_i, L, lua_gettop(L), VT_NORMAL ))
885 luaL_error( L, "Cannot copy upvalue type '%s'", luaG_typename(L,-1) );
886 }
887 lua_pop(L,1);
888 }
889 // L2: function + 'n' upvalues (>=0)
890
891 STACK_MID(L,0)
892
893 if (cfunc) {
894 lua_pushcclosure( L2, cfunc, n ); // eats up upvalues
895 } else {
896 // Set upvalues (originally set to 'nil' by 'lua_load')
897 //
898 int func_index= lua_gettop(L2)-n;
899
900 for( ; n>0; n-- ) {
901 const char *rc= lua_setupvalue( L2, func_index, n );
902 //
903 // "assigns the value at the top of the stack to the upvalue and returns its name.
904 // It also pops the value from the stack."
905
906 ASSERT_L(rc); // not having enough slots?
907 }
908 }
909 STACK_END(L,0)
910}
911
912
913/*
914* Copies a value from 'L' state (at index 'i') to 'L2' state. Does not remove
915* the original value.
916*
917* NOTE: Both the states must be solely in the current OS thread's posession.
918*
919* 'i' is an absolute index (no -1, ...)
920*
921* Returns TRUE if value was pushed, FALSE if its type is non-supported.
922*/
923static bool_t inter_copy_one_( lua_State *L2, uint_t L2_cache_i, lua_State *L, uint_t i, enum e_vt vt )
924{
925 bool_t ret= TRUE;
926
927 STACK_GROW( L2, 1 );
928
929 STACK_CHECK(L2)
930
931 switch ( lua_type(L,i) ) {
932 /* Basic types allowed both as values, and as table keys */
933
934 case LUA_TBOOLEAN:
935 lua_pushboolean( L2, lua_toboolean(L, i) );
936 break;
937
938 case LUA_TNUMBER:
939 /* LNUM patch support (keeping integer accuracy) */
940#ifdef LUA_LNUM
941 if (lua_isinteger(L,i)) {
942 lua_pushinteger( L2, lua_tointeger(L, i) );
943 break;
944 }
945#endif
946 lua_pushnumber( L2, lua_tonumber(L, i) );
947 break;
948
949 case LUA_TSTRING: {
950 size_t len; const char *s = lua_tolstring( L, i, &len );
951 lua_pushlstring( L2, s, len );
952 } break;
953
954 case LUA_TLIGHTUSERDATA:
955 lua_pushlightuserdata( L2, lua_touserdata(L, i) );
956 break;
957
958 /* The following types are not allowed as table keys */
959
960 case LUA_TUSERDATA: if (vt==VT_KEY) { ret=FALSE; break; }
961 /* Allow only deep userdata entities to be copied across
962 */
963 if (!luaG_copydeep( L, L2, i )) {
964 // Cannot copy it full; copy as light userdata
965 //
966 lua_pushlightuserdata( L2, lua_touserdata(L, i) );
967 } break;
968
969 case LUA_TNIL: if (vt==VT_KEY) { ret=FALSE; break; }
970 lua_pushnil(L2);
971 break;
972
973 case LUA_TFUNCTION: if (vt==VT_KEY) { ret=FALSE; break; } {
974 /*
975 * Passing C functions is risky; if they refer to LUA_ENVIRONINDEX
976 * and/or LUA_REGISTRYINDEX they might work unintended (not work)
977 * at the target.
978 *
979 * On the other hand, NOT copying them causes many self tests not
980 * to work (timer, hangtest, ...)
981 *
982 * The trouble is, we cannot KNOW if the function at hand is safe
983 * or not. We cannot study it's behaviour. We could trust the user,
984 * but they might not even know they're sending lua_CFunction over
985 * (as upvalues etc.).
986 */
987#if 0
988 if (lua_iscfunction(L,i))
989 luaL_error( L, "Copying lua_CFunction between Lua states is risky, and currently disabled." );
990#endif
991 STACK_CHECK(L2)
992 push_cached_func( L2, L2_cache_i, L, i );
993 ASSERT_L( lua_isfunction(L2,-1) );
994 STACK_END(L2,1)
995 } break;
996
997 case LUA_TTABLE: if (vt==VT_KEY) { ret=FALSE; break; } {
998
999 STACK_CHECK(L)
1000 STACK_CHECK(L2)
1001
1002 /* Check if we've already copied the same table from 'L' (during this transmission), and
1003 * reuse the old copy. This allows table upvalues shared by multiple
1004 * local functions to point to the same table, also in the target.
1005 * Also, this takes care of cyclic tables and multiple references
1006 * to the same subtable.
1007 *
1008 * Note: Even metatables need to go through this test; to detect
1009 * loops s.a. those in required module tables (getmetatable(lanes).lanes == lanes)
1010 */
1011 if (push_cached_table( L2, L2_cache_i, L, i )) {
1012 ASSERT_L( lua_istable(L2, -1) ); // from cache
1013 break;
1014 }
1015 ASSERT_L( lua_istable(L2,-1) );
1016
1017 STACK_GROW( L, 2 );
1018 STACK_GROW( L2, 2 );
1019
1020 lua_pushnil(L); // start iteration
1021 while( lua_next( L, i ) ) {
1022 uint_t val_i= lua_gettop(L);
1023 uint_t key_i= val_i-1;
1024
1025 /* Only basic key types are copied over; others ignored
1026 */
1027 if (inter_copy_one_( L2, 0 /*key*/, L, key_i, VT_KEY )) {
1028 /*
1029 * Contents of metatables are copied with cache checking;
1030 * important to detect loops.
1031 */
1032 if (inter_copy_one_( L2, L2_cache_i, L, val_i, VT_NORMAL )) {
1033 ASSERT_L( lua_istable(L2,-3) );
1034 lua_rawset( L2, -3 ); // add to table (pops key & val)
1035 } else {
1036 luaL_error( L, "Unable to copy over type '%s' (in %s)",
1037 luaG_typename(L,val_i),
1038 vt==VT_NORMAL ? "table":"metatable" );
1039 }
1040 }
1041 lua_pop( L, 1 ); // pop value (next round)
1042 }
1043 STACK_MID(L,0)
1044 STACK_MID(L2,1)
1045
1046 /* Metatables are expected to be immutable, and copied only once.
1047 */
1048 if (lua_getmetatable( L, i )) {
1049 //
1050 // L [-1]: metatable
1051
1052 uint_t mt_id= get_mt_id( L, -1 ); // Unique id for the metatable
1053
1054 STACK_GROW(L2,4);
1055
1056 push_registry_subtable( L2, REG_MTID );
1057 STACK_MID(L2,2);
1058 lua_pushinteger( L2, mt_id );
1059 lua_rawget( L2, -2 );
1060 //
1061 // L2 ([-3]: copied table)
1062 // [-2]: reg[REG_MTID]
1063 // [-1]: nil/metatable pre-known in L2
1064
1065 STACK_MID(L2,3);
1066
1067 if (lua_isnil(L2,-1)) { /* L2 did not know the metatable */
1068 lua_pop(L2,1);
1069 STACK_MID(L2,2);
1070ASSERT_L( lua_istable(L,-1) );
1071 if (inter_copy_one_( L2, L2_cache_i /*for function cacheing*/, L, lua_gettop(L) /*[-1]*/, VT_METATABLE )) {
1072 //
1073 // L2 ([-3]: copied table)
1074 // [-2]: reg[REG_MTID]
1075 // [-1]: metatable (copied from L)
1076
1077 STACK_MID(L2,3);
1078 // mt_id -> metatable
1079 //
1080 lua_pushinteger(L2,mt_id);
1081 lua_pushvalue(L2,-2);
1082 lua_rawset(L2,-4);
1083
1084 // metatable -> mt_id
1085 //
1086 lua_pushvalue(L2,-1);
1087 lua_pushinteger(L2,mt_id);
1088 lua_rawset(L2,-4);
1089
1090 STACK_MID(L2,3);
1091 } else {
1092 luaL_error( L, "Error copying a metatable" );
1093 }
1094 STACK_MID(L2,3);
1095 }
1096 // L2 ([-3]: copied table)
1097 // [-2]: reg[REG_MTID]
1098 // [-1]: metatable (pre-known or copied from L)
1099
1100 lua_remove(L2,-2); // take away 'reg[REG_MTID]'
1101 //
1102 // L2: ([-2]: copied table)
1103 // [-1]: metatable for that table
1104
1105 lua_setmetatable( L2, -2 );
1106
1107 // L2: [-1]: copied table (with metatable set if source had it)
1108
1109 lua_pop(L,1); // remove source metatable (L, not L2!)
1110 }
1111 STACK_END(L2,1)
1112 STACK_END(L,0)
1113 } break;
1114
1115 /* The following types cannot be copied */
1116
1117 case LUA_TTHREAD:
1118 ret=FALSE; break;
1119 }
1120
1121 STACK_END(L2, ret? 1:0)
1122
1123 return ret;
1124}
1125
1126
1127/*
1128* Akin to 'lua_xmove' but copies values between _any_ Lua states.
1129*
1130* NOTE: Both the states must be solely in the current OS thread's posession.
1131*
1132* Note: Parameters are in this order ('L' = from first) to be same as 'lua_xmove'.
1133*/
1134void luaG_inter_copy( lua_State* L, lua_State *L2, uint_t n )
1135{
1136 uint_t top_L= lua_gettop(L);
1137 uint_t top_L2= lua_gettop(L2);
1138 uint_t i;
1139
1140 /* steal Lua library's 'luaB_tostring()' from the first call. Other calls
1141 * don't have to have access to it.
1142 *
1143 * Note: multiple threads won't come here at once; this function will
1144 * be called before there can be multiple threads (no locking needed).
1145 */
1146 if (!hijacked_tostring) {
1147 STACK_GROW( L,1 );
1148
1149 STACK_CHECK(L)
1150 lua_getglobal( L, "tostring" );
1151 //
1152 // [-1]: function|nil
1153
1154 hijacked_tostring= lua_tocfunction( L, -1 );
1155 lua_pop(L,1);
1156 STACK_END(L,0)
1157
1158 if (!hijacked_tostring) {
1159 luaL_error( L, "Need to see 'tostring()' once" );
1160 }
1161 }
1162
1163 if (n > top_L)
1164 luaL_error( L, "Not enough values: %d < %d", top_L, n );
1165
1166 STACK_GROW( L2, n+1 );
1167
1168 /*
1169 * Make a cache table for the duration of this copy. Collects tables and
1170 * function entries, avoiding the same entries to be passed on as multiple
1171 * copies. ESSENTIAL i.e. for handling upvalue tables in the right manner!
1172 */
1173 lua_newtable(L2);
1174
1175 for (i=top_L-n+1; i <= top_L; i++) {
1176 if (!inter_copy_one_( L2, top_L2+1, L, i, VT_NORMAL )) {
1177
1178 luaL_error( L, "Cannot copy type: %s", luaG_typename(L,i) );
1179 }
1180 }
1181
1182 /*
1183 * Remove the cache table. Persistant caching would cause i.e. multiple
1184 * messages passed in the same table to use the same table also in receiving
1185 * end.
1186 */
1187 lua_remove( L2, top_L2+1 );
1188
1189 ASSERT_L( (uint_t)lua_gettop(L) == top_L );
1190 ASSERT_L( (uint_t)lua_gettop(L2) == top_L2+n );
1191}
1192
1193
1194void luaG_inter_move( lua_State* L, lua_State *L2, uint_t n )
1195{
1196 luaG_inter_copy( L, L2, n );
1197 lua_pop( L,(int)n );
1198}