GCC Code Coverage Report


Directory: src/gate/
File: src/gate/scripting/luascripts.c
Date: 2025-12-12 23:40:09
Exec Total Coverage
Lines: 0 792 0.0%
Functions: 0 43 0.0%
Branches: 0 273 0.0%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright(c) 2018-2025, Stefan Meislinger <sm@opengate.at> |
4 | All rights reserved. |
5 | |
6 | Redistribution and use in source and binary forms, with or without |
7 | modification, are permitted provided that the following conditions are met:|
8 | |
9 | 1. Redistributions of source code must retain the above copyright notice, |
10 | this list of conditions and the following disclaimer. |
11 | 2. Redistributions in binary form must reproduce the above copyright |
12 | notice, this list of conditions and the following disclaimer in the |
13 | documentation and/or other materials provided with the distribution. |
14 | |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"|
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
25 | THE POSSIBILITY OF SUCH DAMAGE. |
26 +----------------------------------------------------------------------------+
27 */
28
29 #include "gate/scripting/luascripts.h"
30 #include "gate/results.h"
31 #include "gate/guids.h"
32 #include "gate/times.h"
33 #include "gate/console.h"
34 #include "gate/functions.h"
35 #include "gate/files.h"
36 #include "gate/platforms.h"
37
38 #if defined(GATE_EXTLIB_LUA)
39 # define GATE_SCRIPTING_LUA_USE_LUA 1
40 #else
41 # define GATE_SCRIPTING_LUA_NO_IMPL 1
42 #endif
43
44
45 #if defined(GATE_SCRIPTING_LUA_USE_LUA)
46
47 #include <lua.h>
48 #include <lualib.h>
49 #include <lauxlib.h>
50
51
52 #define GATE_SCRIPT_LUA_SESSION_POINTER_NAME "__gate_script_lua_session"
53
54 void gate_lua_writestring(char const* str, size_t len, gate_bool_t flushcon)
55 {
56 gate_size_t written = 0;
57 gate_console_t* con = gate_console();
58 gate_stream_write_block((gate_stream_t*)con, str, len, &written);
59 if (flushcon)
60 {
61 gate_stream_flush((gate_stream_t*)con);
62 }
63 }
64
65 void gate_lua_writestring_err(char const* str, size_t len, gate_bool_t flushcon)
66 {
67 gate_size_t written = 0;
68 gate_console_t* con = gate_console();
69 gate_stream_write_block((gate_stream_t*)con, str, len, &written);
70 if (flushcon)
71 {
72 gate_stream_flush((gate_stream_t*)con);
73 }
74 }
75
76 gate_result_t gate_script_lua_init(gate_script_lua_session_t* session)
77 {
78 gate_result_t ret;
79
80 do
81 {
82 gate_mem_clear(session, sizeof(gate_script_lua_session_t));
83 ret = gate_script_lua_reset(session);
84 } while (0);
85 return ret;
86 }
87 gate_result_t gate_script_lua_uninit(gate_script_lua_session_t* session)
88 {
89 gate_result_t ret = GATE_RESULT_FAILED;
90 lua_State* lstate = NULL;
91
92 do
93 {
94 lstate = (lua_State*)session->state;
95 if (lstate != NULL)
96 {
97 lua_close(lstate);
98 session->state = NULL;
99 }
100 ret = GATE_RESULT_OK;
101 } while (0);
102
103 return ret;
104 }
105 gate_result_t gate_script_lua_reset(gate_script_lua_session_t* session)
106 {
107 gate_result_t ret = GATE_RESULT_FAILED;
108 lua_State* lstate = NULL;
109
110 do
111 {
112 lstate = luaL_newstate();
113 if (NULL == lstate)
114 {
115 ret = GATE_RESULT_OUTOFRESOURCES;
116 break;
117 }
118
119 luaopen_base(lstate);
120 luaopen_table(lstate);
121 luaopen_string(lstate);
122 luaopen_math(lstate);
123 luaopen_coroutine(lstate);
124 luaopen_utf8(lstate);
125
126 if (session->state != NULL)
127 {
128 lua_close((lua_State*)session->state);
129 }
130 lua_pushlightuserdata(lstate, session);
131 lua_setglobal(lstate, GATE_SCRIPT_LUA_SESSION_POINTER_NAME);
132 session->state = lstate;
133 lstate = NULL;
134 ret = GATE_RESULT_OK;
135 } while (0);
136
137 if (lstate != NULL)
138 {
139 lua_close(lstate);
140 }
141
142 return ret;
143 }
144
145 static gate_script_lua_session_t* gate_script_lua_get_session(lua_State* L)
146 {
147 lua_getglobal(L, GATE_SCRIPT_LUA_SESSION_POINTER_NAME);
148 return (gate_script_lua_session_t*)lua_touserdata(L, -1);
149 }
150
151
152 struct gate_script_lua_code_block
153 {
154 char const* data;
155 gate_size_t size;
156 };
157
158 static char const* gate_script_lua_code_reader(lua_State* L, void* data, size_t* size)
159 {
160 char const* ret = NULL;
161 struct gate_script_lua_code_block* block = (struct gate_script_lua_code_block*)data;
162
163 (void)L;
164 *size = 0;
165 if (block->size > 0)
166 {
167 ret = block->data;
168 *size = block->size;
169
170 block->data += block->size;
171 block->size = 0;
172 }
173 return ret;
174 }
175
176 static gate_result_t gate_script_lua_map_error(int lua_result_code)
177 {
178 switch (lua_result_code)
179 {
180 case LUA_OK: return GATE_RESULT_OK;
181 case LUA_YIELD: return GATE_RESULT_OK_PARTIAL;
182 case LUA_ERRRUN: return GATE_RESULT_EXECUTIONFAILED;
183 case LUA_ERRSYNTAX: return GATE_RESULT_INVALIDDATA;
184 case LUA_ERRMEM: return GATE_RESULT_OUTOFMEMORY;
185 case LUA_ERRERR: return GATE_RESULT_CRITICALERROR;
186 default: return GATE_RESULT_FAILED;
187 }
188 }
189
190 static gate_result_t gate_script_lua_load_impl(lua_State* lstate, gate_string_t const* code, gate_bool_t print_error)
191 {
192 gate_result_t ret = GATE_RESULT_FAILED;
193
194 (void)print_error;
195 do
196 {
197 int result;
198 struct gate_script_lua_code_block block;
199
200 block.data = gate_string_ptr(code, 0);
201 block.size = gate_string_length(code);
202 result = lua_load(lstate, &gate_script_lua_code_reader, &block, "gate_lua_code", NULL);
203 ret = gate_script_lua_map_error(result);
204 GATE_BREAK_IF_FAILED(ret);
205
206 result = lua_pcall(lstate, 0, 0, 0);
207 ret = gate_script_lua_map_error(result);
208 GATE_BREAK_IF_FAILED(ret);
209 } while (0);
210
211 return ret;
212
213 }
214
215 gate_result_t gate_script_lua_load(gate_script_lua_session_t* session, gate_string_t const* code)
216 {
217 return gate_script_lua_load_impl((lua_State*)session->state, code, false);
218 }
219
220
221 static gate_result_t gate_script_lua_push_value(lua_State* L, gate_value_t const* val)
222 {
223 gate_result_t ret = GATE_RESULT_FAILED;
224 gate_type_id_t value_type = gate_value_type(val);
225 void const* value_ptr = gate_value_get_ptr(val);
226
227 char buffer[8192];
228 gate_size_t buffer_used = 0;
229 gate_datetime_t datetime = GATE_INIT_EMPTY;
230
231 do
232 {
233 if (!value_ptr)
234 {
235 ret = GATE_RESULT_NOTAVAILABLE;
236 break;
237 }
238
239 ret = GATE_RESULT_OK;
240
241 switch (value_type)
242 {
243 case GATE_TYPE_BOOL: lua_pushboolean(L, *((gate_bool_t const*)value_ptr) ? 1 : 0); break;
244 case GATE_TYPE_I8: lua_pushinteger(L, (lua_Integer) * ((gate_int8_t const*)value_ptr)); break;
245 case GATE_TYPE_UI8: lua_pushinteger(L, (lua_Integer) * ((gate_uint8_t const*)value_ptr)); break;
246 case GATE_TYPE_I16: lua_pushinteger(L, (lua_Integer) * ((gate_int16_t const*)value_ptr)); break;
247 case GATE_TYPE_UI16: lua_pushinteger(L, (lua_Integer) * ((gate_uint16_t const*)value_ptr)); break;
248 case GATE_TYPE_I32: lua_pushinteger(L, (lua_Integer) * ((gate_int32_t const*)value_ptr)); break;
249 case GATE_TYPE_UI32: lua_pushinteger(L, (lua_Integer) * ((gate_uint32_t const*)value_ptr)); break;
250 case GATE_TYPE_I64: lua_pushinteger(L, (lua_Integer) * ((gate_int64_t const*)value_ptr)); break;
251 case GATE_TYPE_UI64: lua_pushinteger(L, (lua_Integer) * ((gate_uint64_t const*)value_ptr)); break;
252 case GATE_TYPE_ADDRESS: lua_pushinteger(L, (lua_Integer) * ((gate_uintptr_t const*)value_ptr)); break;
253 case GATE_TYPE_R32: lua_pushnumber(L, (lua_Number) * ((gate_real32_t const*)value_ptr)); break;
254 case GATE_TYPE_R64: lua_pushnumber(L, (lua_Number) * ((gate_real64_t const*)value_ptr)); break;
255
256 case GATE_TYPE_CSTR: lua_pushlstring(L, (char const*)value_ptr, gate_str_length((char const*)value_ptr)); break;
257 case GATE_TYPE_WSTR:
258 buffer_used = gate_str_utf16_2_utf8((gate_char16_t const*)value_ptr,
259 gate_str16_length((gate_char16_t const*)value_ptr),
260 buffer, sizeof(buffer));
261 lua_pushlstring(L, buffer, buffer_used);
262 break;
263 case GATE_TYPE_GUID:
264 gate_guid_to_string((gate_guid_t const*)value_ptr, buffer);
265 lua_pushlstring(L, buffer, 36);
266 break;
267 case GATE_TYPE_DATE:
268 datetime.date = *((gate_date_t const*)value_ptr);
269 buffer_used = sizeof(buffer);
270 gate_date_to_string(&datetime, 0, "{YYYY}-{MM}-{DD}", buffer, &buffer_used);
271 lua_pushlstring(L, buffer, buffer_used);
272 break;
273 case GATE_TYPE_DAYTIME:
274 datetime.time = *((gate_daytime_t const*)value_ptr);
275 buffer_used = sizeof(buffer);
276 gate_date_to_string(&datetime, 0, "{hh}:{mm}:{ss}.{SSS}", buffer, &buffer_used);
277 lua_pushlstring(L, buffer, buffer_used);
278 break;
279 case GATE_TYPE_DATETIME:
280 buffer_used = sizeof(buffer);
281 gate_date_to_string((gate_datetime_t const*)value_ptr, 0, NULL, buffer, &buffer_used);
282 lua_pushlstring(L, buffer, buffer_used);
283 break;
284 case GATE_TYPE_TIME:
285 gate_time_to_datetime((gate_time_t const*)value_ptr, &datetime);
286 buffer_used = sizeof(buffer);
287 gate_date_to_string((gate_datetime_t const*)value_ptr, 0, NULL, buffer, &buffer_used);
288 lua_pushlstring(L, buffer, buffer_used);
289 break;
290 case GATE_TYPE_STRING:
291 lua_pushlstring(L, gate_string_ptr((gate_string_t const*)value_ptr, 0),
292 gate_string_length((gate_string_t const*)value_ptr));
293 break;
294
295
296 default:
297 ret = GATE_RESULT_NOTSUPPORTED;
298 break;
299 }
300
301
302 } while (0);
303
304 return ret;
305 }
306
307
308 static gate_result_t gate_script_lua_get_value(lua_State* L, int index, gate_value_t* value)
309 {
310 int ltype = lua_type(L, index);
311
312 gate_value_t* ret_value = NULL;
313 gate_bool_t bool_val = false;
314 gate_real64_t real_val = 0.0;
315 gate_string_t str_val = GATE_STRING_INIT_EMPTY;
316 size_t str_len = 0;
317 gate_cstr_t cstr = NULL;
318
319
320 switch (ltype)
321 {
322 case LUA_TNIL:
323 {
324 ret_value = gate_value_create(GATE_TYPE_EMPTY, NULL, value);
325 break;
326 }
327 case LUA_TBOOLEAN:
328 {
329 bool_val = (lua_toboolean(L, index) == 0) ? false : true;
330 ret_value = gate_value_create(GATE_TYPE_BOOL, &bool_val, value);
331 break;
332 }
333 case LUA_TNUMBER:
334 {
335 real_val = (gate_real64_t)lua_tonumber(L, index);
336 ret_value = gate_value_create(GATE_TYPE_R64, &real_val, value);
337 break;
338 }
339 case LUA_TSTRING:
340 {
341 cstr = lua_tolstring(L, index, &str_len);
342 if (gate_string_create(&str_val, cstr, str_len))
343 {
344 ret_value = gate_value_create(GATE_TYPE_STRING, &str_val, value);
345 }
346 break;
347 }
348 case LUA_TFUNCTION:
349 case LUA_TTABLE:
350 default:
351 {
352 break;
353 }
354 }
355
356 gate_string_release(&str_val);
357 return ret_value == NULL ? GATE_RESULT_NOTSUPPORTED : GATE_RESULT_OK;
358 }
359
360 gate_result_t gate_script_lua_invoke(gate_script_lua_session_t* session, gate_string_t const* func_name,
361 gate_value_t* args, gate_size_t arg_count, gate_value_t* ret_val)
362 {
363 gate_result_t ret = GATE_RESULT_FAILED;
364
365 do
366 {
367 int result;
368 char buffer[4096];
369 int index;
370 lua_State* lstate = (lua_State*)session->state;
371
372 gate_string_to_buffer(func_name, buffer, sizeof(buffer));
373
374 lua_checkstack(lstate, (int)(arg_count + 2));
375 result = lua_getglobal(lstate, buffer);
376 ret = gate_script_lua_map_error(result);
377 GATE_BREAK_IF_FAILED(ret);
378
379 for (index = 0; index != arg_count; ++index)
380 {
381 ret = gate_script_lua_push_value(lstate, &args[index]);
382 if (GATE_FAILED(ret))
383 {
384 lua_pop(lstate, index + 1);
385 break;
386 }
387 }
388 GATE_BREAK_IF_FAILED(ret);
389
390 result = lua_pcall(lstate, (int)arg_count, 1, 0);
391 ret = gate_script_lua_map_error(result);
392 GATE_BREAK_IF_FAILED(ret);
393
394 ret = gate_script_lua_get_value(lstate, -1, ret_val);
395 lua_pop(lstate, 1);
396
397 } while (0);
398
399 return ret;
400 }
401 gate_result_t gate_script_lua_set_var(gate_script_lua_session_t* session,
402 gate_string_t const* name, gate_value_t const* value)
403 {
404 gate_result_t ret = GATE_RESULT_FAILED;
405
406 do
407 {
408 lua_State* lstate;
409 char buffer[4096];
410
411 gate_string_to_buffer(name, buffer, sizeof(buffer));
412 lstate = (lua_State*)session->state;
413 ret = gate_script_lua_push_value(lstate, value);
414 lua_setglobal(lstate, buffer);
415 } while (0);
416 return ret;
417 }
418 gate_result_t gate_script_lua_get_var(gate_script_lua_session_t* session,
419 gate_string_t const* name, gate_value_t* value)
420 {
421 gate_result_t ret = GATE_RESULT_FAILED;
422
423 do
424 {
425 lua_State* lstate;
426 char buffer[4096];
427
428 gate_string_to_buffer(name, buffer, sizeof(buffer));
429 lstate = (lua_State*)session->state;
430 lua_getglobal(lstate, buffer);
431
432 ret = gate_script_lua_get_value(lstate, -1, value);
433 GATE_BREAK_IF_FAILED(ret);
434
435 lua_pop(lstate, 1);
436 ret = GATE_RESULT_OK;
437 } while (0);
438
439 return ret;
440 }
441
442 gate_result_t gate_script_lua_cfunc_add(
443 gate_script_lua_session_t* session,
444 gate_string_t const* func_name,
445 int(*lua_cfunc)(void* lstate),
446 void* userparam)
447 {
448 gate_result_t ret = GATE_RESULT_FAILED;
449 gate_cstrbuffer_t name_buffer = GATE_INIT_EMPTY;
450
451 do
452 {
453 lua_State* lstate;
454
455 if (!session || !func_name || !lua_cfunc)
456 {
457 ret = GATE_RESULT_INVALIDARG;
458 break;
459 }
460
461 if (NULL == gate_cstrbuffer_create_string(&name_buffer, func_name, false))
462 {
463 ret = GATE_RESULT_OUTOFMEMORY;
464 break;
465 }
466
467 lstate = (lua_State*)session->state;
468
469 if (userparam)
470 {
471 /* add userparam to stack */
472 lua_pushlightuserdata(lstate, userparam);
473 lua_pushcclosure(lstate, (lua_CFunction)lua_cfunc, 1);
474 }
475 else
476 {
477 /* add function dispatcher with one upvalue (cfunc-def) */
478 lua_pushcclosure(lstate, (lua_CFunction)lua_cfunc, 0);
479 }
480
481 /* set global name of function */
482 lua_setglobal(lstate, gate_cstrbuffer_get(&name_buffer));
483
484 ret = GATE_RESULT_OK;
485 } while (0);
486
487 gate_cstrbuffer_destroy(&name_buffer);
488
489 return ret;
490 }
491
492 gate_size_t gate_script_lua_cfunc_get_arg_count(void* lstate)
493 {
494 lua_State* L = (lua_State*)lstate;
495 return (gate_size_t)lua_gettop(L);
496 }
497
498 static void lua_stack_get_bool(lua_State* state, int index, gate_bool_t* ptr)
499 {
500 *ptr = lua_toboolean(state, index) == 0 ? false : true;
501 }
502
503 static void lua_stack_get_int(lua_State* state, int index, gate_int32_t* ptr)
504 {
505 *ptr = (gate_int32_t)lua_tointeger(state, index);
506 }
507
508 static void lua_stack_get_number(lua_State* state, int index, gate_real64_t* ptr)
509 {
510 *ptr = (gate_real64_t)lua_tonumber(state, index);
511 }
512
513 static void lua_stack_get_string(lua_State* state, int index, gate_string_t* ptr)
514 {
515 size_t len = 0;
516 char const* str = lua_tolstring(state, index, &len);
517 gate_string_create(ptr, str, len);
518 }
519
520 static gate_result_t lua_stack_item_to_prop(lua_State* L, int index, gate_property_t* prop)
521 {
522 gate_property_t* ret = NULL;
523 if (lua_isboolean(L, index))
524 {
525 gate_bool_t v = false;
526 lua_stack_get_bool(L, index, &v);
527 ret = gate_property_create_bool(prop, v);
528 }
529 else if (lua_isinteger(L, index))
530 {
531 gate_int32_t v = 0;
532 lua_stack_get_int(L, index, &v);
533 ret = gate_property_create_int(prop, (gate_int64_t)v);
534 }
535 else if (lua_isnumber(L, index))
536 {
537 gate_real64_t v = 0.0;
538 lua_stack_get_number(L, index, &v);
539 ret = gate_property_create_real(prop, (gate_real64_t)v);
540 }
541 else if (lua_isstring(L, index))
542 {
543 gate_string_t gstr = GATE_STRING_INIT_EMPTY;
544 lua_stack_get_string(L, index, &gstr);
545 ret = gate_property_create_string(prop, &gstr);
546 gate_string_release(&gstr);
547 }
548 else if (lua_istable(L, index))
549 {
550 gate_bool_t prop_init = false;
551 /* empty-pre-first-key to search next: */
552 lua_pushnil(L);
553
554 /* search next key from stack and push key-vakue pair */
555 while (lua_next(L, index) != 0)
556 {
557 gate_property_t item = GATE_INIT_EMPTY;
558 gate_result_t result = lua_stack_item_to_prop(L, -1, &item);
559 if (GATE_SUCCEEDED(result))
560 {
561 if (lua_isnumber(L, -2))
562 {
563 /* lua_Integer tbl_ndx = lua_tointeger(L, -2); */
564 if (!prop_init)
565 {
566 /* first key is a number -> table is an array */
567 ret = gate_property_create_array(prop, NULL, 0);
568 prop_init = true;
569 }
570 gate_property_array_add(prop, &item);
571 }
572 else if (lua_isstring(L, -2))
573 {
574 size_t key_len;
575 char const* key_value;
576 gate_string_t key_str = GATE_STRING_INIT_EMPTY;
577 if (!prop_init)
578 {
579 /* first key is a string -> table is a property object */
580 ret = gate_property_create_object(prop);
581 prop_init = true;
582 }
583 key_value = lua_tolstring(L, -2, &key_len);
584 gate_string_create(&key_str, key_value, key_len);
585 gate_property_member_add(prop, &key_str, &item);
586 gate_string_release(&key_str);
587 }
588
589 gate_property_destroy(&item);
590 }
591 lua_pop(L, 1);
592 }
593 }
594 if (ret == NULL)
595 {
596 return GATE_RESULT_FAILED;
597 }
598 return GATE_RESULT_OK;
599 }
600
601 gate_result_t gate_script_lua_cfunc_get_stack_item(void* lstate, int arg_index, gate_property_t* prop)
602 {
603 lua_State* const L = (lua_State*)lstate;
604 return lua_stack_item_to_prop(L, arg_index, prop);
605 }
606
607 gate_result_t gate_script_lua_cfunc_get_arg(void* lstate, gate_size_t arg_index, gate_property_t* prop)
608 {
609 lua_State* const L = (lua_State*)lstate;
610 int const lua_func_arg_count = lua_gettop(L);
611 int const lua_func_arg_index = (int)arg_index + 1;
612
613 if (lua_func_arg_index > lua_func_arg_count)
614 {
615 return GATE_RESULT_OUTOFBOUNDS;
616 }
617
618 return lua_stack_item_to_prop(L, lua_func_arg_index, prop);
619 }
620
621
622 static void lua_stack_push_property(lua_State* L, gate_property_t const* prop)
623 {
624 switch (gate_property_get_type(prop))
625 {
626 case GATE_PROPERTY_TYPE_EMPTY:
627 {
628 lua_pushnil(L);
629 return;
630 }
631 case GATE_PROPERTY_TYPE_BOOL:
632 {
633 gate_bool_t b = false;
634 gate_property_get_bool(prop, &b);
635 lua_pushboolean(L, b ? 1 : 0);
636 return;
637 }
638 case GATE_PROPERTY_TYPE_INT:
639 {
640 gate_int64_t v = 0;
641 gate_property_get_int(prop, &v);
642 if ((v < -2147483648LL) || (v > 2147483647LL))
643 {
644 lua_pushnumber(L, (lua_Number)v);
645 }
646 else
647 {
648 lua_pushinteger(L, (lua_Integer)v);
649 }
650 return;
651 }
652 case GATE_PROPERTY_TYPE_REAL:
653 {
654 gate_real64_t v = 0.0;
655 gate_property_get_real(prop, &v);
656 lua_pushnumber(L, (lua_Number)v);
657 return;
658 }
659 case GATE_PROPERTY_TYPE_STRING:
660 {
661 gate_string_t str = GATE_STRING_INIT_EMPTY;
662 gate_property_get_string(prop, &str);
663 lua_pushlstring(L, gate_string_ptr(&str, 0), gate_string_length(&str));
664 gate_string_release(&str);
665 return;
666 }
667 case GATE_PROPERTY_TYPE_ARRAY:
668 {
669 gate_size_t ndx;
670 const gate_size_t length = gate_property_array_length(prop);
671 lua_createtable(L, (int)length, 0);
672 for (ndx = 0; ndx < (int)length; ++ndx)
673 {
674 gate_property_t const* item = gate_property_array_get(prop, ndx);
675 if (item)
676 {
677 lua_stack_push_property(L, item);
678 }
679 else
680 {
681 lua_pushnil(L);
682 }
683 lua_rawseti(L, -2, (lua_Integer)(ndx + 1));
684 }
685 return;
686 }
687 case GATE_PROPERTY_TYPE_OBJECT:
688 {
689 gate_size_t ndx, length;
690 gate_array_t names = GATE_INIT_EMPTY;
691 gate_property_member_names(prop, &names);
692 length = gate_array_length(&names);
693
694 lua_newtable(L);
695 for (ndx = 0; ndx != length; ++ndx)
696 {
697 gate_string_t const* name = (gate_string_t const*)gate_array_get(&names, ndx);
698 gate_property_t const* item;
699 if (!name)
700 {
701 continue;
702 }
703 item = gate_property_member_get(prop, name);
704 if (!item)
705 {
706 continue;
707 }
708 lua_pushlstring(L, gate_string_ptr(name, 0), gate_string_length(name));
709 lua_stack_push_property(L, item);
710 lua_settable(L, -3);
711 }
712 return;
713 }
714 }
715 }
716
717 gate_result_t gate_script_lua_cfunc_push_stack_item(void* lstate, gate_property_t const* prop)
718 {
719 lua_State* const L = (lua_State*)lstate;
720 if (!L || !prop)
721 {
722 return GATE_RESULT_INVALIDARG;
723 }
724 lua_stack_push_property(L, prop);
725 return GATE_RESULT_OK;
726 }
727
728 gate_size_t gate_script_lua_cfunc_def_param_count(gate_script_lua_cfunc_def_t const* cfunc_def)
729 {
730 unsigned ndx;
731 for (ndx = 0; ndx != GATE_SCRIPTING_LUA_MAX_FUNC_PARAMS; ++ndx)
732 {
733 if (cfunc_def->params[ndx] == GATE_TYPE_VOID)
734 {
735 return ndx;
736 }
737 }
738 return GATE_SCRIPTING_LUA_MAX_FUNC_PARAMS;
739 }
740
741 #define CREATE_INT_VALUE(native_type) \
742 const native_type v = (native_type)lua_tointeger(L, lua_param_index); \
743 gate_value_create(required_type, &v, ptr_val)
744
745 #define CREATE_NUM_VALUE(native_type) \
746 const native_type v = (native_type)lua_tonumber(L, lua_param_index); \
747 gate_value_create(required_type, &v, ptr_val)
748
749
750 static gate_result_t load_lua_params(lua_State* L, gate_type_id_t required_type, int lua_param_index, gate_value_t* ptr_val)
751 {
752 gate_result_t ret = GATE_RESULT_OK;
753
754 switch (required_type)
755 {
756 case GATE_TYPE_BOOL:
757 {
758 const gate_bool_t v = lua_toboolean(L, lua_param_index);
759 gate_value_create(GATE_TYPE_BOOL, &v, ptr_val);
760 break;
761 }
762 case GATE_TYPE_I8: { CREATE_INT_VALUE(gate_int8_t); break; }
763 case GATE_TYPE_UI8: { CREATE_INT_VALUE(gate_uint8_t); break; }
764 case GATE_TYPE_I16: { CREATE_INT_VALUE(gate_int16_t); break; }
765 case GATE_TYPE_UI16: { CREATE_INT_VALUE(gate_uint16_t); break; }
766 case GATE_TYPE_I32: { CREATE_INT_VALUE(gate_int32_t); break; }
767 case GATE_TYPE_UI32: { CREATE_INT_VALUE(gate_uint32_t); break; }
768 case GATE_TYPE_I64: { CREATE_NUM_VALUE(gate_int64_t); break; }
769 case GATE_TYPE_UI64: { CREATE_NUM_VALUE(gate_uint64_t); break; }
770 case GATE_TYPE_R32: { CREATE_NUM_VALUE(gate_real32_t); break; }
771 case GATE_TYPE_R64: { CREATE_NUM_VALUE(gate_real64_t); break; }
772 case GATE_TYPE_ADDRESS:
773 case GATE_TYPE_DATAPTR:
774 case GATE_TYPE_FUNCPTR:
775 {
776 ret = GATE_RESULT_NOTSUPPORTED;
777 break;
778 }
779 case GATE_TYPE_CSTR:
780 {
781 size_t l;
782 gate_cstr_t s = luaL_tolstring(L, lua_param_index, &l);
783 gate_value_create(GATE_TYPE_CSTR, &s, ptr_val);
784 break;
785 }
786 case GATE_TYPE_WSTR:
787 case GATE_TYPE_GUID:
788 {
789 ret = GATE_RESULT_NOTSUPPORTED;
790 break;
791 }
792 case GATE_TYPE_DATE:
793 {
794 gate_time_t tm = GATE_INIT_EMPTY;
795 gate_datetime_t dt = GATE_INIT_EMPTY;
796 const gate_int64_t unix_seconds = (gate_int64_t)lua_tointeger(L, lua_param_index);
797 gate_time_from_unix(unix_seconds, &tm.timestamp);
798 gate_time_to_datetime(&tm, &dt);
799 gate_value_create(GATE_TYPE_DATE, &dt.date, ptr_val);
800 break;
801 }
802 case GATE_TYPE_DAYTIME:
803 {
804 gate_time_t tm = GATE_INIT_EMPTY;
805 gate_datetime_t dt = GATE_INIT_EMPTY;
806 const gate_int64_t unix_seconds = (gate_int64_t)lua_tointeger(L, lua_param_index);
807 gate_time_from_unix(unix_seconds, &tm.timestamp);
808 gate_time_to_datetime(&tm, &dt);
809 gate_value_create(GATE_TYPE_DAYTIME, &dt.time, ptr_val);
810 break;
811 }
812 case GATE_TYPE_DATETIME:
813 {
814 gate_time_t tm = GATE_INIT_EMPTY;
815 gate_datetime_t dt = GATE_INIT_EMPTY;
816 const gate_int64_t unix_seconds = (gate_int64_t)lua_tointeger(L, lua_param_index);
817 gate_time_from_unix(unix_seconds, &tm.timestamp);
818 gate_time_to_datetime(&tm, &dt);
819 gate_value_create(GATE_TYPE_DATETIME, &dt, ptr_val);
820 break;
821 }
822 case GATE_TYPE_TIME:
823 {
824 gate_time_t tm = GATE_INIT_EMPTY;
825 const gate_int64_t unix_seconds = (gate_int64_t)lua_tointeger(L, lua_param_index);
826 gate_time_from_unix(unix_seconds, &tm.timestamp);
827 gate_value_create(GATE_TYPE_TIME, &tm, ptr_val);
828 break;
829 }
830 case GATE_TYPE_STRING:
831 {
832 gate_string_t str = GATE_STRING_INIT_EMPTY;
833 size_t l;
834 gate_cstr_t s = luaL_tolstring(L, lua_param_index, &l);
835 gate_string_create(&str, s, l);
836 gate_value_create(GATE_TYPE_STRING, &str, ptr_val);
837 gate_string_release(&str);
838 break;
839 }
840 case GATE_TYPE_BLOB:
841 {
842 gate_blob_t blob = GATE_INIT_EMPTY;
843 size_t l;
844 gate_cstr_t s = luaL_tolstring(L, lua_param_index, &l);
845 gate_blob_create(&blob, s, l);
846 gate_value_create(GATE_TYPE_BLOB, &blob, ptr_val);
847 gate_blob_release(&blob);
848 break;
849 }
850 case GATE_TYPE_STRUCT:
851 case GATE_TYPE_OBJECT:
852 case GATE_TYPE_PROPERTY:
853
854 case GATE_TYPE_ARRAY:
855 case GATE_TYPE_ARRAYLIST:
856 case GATE_TYPE_ARRAYLIST_BOOL:
857 case GATE_TYPE_ARRAYLIST_I8:
858 case GATE_TYPE_ARRAYLIST_UI8:
859 case GATE_TYPE_ARRAYLIST_I16:
860 case GATE_TYPE_ARRAYLIST_UI16:
861 case GATE_TYPE_ARRAYLIST_I32:
862 case GATE_TYPE_ARRAYLIST_UI32:
863 case GATE_TYPE_ARRAYLIST_I64:
864 case GATE_TYPE_ARRAYLIST_UI64:
865 case GATE_TYPE_ARRAYLIST_R32:
866 case GATE_TYPE_ARRAYLIST_R64:
867 case GATE_TYPE_ARRAYLIST_ADDRESS:
868
869 case GATE_TYPE_ARRAYLIST_DATAPTR:
870 case GATE_TYPE_ARRAYLIST_FUNCPTR:
871 case GATE_TYPE_ARRAYLIST_CSTR:
872 case GATE_TYPE_ARRAYLIST_WSTR:
873 case GATE_TYPE_ARRAYLIST_GUID:
874 case GATE_TYPE_ARRAYLIST_DATE:
875 case GATE_TYPE_ARRAYLIST_DAYTIME:
876 case GATE_TYPE_ARRAYLIST_DATETIME:
877 case GATE_TYPE_ARRAYLIST_TIME:
878
879 case GATE_TYPE_ARRAYLIST_STRING:
880 case GATE_TYPE_ARRAYLIST_ARRAY:
881 case GATE_TYPE_ARRAYLIST_BLOB:
882
883 case GATE_TYPE_ARRAYLIST_STRUCT:
884 case GATE_TYPE_ARRAYLIST_OBJECT:
885 case GATE_TYPE_ARRAYLIST_PROPERTY:
886 default:
887 {
888 /*TODO*/
889 ret = GATE_RESULT_NOTSUPPORTED;
890 break;
891 }
892
893 }
894
895 return ret;
896 }
897
898 static gate_result_t convert_value_to_func_arg(gate_value_t const* ptr_val, gate_function_argument_t* ptr_arg)
899 {
900 gate_result_t ret = GATE_RESULT_OK;
901 gate_type_id_t const gt = gate_value_type(ptr_val);
902 switch (gt)
903 {
904 case GATE_TYPE_BOOL:
905 ptr_arg->arg_type = GATE_FUNCTION_ARG_UCHAR;
906 ptr_arg->arg_value.u_chr = ptr_val->content.bool_value;
907 break;
908 case GATE_TYPE_I8:
909 ptr_arg->arg_type = GATE_FUNCTION_ARG_SCHAR;
910 ptr_arg->arg_value.s_chr = ptr_val->content.i8_value;
911 break;
912 case GATE_TYPE_UI8:
913 ptr_arg->arg_type = GATE_FUNCTION_ARG_UCHAR;
914 ptr_arg->arg_value.u_chr = ptr_val->content.ui8_value;
915 break;
916 case GATE_TYPE_I16:
917 ptr_arg->arg_type = GATE_FUNCTION_ARG_SSHORT;
918 ptr_arg->arg_value.s_short = ptr_val->content.i16_value;
919 break;
920 case GATE_TYPE_UI16:
921 ptr_arg->arg_type = GATE_FUNCTION_ARG_USHORT;
922 ptr_arg->arg_value.u_short = ptr_val->content.ui16_value;
923 break;
924 case GATE_TYPE_I32:
925 ptr_arg->arg_type = GATE_FUNCTION_ARG_SLONG;
926 ptr_arg->arg_value.s_long = ptr_val->content.i32_value;
927 break;
928 case GATE_TYPE_UI32:
929 ptr_arg->arg_type = GATE_FUNCTION_ARG_ULONG;
930 ptr_arg->arg_value.u_long = ptr_val->content.ui32_value;
931 break;
932 case GATE_TYPE_I64:
933 ptr_arg->arg_type = GATE_FUNCTION_ARG_SLONGLONG;
934 ptr_arg->arg_value.s_long_long = ptr_val->content.i64_value;
935 break;
936 case GATE_TYPE_UI64:
937 ptr_arg->arg_type = GATE_FUNCTION_ARG_ULONGLONG;
938 ptr_arg->arg_value.u_long_long = ptr_val->content.ui64_value;
939 break;
940 case GATE_TYPE_R32:
941 ptr_arg->arg_type = GATE_FUNCTION_ARG_FLOAT;
942 ptr_arg->arg_value.flt = ptr_val->content.r32_value;
943 break;
944 case GATE_TYPE_R64:
945 ptr_arg->arg_type = GATE_FUNCTION_ARG_DOUBLE;
946 ptr_arg->arg_value.dbl = ptr_val->content.r64_value;
947 break;
948 /* pointer types: */
949 case GATE_TYPE_ADDRESS:
950 ptr_arg->arg_type = GATE_FUNCTION_ARG_POINTER;
951 ptr_arg->arg_value.ptr = (void*)ptr_val->content.address_value;
952 break;
953 case GATE_TYPE_DATAPTR:
954 case GATE_TYPE_FUNCPTR:
955 ptr_arg->arg_type = GATE_FUNCTION_ARG_POINTER;
956 ptr_arg->arg_value.ptr = ptr_val->content.ptr_value;
957 break;
958 case GATE_TYPE_CSTR:
959 ptr_arg->arg_type = GATE_FUNCTION_ARG_POINTER;
960 ptr_arg->arg_value.ptr = (void*)ptr_val->content.cstring_value;
961 break;
962 case GATE_TYPE_WSTR:
963 ptr_arg->arg_type = GATE_FUNCTION_ARG_POINTER;
964 ptr_arg->arg_value.ptr = (void*)ptr_val->content.wstring_value;
965 break;
966 case GATE_TYPE_GUID:
967 ptr_arg->arg_type = GATE_FUNCTION_ARG_POINTER;
968 ptr_arg->arg_value.ptr = (void*)&ptr_val->content.guid_value;
969 break;
970 case GATE_TYPE_DATE:
971 ptr_arg->arg_type = GATE_FUNCTION_ARG_POINTER;
972 ptr_arg->arg_value.ptr = (void*)&ptr_val->content.date_value;
973 break;
974 case GATE_TYPE_DAYTIME:
975 ptr_arg->arg_type = GATE_FUNCTION_ARG_POINTER;
976 ptr_arg->arg_value.ptr = (void*)&ptr_val->content.daytime_value;
977 break;
978 case GATE_TYPE_DATETIME:
979 ptr_arg->arg_type = GATE_FUNCTION_ARG_POINTER;
980 ptr_arg->arg_value.ptr = (void*)&ptr_val->content.datetime_value;
981 break;
982 case GATE_TYPE_TIME:
983 ptr_arg->arg_type = GATE_FUNCTION_ARG_POINTER;
984 ptr_arg->arg_value.ptr = (void*)&ptr_val->content.time_value;
985 break;
986 case GATE_TYPE_STRING:
987 ptr_arg->arg_type = GATE_FUNCTION_ARG_POINTER;
988 ptr_arg->arg_value.ptr = (void*)&ptr_val->content.string_value;
989 break;
990 case GATE_TYPE_BLOB:
991 ptr_arg->arg_type = GATE_FUNCTION_ARG_POINTER;
992 ptr_arg->arg_value.ptr = (void*)&ptr_val->content.blob_value;
993 break;
994 case GATE_TYPE_ARRAY:
995 ptr_arg->arg_type = GATE_FUNCTION_ARG_POINTER;
996 ptr_arg->arg_value.ptr = (void*)&ptr_val->content.array_value;
997 break;
998 default:
999 ret = GATE_RESULT_NOTSUPPORTED;
1000 break;
1001 }
1002 return ret;
1003 }
1004
1005 static int gate_lua_cfunc_dispatcher(lua_State* L)
1006 {
1007 static char const* const error_msg_fmt = "LUA C-function dispatcher error: #%d %s";
1008 int const lua_func_arg_count = lua_gettop(L);
1009 gate_script_lua_cfunc_def_t const* const cfunc_def =
1010 (gate_script_lua_cfunc_def_t const*)lua_touserdata(L, lua_upvalueindex(1));
1011 gate_size_t cfunc_count = 0;
1012 gate_value_t value_store[GATE_SCRIPTING_LUA_MAX_FUNC_PARAMS] = GATE_INIT_EMPTY;
1013 int ret = 0;
1014 int ndx;
1015 gate_result_t result;
1016
1017 do
1018 {
1019 gate_function_argument_t cfunc_args[GATE_SCRIPTING_LUA_MAX_FUNC_PARAMS] = GATE_INIT_EMPTY;
1020 gate_function_argument_t ret_val = GATE_INIT_EMPTY;
1021
1022 if (NULL == cfunc_def)
1023 {
1024 ret = luaL_error(L, error_msg_fmt, 1, "internal lua_cfunc_def parameter is missing");
1025 break;
1026 }
1027
1028 cfunc_count = gate_script_lua_cfunc_def_param_count(cfunc_def);
1029
1030 if (lua_func_arg_count < (int)cfunc_count)
1031 {
1032 ret = luaL_error(L, error_msg_fmt, (int)cfunc_count, " required parameters not available");
1033 break;
1034 }
1035
1036 if (lua_func_arg_count > GATE_SCRIPTING_LUA_MAX_FUNC_PARAMS)
1037 {
1038 ret = luaL_error(L, error_msg_fmt, (int)lua_func_arg_count, " too many parameters");
1039 break;
1040 }
1041
1042 /* store lua parameters as gate_value objects */
1043 for (ndx = 0; ndx < (int)cfunc_count; ++ndx)
1044 {
1045 result = load_lua_params(L, cfunc_def->params[ndx], ndx + 1, &value_store[ndx]);
1046 }
1047
1048 /* create generic function args from gate_value objects */
1049 for (ndx = 0; ndx < (int)cfunc_count; ++ndx)
1050 {
1051 result = convert_value_to_func_arg(&value_store[ndx], &cfunc_args[ndx]);
1052 }
1053
1054 /* call native gate-function pointer */
1055 result = gate_function_invoke_generic(cfunc_def->func_ptr, 0, cfunc_args, cfunc_count, &ret_val);
1056
1057
1058 } while (0);
1059
1060 for (ndx = 0; ndx < (int)cfunc_count; ++ndx)
1061 {
1062 gate_value_release(&value_store[ndx]);
1063 }
1064
1065 return ret;
1066 }
1067
1068 gate_result_t gate_script_lua_add_function(
1069 gate_script_lua_session_t* session,
1070 gate_string_t const* func_name,
1071 gate_script_lua_cfunc_def_t const* func_def)
1072 {
1073 gate_result_t ret = GATE_RESULT_FAILED;
1074
1075 do
1076 {
1077 lua_State* lstate;
1078 void* const cfunc_def_param = (void*)func_def;
1079 char name[128];
1080
1081 gate_string_to_buffer(func_name, name, sizeof(name));
1082
1083 lstate = (lua_State*)session->state;
1084
1085 /* push pointer to function definition as upvalue for function */
1086 lua_pushlightuserdata(lstate, cfunc_def_param);
1087
1088 /* add function dispatcher with one upvalue (cfunc-def) */
1089 lua_pushcclosure(lstate, &gate_lua_cfunc_dispatcher, 1);
1090
1091 /* set global name of function */
1092 lua_setglobal(lstate, name);
1093
1094 ret = GATE_RESULT_OK;
1095
1096 } while (0);
1097
1098 return ret;
1099 }
1100
1101
1102 static int gate_lua_print(lua_State* L)
1103 {
1104 int n = lua_gettop(L); /* number of arguments */
1105 int i;
1106 for (i = 1; i <= n; i++)
1107 {
1108 size_t l;
1109 const char* s = luaL_tolstring(L, i, &l); /* convert it to string */
1110 if (i > 1)
1111 {
1112 /* not the first element? */
1113 gate_lua_writestring(" ", 1, false); /* add a tab before it */
1114 }
1115 gate_lua_writestring(s, l, false); /* print it */
1116 lua_pop(L, 1); /* pop result */
1117 }
1118 gate_lua_writestring(GATE_STR_NEWLINE, GATE_STR_NEWLINE_LENGTH, true);
1119 return 0;
1120 }
1121
1122 static int gate_lua_printerr(lua_State* L)
1123 {
1124 int n = lua_gettop(L); /* number of arguments */
1125 int i;
1126 for (i = 1; i <= n; i++)
1127 {
1128 size_t l;
1129 const char* s = luaL_tolstring(L, i, &l); /* convert it to string */
1130 if (i > 1)
1131 {
1132 /* not the first element? */
1133 gate_lua_writestring_err(" ", 1, false); /* add a tab before it */
1134 }
1135 gate_lua_writestring_err(s, l, false); /* print it */
1136 lua_pop(L, 1); /* pop result */
1137 }
1138 gate_lua_writestring_err(GATE_STR_NEWLINE, GATE_STR_NEWLINE_LENGTH, true);
1139 return 0;
1140 }
1141
1142 static int gate_lua_read(lua_State* L)
1143 {
1144 gate_string_t line = GATE_STRING_INIT_EMPTY;
1145 gate_console_t* const con = gate_console();
1146
1147 gate_console_readln(con, &line);
1148
1149 lua_pushlstring(L, gate_string_ptr(&line, 0), gate_string_length(&line));
1150
1151 gate_string_release(&line);
1152 return 1;
1153 }
1154
1155 static void add_console_feature(lua_State* lstate)
1156 {
1157 lua_register(lstate, "print", &gate_lua_print);
1158 lua_register(lstate, "printerror", &gate_lua_printerr);
1159 lua_register(lstate, "read", &gate_lua_read);
1160 }
1161
1162 static int gate_lua_fileopen(lua_State* lstate)
1163 {
1164 gate_result_t ret = 0;
1165 gate_string_t str_path = GATE_STRING_INIT_EMPTY;
1166 gate_string_t str_flags = GATE_STRING_INIT_EMPTY;
1167
1168 do
1169 {
1170 gate_result_t result;
1171 gate_enumint_t openflags = GATE_STREAM_OPEN_READ;
1172 gate_bool_t truncate = false;
1173 gate_file_t f;
1174
1175 gate_size_t arg_count = gate_script_lua_cfunc_get_arg_count(lstate);
1176 if (arg_count < 1)
1177 {
1178 luaL_error(lstate, "Missing arguments");
1179 break;
1180 }
1181
1182 lua_stack_get_string(lstate, 1, &str_path);
1183 if (gate_string_is_empty(&str_path))
1184 {
1185 lua_pushnil(lstate);
1186 ret = 1;
1187 break;
1188 }
1189
1190 if (arg_count >= 2)
1191 {
1192 lua_stack_get_string(lstate, 2, &str_flags);
1193 }
1194 if (gate_string_equals_str(&str_flags, "r") || gate_string_is_empty(&str_flags))
1195 {
1196 openflags = GATE_STREAM_OPEN_READ;
1197 }
1198 else if (gate_string_equals_str(&str_flags, "r+"))
1199 {
1200 openflags = GATE_STREAM_OPEN_READWRITE;
1201 }
1202 else if (gate_string_equals_str(&str_flags, "w"))
1203 {
1204 openflags = GATE_STREAM_OPEN_WRITE;
1205 }
1206 else if (gate_string_equals_str(&str_flags, "w+"))
1207 {
1208 openflags = GATE_STREAM_OPEN_READWRITE;
1209 truncate = true;
1210 }
1211 else if (gate_string_equals_str(&str_flags, "a"))
1212 {
1213 openflags = GATE_STREAM_OPEN_APPENDWRITE;
1214 }
1215 else if (gate_string_equals_str(&str_flags, "a+"))
1216 {
1217 openflags = GATE_STREAM_OPEN_APPENDREADWRITE;
1218 }
1219 else
1220 {
1221 /* unsupported open-type */
1222 lua_pushnil(lstate);
1223 ret = 1;
1224 break;
1225 }
1226
1227 result = gate_file_open(&str_path, openflags, &f);
1228 if (GATE_FAILED(result))
1229 {
1230 /* error case */
1231 lua_pushnil(lstate);
1232 ret = 1;
1233 break;
1234 }
1235
1236 if (truncate)
1237 {
1238 gate_file_truncate(f);
1239 }
1240
1241 /* success case */
1242 lua_pushinteger(lstate, (lua_Integer)(gate_intptr_t)(void*)f);
1243 ret = 1;
1244 } while (0);
1245
1246 gate_string_release(&str_flags);
1247 gate_string_release(&str_path);
1248 return ret;
1249 }
1250
1251 static int gate_lua_fileclose(lua_State* lstate)
1252 {
1253 gate_result_t ret = 0;
1254
1255 do
1256 {
1257 gate_int32_t file_handle;
1258 gate_file_t f;
1259 gate_size_t arg_count = gate_script_lua_cfunc_get_arg_count(lstate);
1260
1261 if (arg_count < 1)
1262 {
1263 luaL_error(lstate, "Missing arguments");
1264 break;
1265 }
1266
1267 lua_stack_get_int(lstate, 1, &file_handle);
1268 f = (gate_file_t)(gate_intptr_t)file_handle;
1269
1270 gate_file_close(f);
1271 /* success case */
1272 } while (0);
1273
1274 return ret;
1275 }
1276
1277 static int gate_lua_fileread(lua_State* lstate)
1278 {
1279 gate_result_t ret = 0;
1280 char buffer[GATE_MAX_COPYBUFFER_LENGTH];
1281 char* ptr_buffer = &buffer[0];
1282
1283 do
1284 {
1285 gate_result_t result;
1286 gate_int32_t file_handle = 0;
1287 gate_int32_t read_len = 0;
1288 gate_file_t f;
1289 gate_size_t buffer_len;
1290 gate_size_t buffer_used = 0;
1291 gate_size_t arg_count = gate_script_lua_cfunc_get_arg_count(lstate);
1292 if (arg_count < 2)
1293 {
1294 luaL_error(lstate, "Missing arguments");
1295 break;
1296 }
1297
1298 lua_stack_get_int(lstate, 1, &file_handle);
1299 f = (gate_file_t)(gate_intptr_t)file_handle;
1300
1301 lua_stack_get_int(lstate, 2, &read_len);
1302
1303 if (read_len <= 0)
1304 {
1305 /* invalid read-length */
1306 lua_pushnil(lstate);
1307 ret = 1;
1308 break;
1309 }
1310
1311 buffer_len = (gate_size_t)read_len;
1312 if (buffer_len > sizeof(buffer))
1313 {
1314 ptr_buffer = gate_mem_alloc(buffer_len);
1315 if (NULL == ptr_buffer)
1316 {
1317 luaL_error(lstate, "Out of memory");
1318 break;
1319 }
1320 }
1321
1322 result = gate_file_read(f, ptr_buffer, buffer_len, &buffer_used);
1323 if (GATE_FAILED(result))
1324 {
1325 /* failed to read from file */
1326 lua_pushnil(lstate);
1327 ret = 1;
1328 break;
1329 }
1330
1331 /* succes case, return buffer content as string */
1332 lua_pushlstring(lstate, ptr_buffer, buffer_used);
1333 ret = 1;
1334 } while (0);
1335
1336 if (ptr_buffer && (ptr_buffer != &buffer[0]))
1337 {
1338 gate_mem_dealloc(ptr_buffer);
1339 }
1340
1341 return ret;
1342 }
1343
1344 static int gate_lua_filewrite(lua_State* lstate)
1345 {
1346 gate_result_t ret = 0;
1347 gate_string_t buffer = GATE_STRING_INIT_EMPTY;
1348
1349 do
1350 {
1351 gate_result_t result;
1352 gate_int32_t file_handle = 0;
1353 gate_file_t f;
1354 gate_size_t written;
1355 gate_size_t arg_count = gate_script_lua_cfunc_get_arg_count(lstate);
1356 if (arg_count < 2)
1357 {
1358 luaL_error(lstate, "Missing arguments");
1359 break;
1360 }
1361
1362 lua_stack_get_int(lstate, 1, &file_handle);
1363 f = (gate_file_t)(gate_intptr_t)file_handle;
1364
1365 lua_stack_get_string(lstate, 2, &buffer);
1366
1367 result = gate_file_write(f, gate_string_ptr(&buffer, 0), gate_string_length(&buffer), &written);
1368 if (GATE_FAILED(result))
1369 {
1370 /* failed to read from file */
1371 lua_pushnil(lstate);
1372 ret = 1;
1373 break;
1374 }
1375
1376 /* success case, return amount of written bytes */
1377 lua_pushinteger(lstate, (lua_Integer)written);
1378 ret = 1;
1379 } while (0);
1380
1381 gate_string_release(&buffer);
1382 return ret;
1383 }
1384
1385
1386
1387 static void add_fileaccess_feature(lua_State* lstate)
1388 {
1389 lua_register(lstate, "file_open", &gate_lua_fileopen);
1390 lua_register(lstate, "file_close", &gate_lua_fileclose);
1391 lua_register(lstate, "file_read", &gate_lua_fileread);
1392 lua_register(lstate, "file_write", &gate_lua_filewrite);
1393 }
1394
1395 gate_result_t gate_script_lua_add_feature(gate_script_lua_session_t* session, gate_script_lua_feature_enum_t feature)
1396 {
1397 lua_State* lstate = (lua_State*)session->state;
1398
1399 switch (feature)
1400 {
1401 case gate_script_lua_feature_console:
1402 add_console_feature(lstate);
1403 return GATE_RESULT_OK;
1404 case gate_script_lua_feature_fileaccess:
1405 add_fileaccess_feature(lstate);
1406 return GATE_RESULT_OK;
1407 case gate_script_lua_feature_filesystem:
1408 case gate_script_lua_feature_process:
1409 default:
1410 return GATE_RESULT_NOTSUPPORTED;
1411 }
1412 }
1413
1414 static int gate_script_lua_console_quit(lua_State* L)
1415 {
1416 gate_script_lua_session_t* ptr_session = gate_script_lua_get_session(L);
1417 if (ptr_session)
1418 {
1419 ptr_session->cancel = true;
1420 }
1421 return 0;
1422 }
1423
1424 gate_result_t gate_script_lua_console(gate_stream_t* console)
1425 {
1426 gate_result_t ret = GATE_RESULT_OK;
1427 gate_strbuilder_t builder = GATE_INIT_EMPTY;
1428
1429 do
1430 {
1431 gate_script_lua_session_t session = GATE_INIT_EMPTY;
1432 lua_State* lstate;
1433
1434 ret = gate_script_lua_init(&session);
1435 GATE_BREAK_IF_FAILED(ret);
1436
1437 ret = gate_script_lua_add_feature(&session, gate_script_lua_feature_console);
1438 GATE_BREAK_IF_FAILED(ret);
1439 ret = gate_script_lua_add_feature(&session, gate_script_lua_feature_fileaccess);
1440 GATE_BREAK_IF_FAILED(ret);
1441
1442 gate_strbuilder_create(&builder, 0);
1443
1444 lstate = (lua_State*)session.state;
1445 session.cancel = false;
1446
1447 lua_pushcfunction(lstate, &gate_script_lua_console_quit);
1448 lua_setglobal(lstate, "quit");
1449
1450 while (!session.cancel)
1451 {
1452 char buffer[4096];
1453 gate_size_t pos;
1454 gate_size_t buffer_used = 0;
1455
1456 if (gate_strbuilder_length(&builder) == 0)
1457 {
1458 gate_stream_print_cstr(console, "[LUA] > ");
1459 }
1460 else
1461 {
1462 gate_stream_print_cstr(console, " > ");
1463
1464 }
1465 ret = gate_stream_read_line(console, buffer, sizeof(buffer), &buffer_used);
1466 GATE_BREAK_IF_FAILED(ret);
1467
1468 pos = gate_str_find_last_not_of(buffer, buffer_used, " \r\n\t", 4);
1469 if (pos == GATE_STR_NPOS)
1470 {
1471 /* empty line */
1472 }
1473 else
1474 {
1475 gate_bool_t command_completed;
1476
1477 buffer_used = pos + 1;
1478 if (gate_str_ends_with(buffer, buffer_used, "\\", 1))
1479 {
1480 gate_strbuilder_append_text(&builder, buffer, buffer_used - 1);
1481 gate_strbuilder_append_cstr(&builder, "\n");
1482 command_completed = false;
1483 }
1484 else
1485 {
1486 gate_strbuilder_append_text(&builder, buffer, buffer_used);
1487 command_completed = true;
1488 }
1489 if (command_completed)
1490 {
1491 gate_string_t command = GATE_STRING_INIT_EMPTY;
1492 if (gate_strbuilder_to_string(&builder, &command))
1493 {
1494 ret = gate_script_lua_load_impl(lstate, &command, true);
1495 gate_strbuilder_release(&builder);
1496 gate_strbuilder_create(&builder, 0);
1497 if (GATE_SUCCEEDED(ret))
1498 {
1499 gate_stream_println_cstr(console, NULL);
1500 gate_stream_println_cstr(console, "[LUA] : OK (^_^)");
1501 }
1502 else
1503 {
1504 gate_stream_println_cstr(console, NULL);
1505 gate_stream_print_cstr(console, "[LUA] : ERROR ");
1506 gate_stream_print_int(console, ret);
1507 gate_stream_println_cstr(console, " (>_<)");
1508 ret = GATE_RESULT_OK;
1509 }
1510 }
1511 else
1512 {
1513 ret = GATE_RESULT_OUTOFMEMORY;
1514 }
1515 gate_string_release(&command);
1516 GATE_BREAK_IF_FAILED(ret);
1517 }
1518 }
1519
1520 }
1521 gate_script_lua_uninit(&session);
1522
1523 } while (0);
1524
1525 gate_strbuilder_release(&builder);
1526
1527 return ret;
1528 }
1529
1530 #endif /* GATE_SCRIPTING_LUA_USE_LUA */
1531
1532
1533 #if defined(GATE_SCRIPTING_LUA_NO_IMPL)
1534
1535 gate_result_t gate_script_lua_init(gate_script_lua_session_t* session)
1536 {
1537 GATE_UNUSED_ARG(session);
1538 return GATE_RESULT_NOTIMPLEMENTED;
1539 }
1540 gate_result_t gate_script_lua_uninit(gate_script_lua_session_t* session)
1541 {
1542 GATE_UNUSED_ARG(session);
1543 return GATE_RESULT_NOTIMPLEMENTED;
1544 }
1545
1546 gate_result_t gate_script_lua_reset(gate_script_lua_session_t* session)
1547 {
1548 GATE_UNUSED_ARG(session);
1549 return GATE_RESULT_NOTIMPLEMENTED;
1550 }
1551
1552 gate_result_t gate_script_lua_load(gate_script_lua_session_t* session, gate_string_t const* code)
1553 {
1554 GATE_UNUSED_ARG(session);
1555 GATE_UNUSED_ARG(code);
1556 return GATE_RESULT_NOTIMPLEMENTED;
1557 }
1558
1559 gate_result_t gate_script_lua_invoke(gate_script_lua_session_t* session,
1560 gate_string_t const* func_name,
1561 gate_value_t* args, gate_size_t arg_count,
1562 gate_value_t* ret_val)
1563 {
1564 GATE_UNUSED_ARG(session);
1565 GATE_UNUSED_ARG(func_name);
1566 GATE_UNUSED_ARG(args);
1567 GATE_UNUSED_ARG(arg_count);
1568 GATE_UNUSED_ARG(ret_val);
1569 return GATE_RESULT_NOTIMPLEMENTED;
1570 }
1571
1572 gate_result_t gate_script_lua_set_var(gate_script_lua_session_t* session,
1573 gate_string_t const* name, gate_value_t const* value)
1574 {
1575 GATE_UNUSED_ARG(session);
1576 GATE_UNUSED_ARG(name);
1577 GATE_UNUSED_ARG(value);
1578 return GATE_RESULT_NOTIMPLEMENTED;
1579 }
1580
1581 gate_result_t gate_script_lua_get_var(gate_script_lua_session_t* session,
1582 gate_string_t const* name, gate_value_t* value)
1583 {
1584 GATE_UNUSED_ARG(session);
1585 GATE_UNUSED_ARG(name);
1586 GATE_UNUSED_ARG(value);
1587 return GATE_RESULT_NOTIMPLEMENTED;
1588 }
1589
1590 gate_result_t gate_script_lua_add_feature(gate_script_lua_session_t* session, gate_script_lua_feature_enum_t feature)
1591 {
1592 GATE_UNUSED_ARG(session);
1593 GATE_UNUSED_ARG(feature);
1594 return GATE_RESULT_NOTIMPLEMENTED;
1595 }
1596
1597 gate_result_t gate_script_lua_console(gate_stream_t* console)
1598 {
1599 GATE_UNUSED_ARG(console);
1600 return GATE_RESULT_NOTIMPLEMENTED;
1601 }
1602
1603 #endif /* GATE_SCRIPTING_LUA_NO_IMPL */
1604