GCC Code Coverage Report


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