Correct method arginfo for expose_function
[phplua.git] / lua.c
blobc46d6cb88beb9c526996d30fdf97150575f5753c
1 /*
2 +----------------------------------------------------------------------+
3 | LUA extension for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2007 Johannes Schlueter |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Author: Johannes Schlueter <johannes@php.net> |
16 | Marcelo Araujo <msaraujo@php.net> |
17 | Andreas Streichardt <andreas.streichardt@globalpark.com |
18 +----------------------------------------------------------------------+
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
25 #include "php.h"
26 #include "php_ini.h"
27 #include "ext/standard/info.h"
28 #include "php_lua.h"
30 #include "lua.h"
31 #include "lauxlib.h"
32 #include "lualib.h"
34 #define EXT_LUA_VERSION PHP_LUA_VERSION
36 #ifdef LUA_STACK_DEBUG
37 #define LUA_STACK_START(L) int __lua_old_top = lua_gettop(L)
38 #define LUA_STACK_END(L) \
39 if (__lua_old_top != lua_gettop(L)) { \
40 php_error_docref(NULL TSRMLS_CC, E_WARNING, "wrong stack size (%i before operation, %i now)", __lua_old_top, lua_gettop(L)); \
42 #else
43 #define LUA_STACK_START(L)
44 #define LUA_STACK_END(L)
45 #endif
47 #define LUA_POP_ZVAL(L, z) \
48 php_lua_get_zval_from_stack(L, -1, z); \
49 lua_pop(L, 1)
51 ZEND_DECLARE_MODULE_GLOBALS(lua)
53 #define getLuaZ(var) (((php_lua_object*)zend_object_store_get_object(var TSRMLS_CC))->L)
54 #define getLuaY() ((php_lua_object*)zend_object_store_get_object(getThis() TSRMLS_CC))
55 #define getLua() getLuaZ(getThis())
57 static zend_object_handlers lua_handlers;
58 static zend_class_entry *lua_ce;
60 typedef struct _php_lua_object {
61 zend_object std;
62 lua_State *L;
63 zval* callbacks;
64 long callback_count;
65 } php_lua_object;
67 static const luaL_Reg php_lualibs[] = {
68 {"base", luaopen_base},
69 {LUA_LOADLIBNAME, luaopen_package},
70 {LUA_TABLIBNAME, luaopen_table},
71 {LUA_IOLIBNAME, luaopen_io},
72 {LUA_OSLIBNAME, luaopen_os},
73 {LUA_STRLIBNAME, luaopen_string},
74 {LUA_MATHLIBNAME, luaopen_math},
75 {LUA_DBLIBNAME, luaopen_debug},
76 {NULL, NULL}
79 static void php_lua_push_zval(lua_State *L, zval *val_p TSRMLS_DC);
80 static void php_lua_write_real_property(lua_State *L,int index,zval *prop, zval *value TSRMLS_DC);
82 static void *php_lua_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { /* {{{ */
83 if (nsize == 0) {
84 if (ptr) {
85 efree(ptr);
87 return NULL;
88 } else {
89 if (ptr) {
90 return erealloc(ptr, nsize);
91 } else {
92 return emalloc(nsize);
95 } /* }}} */
98 static void php_lua_push_array(lua_State *L, zval *array TSRMLS_DC) /* {{{ */
100 zval **data;
101 HashTable *arr_hash;
102 HashPosition pointer;
103 int array_count;
104 char *key;
105 int key_len;
106 long index;
107 int hash_key;
108 char *key_copy;
110 zval *zkey;
112 arr_hash = Z_ARRVAL_P(array);
113 array_count = zend_hash_num_elements(arr_hash);
115 lua_newtable(L);
117 for(zend_hash_internal_pointer_reset_ex(arr_hash, &pointer); zend_hash_get_current_data_ex(arr_hash, (void**) &data, &pointer) == SUCCESS; zend_hash_move_forward_ex(arr_hash, &pointer))
119 hash_key=zend_hash_get_current_key_ex(arr_hash, &key, &key_len, &index, 0, &pointer);
121 if (hash_key == HASH_KEY_IS_LONG && index == 0) {
122 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Trying to push array index %ld to lua which is unsupported in lua. Element has been discarded",index);
124 else {
125 ALLOC_INIT_ZVAL(zkey);
126 if (hash_key == HASH_KEY_IS_STRING) {
127 key_copy=estrndup(key,key_len-1);
128 Z_TYPE_P(zkey)=IS_STRING;
129 Z_STRVAL_P(zkey)=key_copy;
130 Z_STRLEN_P(zkey)=key_len-1;
132 else {
133 Z_TYPE_P(zkey)=IS_LONG;
134 Z_LVAL_P(zkey)=index;
137 php_lua_write_real_property(L,-3,zkey,*data TSRMLS_CC);
138 zval_ptr_dtor(&zkey);
141 } /* }}} */
146 static void php_lua_push_zval(lua_State *L, zval *val_p TSRMLS_DC) /* {{{ */
148 /* TODO: Use proper type for lua and separate only when needed */
150 /* push into lua stack properly */
151 switch (Z_TYPE_P(val_p)) {
152 case IS_STRING:
153 lua_pushlstring(L, Z_STRVAL_P(val_p), Z_STRLEN_P(val_p));
154 break;
156 case IS_NULL:
157 lua_pushnil(L);
158 break;
160 case IS_DOUBLE:
161 lua_pushnumber(L, Z_DVAL_P(val_p));
162 break;
164 case IS_LONG:
165 lua_pushnumber(L, Z_LVAL_P(val_p));
166 break;
168 case IS_BOOL:
169 lua_pushboolean(L, Z_BVAL_P(val_p));
170 break;
172 case IS_ARRAY:
173 php_lua_push_array(L,val_p TSRMLS_CC);
174 break;
176 default:
177 php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid type `%s' supported in lua", zend_zval_type_name(val_p));
178 lua_pushnil(L);
179 break;
182 } /* }}} */
184 static int php_lua_push_apply_func(void *pDest, void *argument TSRMLS_DC) /* {{{ */
186 php_lua_push_zval((lua_State*)argument, *(zval**)pDest TSRMLS_CC);
187 return ZEND_HASH_APPLY_KEEP;
188 } /* }}} */
190 static void php_lua_get_zval_from_stack(lua_State *L, int index, zval *ret TSRMLS_DC) /* {{{ */
192 const char *value;
193 size_t value_len;
194 zval *akey,*aval;
196 switch (lua_type(L, index)) {
197 case LUA_TBOOLEAN:
198 ZVAL_BOOL(ret, lua_toboolean(L, index));
199 break;
201 case LUA_TNUMBER:
202 ZVAL_DOUBLE(ret, lua_tonumber(L, index));
203 break;
205 case LUA_TSTRING:
206 value = lua_tolstring(L, index, &value_len);
207 ZVAL_STRINGL(ret, (char*)value, value_len, 1);
208 break;
210 case LUA_TTABLE:
211 array_init(ret);
212 /* notify lua to traverse the table */
213 lua_pushnil(L);
215 /* table has been moved by one because of the pushnil */
216 /* this will ONLY work with negative indices! */
217 while (lua_next(L, index-1) != 0)
219 ALLOC_INIT_ZVAL(akey);
220 ALLOC_INIT_ZVAL(aval);
222 /* `key' is at index -2 and `value' at index -1 */
223 php_lua_get_zval_from_stack(L,-2,akey TSRMLS_CC);
224 php_lua_get_zval_from_stack(L,-1,aval TSRMLS_CC);
226 switch(Z_TYPE_P(akey))
228 /* lua can't use (at least when i tried ;) ) floats as array keys so that should be safe */
229 case IS_DOUBLE:
230 add_index_zval(ret,(long)Z_DVAL_P(akey),aval);
231 break;
232 default:
233 add_assoc_zval(ret,Z_STRVAL_P(akey),aval);
234 break;
236 lua_pop(L, 1); /* removes `value'; keeps `key' for next iteration */
237 zval_ptr_dtor(&akey);
239 break;
242 case LUA_TFUNCTION:
243 /* TODO: Make this a PHP Function */
245 default:
246 php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid type `%i' passed from lua.", lua_type(L, index));
247 /* fall-through */
249 case LUA_TNIL:
250 ZVAL_NULL(ret);
251 break;
254 } /* }}} */
256 static int php_lua_print(lua_State *L) /* {{{ */
258 int i;
259 int n = lua_gettop(L);
261 for (i = 1; i <= n; i++) {
262 php_printf("%s", lua_tostring(L, i));
265 return 0;
266 } /* }}} */
268 static void php_lua_object_dtor(void *object, zend_object_handle handle TSRMLS_DC) /* {{{ */
270 long i;
271 php_lua_object *intern = (php_lua_object*)object;
272 zend_object_std_dtor(&(intern->std) TSRMLS_CC);
274 for (i=0;i<intern->callback_count;i++)
275 zval_dtor(&intern->callbacks[i]);
276 efree(intern->callbacks);
277 if (intern->L) {
278 lua_close(intern->L);
281 efree(intern);
282 } /* }}} */
284 static zval *php_lua_read_property(zval *obj, zval *prop, int type TSRMLS_DC) /* {{{ */
286 zval *retval;
287 lua_State *L = getLuaZ(obj);
289 LUA_STACK_START(L);
291 if (type != BP_VAR_R) {
292 php_error_docref(NULL TSRMLS_CC, E_WARNING, "No write access using read_property.");
293 ALLOC_INIT_ZVAL(retval);
294 return retval;
297 if (Z_TYPE_P(prop) == IS_STRING) {
298 MAKE_STD_ZVAL(retval);
299 lua_getfield(L, LUA_GLOBALSINDEX, Z_STRVAL_P(prop));
300 php_lua_get_zval_from_stack(L, -1, retval TSRMLS_CC);
301 #if PHP_VERSION_ID>=50300
302 Z_DELREF_P(retval);
303 #else
304 retval->refcount--;
305 #endif
306 } else {
307 ALLOC_INIT_ZVAL(retval);
310 lua_pop(L, 1);
312 LUA_STACK_END(L);
314 return retval;
315 } /* }}} */
318 static void php_lua_write_real_property(lua_State *L,int index,zval *prop, zval *value TSRMLS_DC) /* {{{ */
320 LUA_STACK_START(L);
321 php_lua_push_zval(L, prop TSRMLS_CC);
322 php_lua_push_zval(L, value TSRMLS_CC);
324 lua_settable(L, index);
325 LUA_STACK_END(L);
326 } /* }}} */
330 static void php_lua_write_property(zval *obj, zval *prop, zval *value TSRMLS_DC) /* {{{ */
332 /* TODO: Use proper type for lua and separate only when needed */
333 lua_State *L = getLuaZ(obj);
335 php_lua_write_real_property(L,LUA_GLOBALSINDEX,prop,value TSRMLS_CC);
336 } /* }}} */
338 static int php_lua_atpanic(lua_State *L) { /* {{{ */
339 TSRMLS_FETCH();
340 php_error_docref(NULL TSRMLS_CC, E_WARNING, "lua panic (%s)", lua_tostring(L, 1));
341 lua_pop(L, 1);
342 zend_bailout();
343 return 0;
344 } /* }}} */
346 static zend_object_value php_lua_create_object(zend_class_entry *ce TSRMLS_DC) /* {{{ */
348 zval tmp;
349 zend_object_value retval;
350 php_lua_object *intern;
351 lua_State *L;
353 L = lua_newstate(php_lua_alloc, NULL);
354 lua_atpanic(L, php_lua_atpanic);
356 intern = ecalloc(1, sizeof(php_lua_object));
357 intern->L = L;
358 intern->callback_count=0;
359 intern->callbacks=emalloc(sizeof(zval*));
360 zend_object_std_init(&(intern->std), ce TSRMLS_CC);
361 zend_hash_copy(intern->std.properties,
362 &ce->default_properties, (copy_ctor_func_t) zval_add_ref,
363 (void *) &tmp, sizeof(zval *));
365 retval.handle = zend_objects_store_put(intern, php_lua_object_dtor, NULL, NULL TSRMLS_CC);
366 retval.handlers = &lua_handlers;
367 return retval;
368 } /* }}} */
370 static int php_lua_callback(lua_State *L) /* {{{ */
372 int n,i;
373 php_lua_object *object=(php_lua_object*)lua_topointer(L, lua_upvalueindex(1));
374 long selected_callback_index=(long)lua_tonumber(L, lua_upvalueindex(2));
375 #ifdef ZTS
376 TSRMLS_D=(void ***)lua_topointer(L,lua_upvalueindex(3));
377 #endif
378 zval *return_value;
379 zval **params;
381 ALLOC_INIT_ZVAL(return_value);
383 #if PHP_VERSION_ID>=50300
384 if (!zend_is_callable(&object->callbacks[selected_callback_index],0,NULL TSRMLS_CC))
385 #else
386 if (!zend_is_callable(&object->callbacks[selected_callback_index],0,NULL))
387 #endif
388 return 0;
390 n = lua_gettop(L); /* number of arguments */
392 params=emalloc(n*sizeof(zval));
394 for (i = 1; i <= n; i++) {
395 ALLOC_INIT_ZVAL(params[i-1]);
396 /* php_lua_get_zval_from_stack won't work with positive indices */
397 php_lua_get_zval_from_stack(L,-n-1+i,params[i-1] TSRMLS_CC);
400 /* XXX no check - do we need one? :S */
401 /* johannes said i should use zend_call_method but this only allows up to 2 parameters?! */
402 call_user_function(EG(function_table),NULL,&object->callbacks[selected_callback_index],return_value,n,params TSRMLS_CC);
404 /* hmm...what if the result is NULL? should php return a return value (NULL) then or just return 0? :S */
405 php_lua_push_zval(L,return_value TSRMLS_CC);
407 for (i = 0; i < n; i++) {
408 zval_ptr_dtor(&params[i]);
410 efree(params);
412 zval_ptr_dtor(&return_value);
414 /* PHP doesn't support multiple return values so this will always be 1 */
415 return 1;
416 } /* }}} */
418 static void php_lua_call_table_with_arguments(lua_State *L,int level,int table_index,char *function,int propagate_self,zval *args,zval *return_value TSRMLS_DC) /* {{{ */
420 int retcount,i;
421 zval *val;
423 lua_getfield(L,table_index,function);
424 if (lua_type(L,lua_gettop(L)) != LUA_TFUNCTION) {
425 lua_pop(L, lua_gettop(L) - level);
426 php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid lua callback. '%s' is not a defined function",function);
427 return;
430 /* push the table on the stack as the first argument */
431 if (propagate_self)
432 lua_pushvalue(L,table_index + lua_gettop(L));
434 zend_hash_apply_with_argument(Z_ARRVAL_P(args), php_lua_push_apply_func, (void *)L TSRMLS_CC);
436 if (lua_pcall(L, zend_hash_num_elements(Z_ARRVAL_P(args)) + propagate_self, LUA_MULTRET, 0) != 0) {
437 php_error_docref(NULL TSRMLS_CC, E_WARNING, "error running lua function `%s': %s", function, lua_tostring(L, -1));
438 lua_pop(L, lua_gettop(L) - level);
439 return;
442 /* always return an array. otherwise we couldn't distinguish between a table return or a multi return */
443 array_init(return_value);
444 retcount = lua_gettop(L) - level;
446 for (i = -retcount; i < 0; i++)
448 MAKE_STD_ZVAL(val);
449 php_lua_get_zval_from_stack(L, i, val TSRMLS_CC);
450 add_next_index_zval(return_value, val);
452 lua_pop(L, retcount);
454 return;
455 } /* }}} */
457 static void php_lua_call_table_function(INTERNAL_FUNCTION_PARAMETERS,int propagate_self) /* {{{ */
459 zval *callback,*args;
460 zval **lua_table,**lua_function;
461 int array_count,level;
462 lua_State *L;
464 L=getLua();
465 LUA_STACK_START(L);
467 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "za", &callback, &args) == FAILURE) {
468 return;
471 array_count=zend_hash_num_elements(Z_ARRVAL_P(callback));
472 if (array_count!=2) {
473 LUA_STACK_END(L);
474 php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid callback supplied. must contain exactly 2 elements");
475 return;
477 if (zend_hash_index_find(Z_ARRVAL_P(callback), 0, (void**)&lua_table) == FAILURE) {
478 php_error_docref(NULL TSRMLS_CC, E_WARNING, "callback index 0 is empty");
479 return;
481 if (zend_hash_index_find(Z_ARRVAL_P(callback), 1, (void**)&lua_function) == FAILURE) {
482 php_error_docref(NULL TSRMLS_CC, E_WARNING, "callback index 1 is empty");
483 return;
485 lua_getglobal(L,Z_STRVAL_PP(lua_table));
486 if (lua_type(L,lua_gettop(L)) != LUA_TTABLE) {
487 lua_pop(L, -1);
488 php_error_docref(NULL TSRMLS_CC, E_WARNING, "trying to call an invalid table '%s'",Z_STRVAL_PP(lua_table));
489 return;
491 level=lua_gettop(L);
493 php_lua_call_table_with_arguments(L,level,-1,Z_STRVAL_PP(lua_function),propagate_self,args,return_value TSRMLS_CC);
495 /* remove the table which is still on top */
496 lua_pop(L,-1);
498 LUA_STACK_END(L);
499 } /* }}} */
501 /* {{{ */
502 static int php_lua_binary_zval_writer(lua_State* L, const void* p,size_t size, void* u)
504 Z_STRVAL_P((zval*)u)=erealloc(Z_STRVAL_P((zval*)u),(Z_STRLEN_P((zval*)u)+1+size)*sizeof(char));
505 memcpy(&Z_STRVAL_P((zval*)u)[Z_STRLEN_P((zval*)u)],p,size);
506 Z_STRLEN_P((zval*)u)=Z_STRLEN_P((zval*)u)+size;
507 Z_STRVAL_P((zval*)u)[Z_STRLEN_P((zval*)u)]='\0';
508 return 0;
510 /* }}} */
512 #define RETURN_STR "return %s"
515 /* {{{ lua::__construct()
516 Create new LUA instance */
517 PHP_METHOD(lua, __construct)
519 lua_State *L = getLua();
520 // mop: open standard libs if desired
521 if (INI_BOOL("lua.load_standard_libs")) {
522 luaL_openlibs(L);
524 lua_register(L, "print", php_lua_print);
526 /* }}} */
528 /* {{{ lua::__call(string method, array args [, int nresults])
529 Call a lua function from within PHP */
530 PHP_METHOD(lua, __call)
532 int level, retcount;
533 char *function, *func;
534 int function_len;
535 zval *args;
536 long nresults = LUA_MULTRET;
537 lua_State *L = getLua();
539 LUA_STACK_START(L);
541 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa|l", &function, &function_len, &args, &nresults) == FAILURE) {
542 return;
545 level = lua_gettop(L);
547 spprintf(&func, sizeof(RETURN_STR)-2-1+function_len, RETURN_STR, function);
548 if (luaL_dostring(L, func)) {
549 efree(func);
550 php_error_docref(NULL TSRMLS_CC, E_WARNING, "error looking up lua function `%s': %s", function, lua_tostring(L, -1));
551 lua_pop(L, lua_gettop(L) - level);
552 LUA_STACK_END(L);
553 return;
555 efree(func);
557 zend_hash_apply_with_argument(Z_ARRVAL_P(args), php_lua_push_apply_func, (void *)L TSRMLS_CC);
559 if (lua_pcall(L, zend_hash_num_elements(Z_ARRVAL_P(args)), nresults, 0) != 0) {
560 php_error_docref(NULL TSRMLS_CC, E_WARNING, "error running lua function `%s': %s", function, lua_tostring(L, -1));
561 lua_pop(L, lua_gettop(L) - level);
562 LUA_STACK_END(L);
563 return;
566 retcount = lua_gettop(L) - level;
568 if (retcount == 0) {
569 /* No vlaue returned -> return null */
570 } else {
571 /* multiple return values -> build an array */
572 int i;
573 zval *val;
575 array_init(return_value);
576 for (i = -retcount; i < 0; i++)
578 MAKE_STD_ZVAL(val);
579 php_lua_get_zval_from_stack(L, i, val TSRMLS_CC);
580 add_next_index_zval(return_value, val);
582 lua_pop(L, retcount);
585 LUA_STACK_END(L);
586 return;
589 /* {{{ lua::call_function(string function, array args)
590 Call a lua function from within PHP */
591 PHP_METHOD(lua, call_function)
593 char *function;
594 int function_len;
595 zval *args;
596 lua_State *L;
597 int level;
599 L=getLua();
600 LUA_STACK_START(L);
602 level=lua_gettop(L);
604 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa", &function, &function_len, &args) == FAILURE) {
605 return;
608 php_lua_call_table_with_arguments(L,level,LUA_GLOBALSINDEX,function,0,args,return_value TSRMLS_CC);
610 LUA_STACK_END(L);
613 /* {{{ lua::call_table(array lua_callback, array args)
614 Call a lua table from within PHP (lua_table.lua_function()) */
615 PHP_METHOD(lua, call_table)
617 php_lua_call_table_function(INTERNAL_FUNCTION_PARAM_PASSTHRU,0);
620 /* {{{ lua::call_table_self(array lua_callback, array args)
621 Call a lua table from within PHP and propagate self (lua_table:lua_function()) */
622 PHP_METHOD(lua, call_table_self)
624 php_lua_call_table_function(INTERNAL_FUNCTION_PARAM_PASSTHRU,1);
627 /* {{{ void lua::evaluate(string code)
628 Evaluates code with lua */
629 PHP_METHOD(lua, evaluate)
631 int error;
632 int code_len;
633 int retcount,i;
634 char *code;
635 zval *val;
637 lua_State *L = getLua();
639 LUA_STACK_START(L);
641 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &code, &code_len) == FAILURE) {
642 return;
645 error = luaL_loadbuffer(L, code, code_len, "line") || lua_pcall(L, 0, LUA_MULTRET, 0);
646 if (error) {
647 php_error_docref(NULL TSRMLS_CC, E_WARNING, "lua error: %s", lua_tostring(L, -1));
648 lua_pop(L, 1); /* pop error message from the stack */
651 /* always return an array. otherwise we couldn't distinguish between a table return or a multi return */
652 array_init(return_value);
653 retcount = lua_gettop(L);
655 for (i = -retcount; i < 0; i++)
657 MAKE_STD_ZVAL(val);
658 php_lua_get_zval_from_stack(L, i, val TSRMLS_CC);
659 add_next_index_zval(return_value, val);
661 lua_pop(L, retcount);
663 LUA_STACK_END(L);
665 /* }}} */
667 /* {{{ void lua::evaluatefile(string file)
668 Evaluates a lua script */
669 PHP_METHOD(lua, evaluatefile)
671 int error;
672 int file_len;
673 char *file;
674 lua_State *L = getLua();
675 int retcount;
676 int i;
677 zval *val;
679 LUA_STACK_START(L);
681 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &file, &file_len) == FAILURE) {
682 return;
685 if (php_check_open_basedir(file TSRMLS_CC) || (PG(safe_mode) && !php_checkuid(file, "rb+", CHECKUID_CHECK_MODE_PARAM))) {
686 LUA_STACK_END(L);
687 RETURN_FALSE;
690 error = luaL_dofile(L, file);
692 if (error) {
693 php_error_docref(NULL TSRMLS_CC, E_WARNING, "lua error: %s", lua_tostring(L, -1));
694 lua_pop(L, 1);
696 retcount=lua_gettop(L);
697 array_init(return_value);
699 for (i = -retcount; i < 0; i++)
701 MAKE_STD_ZVAL(val);
702 php_lua_get_zval_from_stack(L, i, val TSRMLS_CC);
703 add_next_index_zval(return_value, val);
705 lua_pop(L, retcount);
707 LUA_STACK_END(L);
709 /* }}} */
711 /* {{{ string lua::getVersion()
712 Return Lua's version */
713 PHP_METHOD(lua, getversion)
715 RETURN_STRING(LUA_RELEASE, 1);
717 /* }}} */
719 /* {{{ */
720 PHP_METHOD(lua,expose_function)
722 zval *callback;
723 char *lua_name;
724 int len;
725 int param_count;
727 php_lua_object *object=getLuaY();
728 lua_State *L = object->L;
730 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,"sz",&lua_name,&len,&callback) == FAILURE)
731 return;
733 #if PHP_VERSION_ID>=50300
734 if (zend_is_callable(callback,0,NULL TSRMLS_CC)) {
735 #else
736 if (zend_is_callable(callback,0,NULL)) {
737 #endif
738 lua_pushlightuserdata(L,object);
739 lua_pushnumber(L,object->callback_count);
740 #ifdef ZTS
741 lua_pushlightuserdata(L,TSRMLS_C);
742 param_count=3;
743 #else
744 param_count=2;
745 #endif
746 lua_pushcclosure(L, php_lua_callback,param_count);
747 lua_setglobal(L, lua_name);
749 /* hmm...out of memory check? */
750 object->callbacks=erealloc(object->callbacks,sizeof(zval)*(object->callback_count+1));
751 object->callbacks[object->callback_count] = *callback;
752 zval_copy_ctor(&object->callbacks[object->callback_count]);
753 object->callback_count++;
755 /* }}} */
757 /* {{{ */
758 PHP_METHOD(lua,compile)
760 char *chunk;
761 int len;
762 int error;
764 lua_State *L = lua_newstate(php_lua_alloc, NULL);
765 lua_atpanic(L, php_lua_atpanic);
767 LUA_STACK_START(L);
769 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,"s",&chunk,&len) == FAILURE)
771 lua_close(L);
772 return;
775 error = luaL_loadbuffer(L, chunk, len, "line");
776 if (error) {
777 php_error_docref(NULL TSRMLS_CC, E_WARNING, "lua error: %s", lua_tostring(L, -1));
778 lua_pop(L, 1); /* pop error message from the stack */
779 lua_close(L);
780 return;
783 RETVAL_STRING("",1);
785 error=lua_dump(L,php_lua_binary_zval_writer,return_value);
786 lua_pop(L, 1); /* clean stack */
787 LUA_STACK_END(L);
788 lua_close(L);
789 if (error) {
790 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Couldn't dump code");
791 RETURN_NULL();
796 /* {{{ ARG_INFO */
798 ZEND_BEGIN_ARG_INFO_EX(arginfo_lua_call, 0, 0, 2)
799 ZEND_ARG_INFO(0, method)
800 ZEND_ARG_INFO(0, args)
801 ZEND_END_ARG_INFO()
803 ZEND_BEGIN_ARG_INFO_EX(arginfo_lua_call_table, 0, 0, 2)
804 ZEND_ARG_INFO(0, callback)
805 ZEND_ARG_INFO(0, args)
806 ZEND_END_ARG_INFO()
808 ZEND_BEGIN_ARG_INFO_EX(arginfo_lua_call_function, 0, 0, 2)
809 ZEND_ARG_INFO(0, function)
810 ZEND_ARG_INFO(0, args)
811 ZEND_END_ARG_INFO()
813 ZEND_BEGIN_ARG_INFO_EX(arginfo_lua_evaluate, 0, 0, 1)
814 ZEND_ARG_INFO(0, code)
815 ZEND_END_ARG_INFO()
817 ZEND_BEGIN_ARG_INFO_EX(arginfo_lua_evaluatefile, 0, 0, 1)
818 ZEND_ARG_INFO(0, file)
819 ZEND_END_ARG_INFO()
821 ZEND_BEGIN_ARG_INFO_EX(arginfo_lua_expose_function, 0, 0, 2)
822 ZEND_ARG_INFO(0, lua_name)
823 ZEND_ARG_INFO(0, callback)
824 ZEND_END_ARG_INFO()
826 ZEND_BEGIN_ARG_INFO_EX(arginfo_lua_compile, 0, 0, 1)
827 ZEND_ARG_INFO(0, chunk)
828 ZEND_END_ARG_INFO()
830 /* }}} */
832 /* {{{ lua_class_functions[] */
833 zend_function_entry lua_class_functions[] = {
834 PHP_ME(lua, __construct, NULL, ZEND_ACC_PUBLIC)
835 PHP_ME(lua, __call, arginfo_lua_call, ZEND_ACC_PUBLIC)
836 PHP_ME(lua, call_function, arginfo_lua_call_function, ZEND_ACC_PUBLIC)
837 PHP_ME(lua, call_table, arginfo_lua_call_table, ZEND_ACC_PUBLIC)
838 PHP_ME(lua, call_table_self, arginfo_lua_call_table, ZEND_ACC_PUBLIC)
839 PHP_ME(lua, evaluate, arginfo_lua_evaluate, ZEND_ACC_PUBLIC)
840 PHP_ME(lua, evaluatefile, arginfo_lua_evaluatefile, ZEND_ACC_PUBLIC)
841 PHP_ME(lua, getversion, NULL, ZEND_ACC_PUBLIC)
842 PHP_ME(lua, expose_function, arginfo_lua_expose_function, ZEND_ACC_PUBLIC)
843 PHP_ME(lua, compile, arginfo_lua_compile, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
844 {NULL, NULL, NULL}
846 /* }}} */
848 #ifdef COMPILE_DL_LUA
849 ZEND_GET_MODULE(lua)
850 #endif
852 /* {{{ PHP_INI
854 PHP_INI_BEGIN()
855 STD_PHP_INI_BOOLEAN("lua.load_standard_libs","1", PHP_INI_ALL, OnUpdateBool, load_standard_libs, zend_lua_globals, lua_globals)
856 PHP_INI_END()
857 /* }}} */
859 /* {{{ php_lua_init_globals
861 static void php_lua_init_globals(zend_lua_globals *lua_globals)
864 /* }}} */
866 /* {{{ PHP_MINIT_FUNCTION
868 PHP_MINIT_FUNCTION(lua)
870 zend_class_entry ce;
871 ZEND_INIT_MODULE_GLOBALS(lua, php_lua_init_globals, NULL);
873 REGISTER_INI_ENTRIES();
874 INIT_CLASS_ENTRY(ce, "lua", lua_class_functions);
875 lua_ce = zend_register_internal_class(&ce TSRMLS_CC);
876 lua_ce->create_object = php_lua_create_object;
877 memcpy(&lua_handlers, zend_get_std_object_handlers(),
878 sizeof(zend_object_handlers));
879 lua_handlers.write_property = php_lua_write_property;
880 lua_handlers.read_property = php_lua_read_property;
881 lua_ce->ce_flags |= ZEND_ACC_FINAL;
883 zend_declare_class_constant_long(lua_ce, "MULTRET", sizeof("MULTRET")-1, LUA_MULTRET TSRMLS_CC);
885 return SUCCESS;
887 /* }}} */
889 /* {{{ PHP_MSHUTDOWN_FUNCTION
891 PHP_MSHUTDOWN_FUNCTION(lua)
893 UNREGISTER_INI_ENTRIES();
894 return SUCCESS;
896 /* }}} */
898 /* {{{ PHP_RINIT_FUNCTION
900 PHP_RINIT_FUNCTION(lua)
902 return SUCCESS;
904 /* }}} */
906 /* {{{ PHP_RSHUTDOWN_FUNCTION
908 PHP_RSHUTDOWN_FUNCTION(lua)
910 return SUCCESS;
912 /* }}} */
914 /* {{{ PHP_MINFO_FUNCTION
916 PHP_MINFO_FUNCTION(lua)
918 php_info_print_table_start();
919 php_info_print_table_row(2, "lua support", "enabled");
920 php_info_print_table_row(2, "lua extension version", EXT_LUA_VERSION);
921 php_info_print_table_row(2, "lua release", LUA_RELEASE);
922 php_info_print_table_row(2, "lua copyright", LUA_COPYRIGHT);
923 php_info_print_table_row(2, "lua authors", LUA_AUTHORS);
924 php_info_print_table_end();
926 DISPLAY_INI_ENTRIES();
928 /* }}} */
930 /* {{{ lua_module_entry
932 zend_module_entry lua_module_entry = {
933 STANDARD_MODULE_HEADER,
934 "lua",
935 NULL,
936 PHP_MINIT(lua),
937 PHP_MSHUTDOWN(lua),
938 PHP_RINIT(lua),
939 PHP_RSHUTDOWN(lua),
940 PHP_MINFO(lua),
941 EXT_LUA_VERSION,
942 STANDARD_MODULE_PROPERTIES
944 /* }}} */
947 * Local variables:
948 * tab-width: 4
949 * c-basic-offset: 4
950 * vim: set noet sw=4 ts=4:
951 * vim600: noet sw=4 ts=4 fdm=marker:
952 * End: