Bump version
[phplua.git] / lua.c
bloba3c0675d7b753743464e92be155cbf9af05924d7
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 #if PHP_VERSION_ID < 50399
362 zend_hash_copy(intern->std.properties,
363 &ce->default_properties, (copy_ctor_func_t) zval_add_ref,
364 (void *) &tmp, sizeof(zval *));
365 #else
366 object_properties_init(&(intern->std), ce);
367 #endif
369 retval.handle = zend_objects_store_put(intern, php_lua_object_dtor, NULL, NULL TSRMLS_CC);
370 retval.handlers = &lua_handlers;
371 return retval;
372 } /* }}} */
374 static int php_lua_callback(lua_State *L) /* {{{ */
376 int n,i;
377 php_lua_object *object=(php_lua_object*)lua_topointer(L, lua_upvalueindex(1));
378 long selected_callback_index=(long)lua_tonumber(L, lua_upvalueindex(2));
379 #ifdef ZTS
380 TSRMLS_D=(void ***)lua_topointer(L,lua_upvalueindex(3));
381 #endif
382 zval *return_value;
383 zval **params;
385 ALLOC_INIT_ZVAL(return_value);
387 #if PHP_VERSION_ID>=50300
388 if (!zend_is_callable(&object->callbacks[selected_callback_index],0,NULL TSRMLS_CC))
389 #else
390 if (!zend_is_callable(&object->callbacks[selected_callback_index],0,NULL))
391 #endif
392 return 0;
394 n = lua_gettop(L); /* number of arguments */
396 params=emalloc(n*sizeof(zval));
398 for (i = 1; i <= n; i++) {
399 ALLOC_INIT_ZVAL(params[i-1]);
400 /* php_lua_get_zval_from_stack won't work with positive indices */
401 php_lua_get_zval_from_stack(L,-n-1+i,params[i-1] TSRMLS_CC);
404 /* XXX no check - do we need one? :S */
405 /* johannes said i should use zend_call_method but this only allows up to 2 parameters?! */
406 call_user_function(EG(function_table),NULL,&object->callbacks[selected_callback_index],return_value,n,params TSRMLS_CC);
408 /* hmm...what if the result is NULL? should php return a return value (NULL) then or just return 0? :S */
409 php_lua_push_zval(L,return_value TSRMLS_CC);
411 for (i = 0; i < n; i++) {
412 zval_ptr_dtor(&params[i]);
414 efree(params);
416 zval_ptr_dtor(&return_value);
418 /* PHP doesn't support multiple return values so this will always be 1 */
419 return 1;
420 } /* }}} */
422 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) /* {{{ */
424 int retcount,i;
425 zval *val;
427 lua_getfield(L,table_index,function);
428 if (lua_type(L,lua_gettop(L)) != LUA_TFUNCTION) {
429 lua_pop(L, lua_gettop(L) - level);
430 php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid lua callback. '%s' is not a defined function",function);
431 return;
434 /* push the table on the stack as the first argument */
435 if (propagate_self)
436 lua_pushvalue(L,table_index + lua_gettop(L));
438 zend_hash_apply_with_argument(Z_ARRVAL_P(args), php_lua_push_apply_func, (void *)L TSRMLS_CC);
440 if (lua_pcall(L, zend_hash_num_elements(Z_ARRVAL_P(args)) + propagate_self, LUA_MULTRET, 0) != 0) {
441 php_error_docref(NULL TSRMLS_CC, E_WARNING, "error running lua function `%s': %s", function, lua_tostring(L, -1));
442 lua_pop(L, lua_gettop(L) - level);
443 return;
446 /* always return an array. otherwise we couldn't distinguish between a table return or a multi return */
447 array_init(return_value);
448 retcount = lua_gettop(L) - level;
450 for (i = -retcount; i < 0; i++)
452 MAKE_STD_ZVAL(val);
453 php_lua_get_zval_from_stack(L, i, val TSRMLS_CC);
454 add_next_index_zval(return_value, val);
456 lua_pop(L, retcount);
458 return;
459 } /* }}} */
461 static void php_lua_call_table_function(INTERNAL_FUNCTION_PARAMETERS,int propagate_self) /* {{{ */
463 zval *callback,*args;
464 zval **lua_table,**lua_function;
465 int array_count,level;
466 lua_State *L;
468 L=getLua();
469 LUA_STACK_START(L);
471 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "za", &callback, &args) == FAILURE) {
472 return;
475 array_count=zend_hash_num_elements(Z_ARRVAL_P(callback));
476 if (array_count!=2) {
477 LUA_STACK_END(L);
478 php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid callback supplied. must contain exactly 2 elements");
479 return;
481 if (zend_hash_index_find(Z_ARRVAL_P(callback), 0, (void**)&lua_table) == FAILURE) {
482 php_error_docref(NULL TSRMLS_CC, E_WARNING, "callback index 0 is empty");
483 return;
485 if (zend_hash_index_find(Z_ARRVAL_P(callback), 1, (void**)&lua_function) == FAILURE) {
486 php_error_docref(NULL TSRMLS_CC, E_WARNING, "callback index 1 is empty");
487 return;
489 lua_getglobal(L,Z_STRVAL_PP(lua_table));
490 if (lua_type(L,lua_gettop(L)) != LUA_TTABLE) {
491 lua_pop(L, -1);
492 php_error_docref(NULL TSRMLS_CC, E_WARNING, "trying to call an invalid table '%s'",Z_STRVAL_PP(lua_table));
493 return;
495 level=lua_gettop(L);
497 php_lua_call_table_with_arguments(L,level,-1,Z_STRVAL_PP(lua_function),propagate_self,args,return_value TSRMLS_CC);
499 /* remove the table which is still on top */
500 lua_pop(L,-1);
502 LUA_STACK_END(L);
503 } /* }}} */
505 /* {{{ */
506 static int php_lua_binary_zval_writer(lua_State* L, const void* p,size_t size, void* u)
508 Z_STRVAL_P((zval*)u)=erealloc(Z_STRVAL_P((zval*)u),(Z_STRLEN_P((zval*)u)+1+size)*sizeof(char));
509 memcpy(&Z_STRVAL_P((zval*)u)[Z_STRLEN_P((zval*)u)],p,size);
510 Z_STRLEN_P((zval*)u)=Z_STRLEN_P((zval*)u)+size;
511 Z_STRVAL_P((zval*)u)[Z_STRLEN_P((zval*)u)]='\0';
512 return 0;
514 /* }}} */
516 #define RETURN_STR "return %s"
519 /* {{{ lua::__construct()
520 Create new LUA instance */
521 PHP_METHOD(lua, __construct)
523 lua_State *L = getLua();
524 // mop: open standard libs if desired
525 if (INI_BOOL("lua.load_standard_libs")) {
526 luaL_openlibs(L);
528 lua_register(L, "print", php_lua_print);
530 /* }}} */
532 /* {{{ lua::__call(string method, array args [, int nresults])
533 Call a lua function from within PHP */
534 PHP_METHOD(lua, __call)
536 int level, retcount;
537 char *function, *func;
538 int function_len;
539 zval *args;
540 long nresults = LUA_MULTRET;
541 lua_State *L = getLua();
543 LUA_STACK_START(L);
545 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa|l", &function, &function_len, &args, &nresults) == FAILURE) {
546 return;
549 level = lua_gettop(L);
551 spprintf(&func, sizeof(RETURN_STR)-2-1+function_len, RETURN_STR, function);
552 if (luaL_dostring(L, func)) {
553 efree(func);
554 php_error_docref(NULL TSRMLS_CC, E_WARNING, "error looking up lua function `%s': %s", function, lua_tostring(L, -1));
555 lua_pop(L, lua_gettop(L) - level);
556 LUA_STACK_END(L);
557 return;
559 efree(func);
561 zend_hash_apply_with_argument(Z_ARRVAL_P(args), php_lua_push_apply_func, (void *)L TSRMLS_CC);
563 if (lua_pcall(L, zend_hash_num_elements(Z_ARRVAL_P(args)), nresults, 0) != 0) {
564 php_error_docref(NULL TSRMLS_CC, E_WARNING, "error running lua function `%s': %s", function, lua_tostring(L, -1));
565 lua_pop(L, lua_gettop(L) - level);
566 LUA_STACK_END(L);
567 return;
570 retcount = lua_gettop(L) - level;
572 if (retcount == 0) {
573 /* No vlaue returned -> return null */
574 } else {
575 /* multiple return values -> build an array */
576 int i;
577 zval *val;
579 array_init(return_value);
580 for (i = -retcount; i < 0; i++)
582 MAKE_STD_ZVAL(val);
583 php_lua_get_zval_from_stack(L, i, val TSRMLS_CC);
584 add_next_index_zval(return_value, val);
586 lua_pop(L, retcount);
589 LUA_STACK_END(L);
590 return;
593 /* {{{ lua::call_function(string function, array args)
594 Call a lua function from within PHP */
595 PHP_METHOD(lua, call_function)
597 char *function;
598 int function_len;
599 zval *args;
600 lua_State *L;
601 int level;
603 L=getLua();
604 LUA_STACK_START(L);
606 level=lua_gettop(L);
608 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa", &function, &function_len, &args) == FAILURE) {
609 return;
612 php_lua_call_table_with_arguments(L,level,LUA_GLOBALSINDEX,function,0,args,return_value TSRMLS_CC);
614 LUA_STACK_END(L);
617 /* {{{ lua::call_table(array lua_callback, array args)
618 Call a lua table from within PHP (lua_table.lua_function()) */
619 PHP_METHOD(lua, call_table)
621 php_lua_call_table_function(INTERNAL_FUNCTION_PARAM_PASSTHRU,0);
624 /* {{{ lua::call_table_self(array lua_callback, array args)
625 Call a lua table from within PHP and propagate self (lua_table:lua_function()) */
626 PHP_METHOD(lua, call_table_self)
628 php_lua_call_table_function(INTERNAL_FUNCTION_PARAM_PASSTHRU,1);
631 /* {{{ void lua::evaluate(string code)
632 Evaluates code with lua */
633 PHP_METHOD(lua, evaluate)
635 int error;
636 int code_len;
637 int retcount,i;
638 char *code;
639 zval *val;
641 lua_State *L = getLua();
643 LUA_STACK_START(L);
645 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &code, &code_len) == FAILURE) {
646 return;
649 error = luaL_loadbuffer(L, code, code_len, "line") || lua_pcall(L, 0, LUA_MULTRET, 0);
650 if (error) {
651 php_error_docref(NULL TSRMLS_CC, E_WARNING, "lua error: %s", lua_tostring(L, -1));
652 lua_pop(L, 1); /* pop error message from the stack */
655 /* always return an array. otherwise we couldn't distinguish between a table return or a multi return */
656 array_init(return_value);
657 retcount = lua_gettop(L);
659 for (i = -retcount; i < 0; i++)
661 MAKE_STD_ZVAL(val);
662 php_lua_get_zval_from_stack(L, i, val TSRMLS_CC);
663 add_next_index_zval(return_value, val);
665 lua_pop(L, retcount);
667 LUA_STACK_END(L);
669 /* }}} */
671 /* {{{ void lua::evaluatefile(string file)
672 Evaluates a lua script */
673 PHP_METHOD(lua, evaluatefile)
675 int error;
676 int file_len;
677 char *file;
678 lua_State *L = getLua();
679 int retcount;
680 int i;
681 zval *val;
683 LUA_STACK_START(L);
685 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &file, &file_len) == FAILURE) {
686 return;
689 #if PHP_VERSION_ID < 50399
690 if (php_check_open_basedir(file TSRMLS_CC) || (PG(safe_mode) && !php_checkuid(file, "rb+", CHECKUID_CHECK_MODE_PARAM))) {
691 LUA_STACK_END(L);
692 RETURN_FALSE;
694 #endif
696 error = luaL_dofile(L, file);
698 if (error) {
699 php_error_docref(NULL TSRMLS_CC, E_WARNING, "lua error: %s", lua_tostring(L, -1));
700 lua_pop(L, 1);
702 retcount=lua_gettop(L);
703 array_init(return_value);
705 for (i = -retcount; i < 0; i++)
707 MAKE_STD_ZVAL(val);
708 php_lua_get_zval_from_stack(L, i, val TSRMLS_CC);
709 add_next_index_zval(return_value, val);
711 lua_pop(L, retcount);
713 LUA_STACK_END(L);
715 /* }}} */
717 /* {{{ string lua::getVersion()
718 Return Lua's version */
719 PHP_METHOD(lua, getversion)
721 RETURN_STRING(LUA_RELEASE, 1);
723 /* }}} */
725 /* {{{ */
726 PHP_METHOD(lua,expose_function)
728 zval *callback;
729 char *lua_name;
730 int len;
731 int param_count;
733 php_lua_object *object=getLuaY();
734 lua_State *L = object->L;
736 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,"sz",&lua_name,&len,&callback) == FAILURE)
737 return;
739 #if PHP_VERSION_ID>=50300
740 if (zend_is_callable(callback,0,NULL TSRMLS_CC)) {
741 #else
742 if (zend_is_callable(callback,0,NULL)) {
743 #endif
744 lua_pushlightuserdata(L,object);
745 lua_pushnumber(L,object->callback_count);
746 #ifdef ZTS
747 lua_pushlightuserdata(L,TSRMLS_C);
748 param_count=3;
749 #else
750 param_count=2;
751 #endif
752 lua_pushcclosure(L, php_lua_callback,param_count);
753 lua_setglobal(L, lua_name);
755 /* hmm...out of memory check? */
756 object->callbacks=erealloc(object->callbacks,sizeof(zval)*(object->callback_count+1));
757 object->callbacks[object->callback_count] = *callback;
758 zval_copy_ctor(&object->callbacks[object->callback_count]);
759 object->callback_count++;
761 /* }}} */
763 /* {{{ */
764 PHP_METHOD(lua,compile)
766 char *chunk;
767 int len;
768 int error;
770 lua_State *L = lua_newstate(php_lua_alloc, NULL);
771 lua_atpanic(L, php_lua_atpanic);
773 LUA_STACK_START(L);
775 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,"s",&chunk,&len) == FAILURE)
777 lua_close(L);
778 return;
781 error = luaL_loadbuffer(L, chunk, len, "line");
782 if (error) {
783 php_error_docref(NULL TSRMLS_CC, E_WARNING, "lua error: %s", lua_tostring(L, -1));
784 lua_pop(L, 1); /* pop error message from the stack */
785 lua_close(L);
786 return;
789 RETVAL_STRING("",1);
791 error=lua_dump(L,php_lua_binary_zval_writer,return_value);
792 lua_pop(L, 1); /* clean stack */
793 LUA_STACK_END(L);
794 lua_close(L);
795 if (error) {
796 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Couldn't dump code");
797 RETURN_NULL();
802 /* {{{ ARG_INFO */
804 ZEND_BEGIN_ARG_INFO_EX(arginfo_lua_call, 0, 0, 2)
805 ZEND_ARG_INFO(0, method)
806 ZEND_ARG_INFO(0, args)
807 ZEND_END_ARG_INFO()
809 ZEND_BEGIN_ARG_INFO_EX(arginfo_lua_call_table, 0, 0, 2)
810 ZEND_ARG_INFO(0, callback)
811 ZEND_ARG_INFO(0, args)
812 ZEND_END_ARG_INFO()
814 ZEND_BEGIN_ARG_INFO_EX(arginfo_lua_call_function, 0, 0, 2)
815 ZEND_ARG_INFO(0, function)
816 ZEND_ARG_INFO(0, args)
817 ZEND_END_ARG_INFO()
819 ZEND_BEGIN_ARG_INFO_EX(arginfo_lua_evaluate, 0, 0, 1)
820 ZEND_ARG_INFO(0, code)
821 ZEND_END_ARG_INFO()
823 ZEND_BEGIN_ARG_INFO_EX(arginfo_lua_evaluatefile, 0, 0, 1)
824 ZEND_ARG_INFO(0, file)
825 ZEND_END_ARG_INFO()
827 ZEND_BEGIN_ARG_INFO_EX(arginfo_lua_expose_function, 0, 0, 2)
828 ZEND_ARG_INFO(0, lua_name)
829 ZEND_ARG_INFO(0, callback)
830 ZEND_END_ARG_INFO()
832 ZEND_BEGIN_ARG_INFO_EX(arginfo_lua_compile, 0, 0, 1)
833 ZEND_ARG_INFO(0, chunk)
834 ZEND_END_ARG_INFO()
836 /* }}} */
838 /* {{{ lua_class_functions[] */
839 zend_function_entry lua_class_functions[] = {
840 PHP_ME(lua, __construct, NULL, ZEND_ACC_PUBLIC)
841 PHP_ME(lua, __call, arginfo_lua_call, ZEND_ACC_PUBLIC)
842 PHP_ME(lua, call_function, arginfo_lua_call_function, ZEND_ACC_PUBLIC)
843 PHP_ME(lua, call_table, arginfo_lua_call_table, ZEND_ACC_PUBLIC)
844 PHP_ME(lua, call_table_self, arginfo_lua_call_table, ZEND_ACC_PUBLIC)
845 PHP_ME(lua, evaluate, arginfo_lua_evaluate, ZEND_ACC_PUBLIC)
846 PHP_ME(lua, evaluatefile, arginfo_lua_evaluatefile, ZEND_ACC_PUBLIC)
847 PHP_ME(lua, getversion, NULL, ZEND_ACC_PUBLIC)
848 PHP_ME(lua, expose_function, arginfo_lua_expose_function, ZEND_ACC_PUBLIC)
849 PHP_ME(lua, compile, arginfo_lua_compile, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
850 {NULL, NULL, NULL}
852 /* }}} */
854 #ifdef COMPILE_DL_LUA
855 ZEND_GET_MODULE(lua)
856 #endif
858 /* {{{ PHP_INI
860 PHP_INI_BEGIN()
861 STD_PHP_INI_BOOLEAN("lua.load_standard_libs","1", PHP_INI_ALL, OnUpdateBool, load_standard_libs, zend_lua_globals, lua_globals)
862 PHP_INI_END()
863 /* }}} */
865 /* {{{ php_lua_init_globals
867 static void php_lua_init_globals(zend_lua_globals *lua_globals)
870 /* }}} */
872 /* {{{ PHP_MINIT_FUNCTION
874 PHP_MINIT_FUNCTION(lua)
876 zend_class_entry ce;
877 ZEND_INIT_MODULE_GLOBALS(lua, php_lua_init_globals, NULL);
879 REGISTER_INI_ENTRIES();
880 INIT_CLASS_ENTRY(ce, "lua", lua_class_functions);
881 lua_ce = zend_register_internal_class(&ce TSRMLS_CC);
882 lua_ce->create_object = php_lua_create_object;
883 memcpy(&lua_handlers, zend_get_std_object_handlers(),
884 sizeof(zend_object_handlers));
885 lua_handlers.write_property = php_lua_write_property;
886 lua_handlers.read_property = php_lua_read_property;
887 lua_ce->ce_flags |= ZEND_ACC_FINAL;
889 zend_declare_class_constant_long(lua_ce, "MULTRET", sizeof("MULTRET")-1, LUA_MULTRET TSRMLS_CC);
891 return SUCCESS;
893 /* }}} */
895 /* {{{ PHP_MSHUTDOWN_FUNCTION
897 PHP_MSHUTDOWN_FUNCTION(lua)
899 UNREGISTER_INI_ENTRIES();
900 return SUCCESS;
902 /* }}} */
904 /* {{{ PHP_RINIT_FUNCTION
906 PHP_RINIT_FUNCTION(lua)
908 return SUCCESS;
910 /* }}} */
912 /* {{{ PHP_RSHUTDOWN_FUNCTION
914 PHP_RSHUTDOWN_FUNCTION(lua)
916 return SUCCESS;
918 /* }}} */
920 /* {{{ PHP_MINFO_FUNCTION
922 PHP_MINFO_FUNCTION(lua)
924 php_info_print_table_start();
925 php_info_print_table_row(2, "lua support", "enabled");
926 php_info_print_table_row(2, "lua extension version", EXT_LUA_VERSION);
927 php_info_print_table_row(2, "lua release", LUA_RELEASE);
928 php_info_print_table_row(2, "lua copyright", LUA_COPYRIGHT);
929 php_info_print_table_row(2, "lua authors", LUA_AUTHORS);
930 php_info_print_table_end();
932 DISPLAY_INI_ENTRIES();
934 /* }}} */
936 /* {{{ lua_module_entry
938 zend_module_entry lua_module_entry = {
939 STANDARD_MODULE_HEADER,
940 "lua",
941 NULL,
942 PHP_MINIT(lua),
943 PHP_MSHUTDOWN(lua),
944 PHP_RINIT(lua),
945 PHP_RSHUTDOWN(lua),
946 PHP_MINFO(lua),
947 EXT_LUA_VERSION,
948 STANDARD_MODULE_PROPERTIES
950 /* }}} */
953 * Local variables:
954 * tab-width: 4
955 * c-basic-offset: 4
956 * vim: set noet sw=4 ts=4:
957 * vim600: noet sw=4 ts=4 fdm=marker:
958 * End: