1 /* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
2
3 /*
4 * Copyright © 2014 Rob Clark <[email protected]>
5 * SPDX-License-Identifier: MIT
6 *
7 * Authors:
8 * Rob Clark <[email protected]>
9 */
10
11 #define LUA_COMPAT_APIINTCASTS
12
13 #include <assert.h>
14 #include <lauxlib.h>
15 #include <lua.h>
16 #include <lualib.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include "util/u_math.h"
21
22 #include "cffdec.h"
23 #include "rnnutil.h"
24 #include "script.h"
25
26 static lua_State *L;
27
28 #if 0
29 #define DBG(fmt, ...) \
30 do { \
31 printf(" ** %s:%d ** " fmt "\n", __func__, __LINE__, ##__VA_ARGS__); \
32 } while (0)
33 #else
34 #define DBG(fmt, ...) \
35 do { \
36 } while (0)
37 #endif
38
39 /* An rnn based decoder, which can either be decoding current register
40 * values, or domain based decoding of a pm4 packet.
41 *
42 */
43 struct rnndec {
44 struct rnn base;
45
46 /* for pm4 packet decoding: */
47 uint32_t sizedwords;
48 uint32_t *dwords;
49 };
50
51 static inline struct rnndec *
to_rnndec(struct rnn * rnn)52 to_rnndec(struct rnn *rnn)
53 {
54 return (struct rnndec *)rnn;
55 }
56
57 static uint32_t
rnn_val(struct rnn * rnn,uint32_t regbase)58 rnn_val(struct rnn *rnn, uint32_t regbase)
59 {
60 struct rnndec *rnndec = to_rnndec(rnn);
61
62 if (!rnndec->sizedwords) {
63 return reg_val(regbase);
64 } else if (regbase < rnndec->sizedwords) {
65 return rnndec->dwords[regbase];
66 } else {
67 // XXX throw an error
68 return -1;
69 }
70 }
71
72 /* does not return */
73 static void
error(const char * fmt)74 error(const char *fmt)
75 {
76 fprintf(stderr, fmt, lua_tostring(L, -1));
77 exit(1);
78 }
79
80 /*
81 * An enum type that can be used as string or number:
82 */
83
84 struct rnndenum {
85 const char *str;
86 int val;
87 };
88
89 static int
l_meta_rnn_enum_tostring(lua_State * L)90 l_meta_rnn_enum_tostring(lua_State *L)
91 {
92 struct rnndenum *e = lua_touserdata(L, 1);
93 if (e->str) {
94 lua_pushstring(L, e->str);
95 } else {
96 char buf[32];
97 sprintf(buf, "%u", e->val);
98 lua_pushstring(L, buf);
99 }
100 return 1;
101 }
102
103 /* so, this doesn't actually seem to be implemented yet, but hopefully
104 * some day lua comes to it's senses
105 */
106 static int
l_meta_rnn_enum_tonumber(lua_State * L)107 l_meta_rnn_enum_tonumber(lua_State *L)
108 {
109 struct rnndenum *e = lua_touserdata(L, 1);
110 lua_pushinteger(L, e->val);
111 return 1;
112 }
113
114 static const struct luaL_Reg l_meta_rnn_enum[] = {
115 {"__tostring", l_meta_rnn_enum_tostring},
116 {"__tonumber", l_meta_rnn_enum_tonumber},
117 {NULL, NULL} /* sentinel */
118 };
119
120 static void
pushenum(struct lua_State * L,int val,struct rnnenum * info)121 pushenum(struct lua_State *L, int val, struct rnnenum *info)
122 {
123 struct rnndenum *e = lua_newuserdata(L, sizeof(*e));
124
125 e->val = val;
126 e->str = NULL;
127
128 for (int i = 0; i < info->valsnum; i++) {
129 if (info->vals[i]->valvalid && (info->vals[i]->value == val)) {
130 e->str = info->vals[i]->name;
131 break;
132 }
133 }
134
135 luaL_newmetatable(L, "rnnmetaenum");
136 luaL_setfuncs(L, l_meta_rnn_enum, 0);
137 lua_pop(L, 1);
138
139 luaL_setmetatable(L, "rnnmetaenum");
140 }
141
142 /* Expose rnn decode to script environment as "rnn" library:
143 */
144
145 struct rnndoff {
146 struct rnn *rnn;
147 struct rnndelem *elem;
148 uint64_t offset;
149 };
150
151 static void
push_rnndoff(lua_State * L,struct rnn * rnn,struct rnndelem * elem,uint64_t offset)152 push_rnndoff(lua_State *L, struct rnn *rnn, struct rnndelem *elem,
153 uint64_t offset)
154 {
155 struct rnndoff *rnndoff = lua_newuserdata(L, sizeof(*rnndoff));
156 rnndoff->rnn = rnn;
157 rnndoff->elem = elem;
158 rnndoff->offset = offset;
159 }
160
161 static int l_rnn_etype_array(lua_State *L, struct rnn *rnn,
162 struct rnndelem *elem, uint64_t offset);
163 static int l_rnn_etype_reg(lua_State *L, struct rnn *rnn, struct rnndelem *elem,
164 uint64_t offset);
165
166 static int
pushdecval(struct lua_State * L,struct rnn * rnn,uint64_t regval,struct rnntypeinfo * info)167 pushdecval(struct lua_State *L, struct rnn *rnn, uint64_t regval,
168 struct rnntypeinfo *info)
169 {
170 union rnndecval val;
171 switch (rnn_decodelem(rnn, info, regval, &val)) {
172 case RNN_TTYPE_ENUM:
173 case RNN_TTYPE_INLINE_ENUM:
174 pushenum(L, val.i, info->eenum);
175 return 1;
176 case RNN_TTYPE_INT:
177 lua_pushinteger(L, val.i);
178 return 1;
179 case RNN_TTYPE_UINT:
180 case RNN_TTYPE_HEX:
181 lua_pushunsigned(L, val.u);
182 return 1;
183 case RNN_TTYPE_FLOAT:
184 lua_pushnumber(L, uif(val.u));
185 return 1;
186 case RNN_TTYPE_BOOLEAN:
187 lua_pushboolean(L, val.u);
188 return 1;
189 case RNN_TTYPE_INVALID:
190 default:
191 return 0;
192 }
193 }
194
195 static int
l_rnn_etype(lua_State * L,struct rnn * rnn,struct rnndelem * elem,uint64_t offset)196 l_rnn_etype(lua_State *L, struct rnn *rnn, struct rnndelem *elem,
197 uint64_t offset)
198 {
199 int ret;
200 uint64_t regval;
201 DBG("elem=%p (%d), offset=%lu", elem, elem->type, offset);
202 switch (elem->type) {
203 case RNN_ETYPE_REG:
204 /* if a register has no bitfields, just return
205 * the raw value:
206 */
207 regval = rnn_val(rnn, offset);
208 if (elem->width == 64)
209 regval |= (uint64_t)rnn_val(rnn, offset + 1) << 32;
210 regval <<= elem->typeinfo.shr;
211 ret = pushdecval(L, rnn, regval, &elem->typeinfo);
212 if (ret)
213 return ret;
214 return l_rnn_etype_reg(L, rnn, elem, offset);
215 case RNN_ETYPE_ARRAY:
216 return l_rnn_etype_array(L, rnn, elem, offset);
217 default:
218 /* hmm.. */
219 printf("unhandled type: %d\n", elem->type);
220 return 0;
221 }
222 }
223
224 /*
225 * Struct Object:
226 * To implement stuff like 'RB_MRT[n].CONTROL' we need a struct-object
227 * to represent the current array index (ie. 'RB_MRT[n]')
228 */
229
230 static int
l_rnn_struct_meta_index(lua_State * L)231 l_rnn_struct_meta_index(lua_State *L)
232 {
233 struct rnndoff *rnndoff = lua_touserdata(L, 1);
234 const char *name = lua_tostring(L, 2);
235 struct rnndelem *elem = rnndoff->elem;
236 int i;
237
238 for (i = 0; i < elem->subelemsnum; i++) {
239 struct rnndelem *subelem = elem->subelems[i];
240 if (!strcmp(name, subelem->name)) {
241 return l_rnn_etype(L, rnndoff->rnn, subelem,
242 rnndoff->offset + subelem->offset);
243 }
244 }
245
246 return 0;
247 }
248
249 static const struct luaL_Reg l_meta_rnn_struct[] = {
250 {"__index", l_rnn_struct_meta_index}, {NULL, NULL} /* sentinel */
251 };
252
253 static int
l_rnn_etype_struct(lua_State * L,struct rnn * rnn,struct rnndelem * elem,uint64_t offset)254 l_rnn_etype_struct(lua_State *L, struct rnn *rnn, struct rnndelem *elem,
255 uint64_t offset)
256 {
257 push_rnndoff(L, rnn, elem, offset);
258
259 luaL_newmetatable(L, "rnnmetastruct");
260 luaL_setfuncs(L, l_meta_rnn_struct, 0);
261 lua_pop(L, 1);
262
263 luaL_setmetatable(L, "rnnmetastruct");
264
265 return 1;
266 }
267
268 /*
269 * Array Object:
270 */
271
272 static int
l_rnn_array_meta_index(lua_State * L)273 l_rnn_array_meta_index(lua_State *L)
274 {
275 struct rnndoff *rnndoff = lua_touserdata(L, 1);
276 int idx = lua_tointeger(L, 2);
277 struct rnndelem *elem = rnndoff->elem;
278 uint64_t offset = rnndoff->offset + (elem->stride * idx);
279
280 DBG("rnndoff=%p, idx=%d, numsubelems=%d", rnndoff, idx,
281 rnndoff->elem->subelemsnum);
282
283 /* if just a single sub-element, it is directly a register,
284 * otherwise we need to accumulate the array index while
285 * we wait for the register name within the array..
286 */
287 if (elem->subelemsnum == 1) {
288 return l_rnn_etype(L, rnndoff->rnn, elem->subelems[0], offset);
289 } else {
290 return l_rnn_etype_struct(L, rnndoff->rnn, elem, offset);
291 }
292
293 return 0;
294 }
295
296 static const struct luaL_Reg l_meta_rnn_array[] = {
297 {"__index", l_rnn_array_meta_index}, {NULL, NULL} /* sentinel */
298 };
299
300 static int
l_rnn_etype_array(lua_State * L,struct rnn * rnn,struct rnndelem * elem,uint64_t offset)301 l_rnn_etype_array(lua_State *L, struct rnn *rnn, struct rnndelem *elem,
302 uint64_t offset)
303 {
304 push_rnndoff(L, rnn, elem, offset);
305
306 luaL_newmetatable(L, "rnnmetaarray");
307 luaL_setfuncs(L, l_meta_rnn_array, 0);
308 lua_pop(L, 1);
309
310 luaL_setmetatable(L, "rnnmetaarray");
311
312 return 1;
313 }
314
315 /*
316 * Register element:
317 */
318
319 static int
l_rnn_reg_meta_index(lua_State * L)320 l_rnn_reg_meta_index(lua_State *L)
321 {
322 struct rnndoff *rnndoff = lua_touserdata(L, 1);
323 const char *name = lua_tostring(L, 2);
324 struct rnndelem *elem = rnndoff->elem;
325 struct rnntypeinfo *info = &elem->typeinfo;
326 struct rnnbitfield **bitfields;
327 int bitfieldsnum;
328 int i;
329
330 switch (info->type) {
331 case RNN_TTYPE_BITSET:
332 bitfields = info->ebitset->bitfields;
333 bitfieldsnum = info->ebitset->bitfieldsnum;
334 break;
335 case RNN_TTYPE_INLINE_BITSET:
336 bitfields = info->bitfields;
337 bitfieldsnum = info->bitfieldsnum;
338 break;
339 default:
340 printf("invalid register type: %d\n", info->type);
341 return 0;
342 }
343
344 for (i = 0; i < bitfieldsnum; i++) {
345 struct rnnbitfield *bf = bitfields[i];
346 if (!strcmp(name, bf->name)) {
347 uint32_t regval = rnn_val(rnndoff->rnn, rnndoff->offset);
348
349 regval &= typeinfo_mask(&bf->typeinfo);
350 regval >>= bf->typeinfo.low;
351 regval <<= bf->typeinfo.shr;
352
353 DBG("name=%s, info=%p, subelemsnum=%d, type=%d, regval=%x", name, info,
354 rnndoff->elem->subelemsnum, bf->typeinfo.type, regval);
355
356 return pushdecval(L, rnndoff->rnn, regval, &bf->typeinfo);
357 }
358 }
359
360 printf("invalid member: %s\n", name);
361 return 0;
362 }
363
364 static int
l_rnn_reg_meta_tostring(lua_State * L)365 l_rnn_reg_meta_tostring(lua_State *L)
366 {
367 struct rnndoff *rnndoff = lua_touserdata(L, 1);
368 uint32_t regval = rnn_val(rnndoff->rnn, rnndoff->offset);
369 struct rnndecaddrinfo *info = rnn_reginfo(rnndoff->rnn, rnndoff->offset);
370 char *decoded;
371 if (info && info->typeinfo) {
372 decoded = rnndec_decodeval(rnndoff->rnn->vc, info->typeinfo, regval);
373 } else {
374 asprintf(&decoded, "%08x", regval);
375 }
376 lua_pushstring(L, decoded);
377 free(decoded);
378 rnn_reginfo_free(info);
379 return 1;
380 }
381
382 static int
l_rnn_reg_meta_tonumber(lua_State * L)383 l_rnn_reg_meta_tonumber(lua_State *L)
384 {
385 struct rnndoff *rnndoff = lua_touserdata(L, 1);
386 uint32_t regval = rnn_val(rnndoff->rnn, rnndoff->offset);
387
388 regval <<= rnndoff->elem->typeinfo.shr;
389
390 lua_pushnumber(L, regval);
391 return 1;
392 }
393
394 static const struct luaL_Reg l_meta_rnn_reg[] = {
395 {"__index", l_rnn_reg_meta_index},
396 {"__tostring", l_rnn_reg_meta_tostring},
397 {"__tonumber", l_rnn_reg_meta_tonumber},
398 {NULL, NULL} /* sentinel */
399 };
400
401 static int
l_rnn_etype_reg(lua_State * L,struct rnn * rnn,struct rnndelem * elem,uint64_t offset)402 l_rnn_etype_reg(lua_State *L, struct rnn *rnn, struct rnndelem *elem,
403 uint64_t offset)
404 {
405 push_rnndoff(L, rnn, elem, offset);
406
407 luaL_newmetatable(L, "rnnmetareg");
408 luaL_setfuncs(L, l_meta_rnn_reg, 0);
409 lua_pop(L, 1);
410
411 luaL_setmetatable(L, "rnnmetareg");
412
413 return 1;
414 }
415
416 /*
417 *
418 */
419
420 static int
l_rnn_meta_index(lua_State * L)421 l_rnn_meta_index(lua_State *L)
422 {
423 struct rnn *rnn = lua_touserdata(L, 1);
424 const char *name = lua_tostring(L, 2);
425 struct rnndelem *elem;
426
427 elem = rnn_regelem(rnn, name);
428 if (!elem)
429 return 0;
430
431 return l_rnn_etype(L, rnn, elem, elem->offset);
432 }
433
434 static int
l_rnn_meta_gc(lua_State * L)435 l_rnn_meta_gc(lua_State *L)
436 {
437 // TODO
438 // struct rnn *rnn = lua_touserdata(L, 1);
439 // rnn_deinit(rnn);
440 return 0;
441 }
442
443 static const struct luaL_Reg l_meta_rnn[] = {
444 {"__index", l_rnn_meta_index},
445 {"__gc", l_rnn_meta_gc},
446 {NULL, NULL} /* sentinel */
447 };
448
449 static int
l_rnn_init(lua_State * L)450 l_rnn_init(lua_State *L)
451 {
452 const char *gpuname = lua_tostring(L, 1);
453 struct rnndec *rnndec = lua_newuserdata(L, sizeof(*rnndec));
454 _rnn_init(&rnndec->base, 0);
455 rnn_load(&rnndec->base, gpuname);
456 rnndec->sizedwords = 0;
457
458 luaL_newmetatable(L, "rnnmeta");
459 luaL_setfuncs(L, l_meta_rnn, 0);
460 lua_pop(L, 1);
461
462 luaL_setmetatable(L, "rnnmeta");
463
464 return 1;
465 }
466
467 static int
l_rnn_enumname(lua_State * L)468 l_rnn_enumname(lua_State *L)
469 {
470 struct rnn *rnn = lua_touserdata(L, 1);
471 const char *name = lua_tostring(L, 2);
472 uint32_t val = (uint32_t)lua_tonumber(L, 3);
473 lua_pushstring(L, rnn_enumname(rnn, name, val));
474 return 1;
475 }
476
477 static int
l_rnn_regname(lua_State * L)478 l_rnn_regname(lua_State *L)
479 {
480 struct rnn *rnn = lua_touserdata(L, 1);
481 uint32_t regbase = (uint32_t)lua_tonumber(L, 2);
482 lua_pushstring(L, rnn_regname(rnn, regbase, 1));
483 return 1;
484 }
485
486 static int
l_rnn_regval(lua_State * L)487 l_rnn_regval(lua_State *L)
488 {
489 struct rnn *rnn = lua_touserdata(L, 1);
490 uint32_t regbase = (uint32_t)lua_tonumber(L, 2);
491 uint32_t regval = (uint32_t)lua_tonumber(L, 3);
492 struct rnndecaddrinfo *info = rnn_reginfo(rnn, regbase);
493 char *decoded;
494 if (info && info->typeinfo) {
495 decoded = rnndec_decodeval(rnn->vc, info->typeinfo, regval);
496 } else {
497 asprintf(&decoded, "%08x", regval);
498 }
499 lua_pushstring(L, decoded);
500 free(decoded);
501 rnn_reginfo_free(info);
502 return 1;
503 }
504
505 static const struct luaL_Reg l_rnn[] = {
506 {"init", l_rnn_init},
507 {"enumname", l_rnn_enumname},
508 {"regname", l_rnn_regname},
509 {"regval", l_rnn_regval},
510 {NULL, NULL} /* sentinel */
511 };
512
513 /* Expose the register state to script enviroment as a "regs" library:
514 */
515
516 static int
l_reg_written(lua_State * L)517 l_reg_written(lua_State *L)
518 {
519 uint32_t regbase = (uint32_t)lua_tonumber(L, 1);
520 lua_pushnumber(L, reg_written(regbase));
521 return 1;
522 }
523
524 static int
l_reg_lastval(lua_State * L)525 l_reg_lastval(lua_State *L)
526 {
527 uint32_t regbase = (uint32_t)lua_tonumber(L, 1);
528 lua_pushnumber(L, reg_lastval(regbase));
529 return 1;
530 }
531
532 static int
l_reg_val(lua_State * L)533 l_reg_val(lua_State *L)
534 {
535 uint32_t regbase = (uint32_t)lua_tonumber(L, 1);
536 lua_pushnumber(L, reg_val(regbase));
537 return 1;
538 }
539
540 static const struct luaL_Reg l_regs[] = {
541 {"written", l_reg_written},
542 {"lastval", l_reg_lastval},
543 {"val", l_reg_val},
544 {NULL, NULL} /* sentinel */
545 };
546
547 /* Expose API to lookup snapshot buffers:
548 */
549
550 uint64_t gpubaseaddr(uint64_t gpuaddr);
551 unsigned hostlen(uint64_t gpuaddr);
552
553 /* given address, return base-address of buffer: */
554 static int
l_bo_base(lua_State * L)555 l_bo_base(lua_State *L)
556 {
557 uint64_t addr = (uint64_t)lua_tonumber(L, 1);
558 lua_pushnumber(L, gpubaseaddr(addr));
559 return 1;
560 }
561
562 /* given address, return the remaining size of the buffer: */
563 static int
l_bo_size(lua_State * L)564 l_bo_size(lua_State *L)
565 {
566 uint64_t addr = (uint64_t)lua_tonumber(L, 1);
567 lua_pushnumber(L, hostlen(addr));
568 return 1;
569 }
570
571 static const struct luaL_Reg l_bos[] = {
572 {"base", l_bo_base}, {"size", l_bo_size}, {NULL, NULL} /* sentinel */
573 };
574
575 static void
openlib(const char * lib,const luaL_Reg * reg)576 openlib(const char *lib, const luaL_Reg *reg)
577 {
578 lua_newtable(L);
579 luaL_setfuncs(L, reg, 0);
580 lua_setglobal(L, lib);
581 }
582
583 /* called at start to load the script: */
584 int
script_load(const char * file)585 script_load(const char *file)
586 {
587 int ret;
588
589 assert(!L);
590
591 L = luaL_newstate();
592 luaL_openlibs(L);
593 openlib("bos", l_bos);
594 openlib("regs", l_regs);
595 openlib("rnn", l_rnn);
596
597 ret = luaL_loadfile(L, file);
598 if (ret)
599 error("%s\n");
600
601 ret = lua_pcall(L, 0, LUA_MULTRET, 0);
602 if (ret)
603 error("%s\n");
604
605 return 0;
606 }
607
608 /* called at start of each cmdstream file: */
609 void
script_start_cmdstream(const char * name)610 script_start_cmdstream(const char *name)
611 {
612 if (!L)
613 return;
614
615 lua_getglobal(L, "start_cmdstream");
616
617 /* if no handler just ignore it: */
618 if (!lua_isfunction(L, -1)) {
619 lua_pop(L, 1);
620 return;
621 }
622
623 lua_pushstring(L, name);
624
625 /* do the call (1 arguments, 0 result) */
626 if (lua_pcall(L, 1, 0, 0) != 0)
627 error("error running function `f': %s\n");
628 }
629
630 /* called at each DRAW_INDX, calls script drawidx fxn to process
631 * the current state
632 */
633 void
script_draw(const char * primtype,uint32_t nindx)634 script_draw(const char *primtype, uint32_t nindx)
635 {
636 if (!L)
637 return;
638
639 lua_getglobal(L, "draw");
640
641 /* if no handler just ignore it: */
642 if (!lua_isfunction(L, -1)) {
643 lua_pop(L, 1);
644 return;
645 }
646
647 lua_pushstring(L, primtype);
648 lua_pushnumber(L, nindx);
649
650 /* do the call (2 arguments, 0 result) */
651 if (lua_pcall(L, 2, 0, 0) != 0)
652 error("error running function `f': %s\n");
653 }
654
655 static int
l_rnn_meta_dom_index(lua_State * L)656 l_rnn_meta_dom_index(lua_State *L)
657 {
658 struct rnn *rnn = lua_touserdata(L, 1);
659 uint32_t offset = (uint32_t)lua_tonumber(L, 2);
660 struct rnndelem *elem;
661
662 /* TODO might be nicer if the arg isn't a number, to search the domain
663 * for matching bitfields.. so that the script could do something like
664 * 'pkt.WIDTH' insteadl of 'pkt[1].WIDTH', ie. not have to remember the
665 * offset of the dword containing the bitfield..
666 */
667
668 elem = rnn_regoff(rnn, offset);
669 if (!elem)
670 return 0;
671
672 return l_rnn_etype(L, rnn, elem, elem->offset);
673 }
674
675 /*
676 * A wrapper object for rnndomain based decoding of an array of dwords
677 * (ie. for pm4 packet decoding). Mostly re-uses the register-value
678 * decoding for the individual dwords and bitfields.
679 */
680
681 static int
l_rnn_meta_dom_gc(lua_State * L)682 l_rnn_meta_dom_gc(lua_State *L)
683 {
684 // TODO
685 // struct rnn *rnn = lua_touserdata(L, 1);
686 // rnn_deinit(rnn);
687 return 0;
688 }
689
690 static const struct luaL_Reg l_meta_rnn_dom[] = {
691 {"__index", l_rnn_meta_dom_index},
692 {"__gc", l_rnn_meta_dom_gc},
693 {NULL, NULL} /* sentinel */
694 };
695
696 /* called to general pm4 packet decoding, such as texture/sampler state
697 */
698 void
script_packet(uint32_t * dwords,uint32_t sizedwords,struct rnn * rnn,struct rnndomain * dom)699 script_packet(uint32_t *dwords, uint32_t sizedwords, struct rnn *rnn,
700 struct rnndomain *dom)
701 {
702 if (!L)
703 return;
704
705 lua_getglobal(L, dom->name);
706
707 /* if no handler for the packet, just ignore it: */
708 if (!lua_isfunction(L, -1)) {
709 lua_pop(L, 1);
710 return;
711 }
712
713 struct rnndec *rnndec = lua_newuserdata(L, sizeof(*rnndec));
714
715 rnndec->base = *rnn;
716 rnndec->base.dom[0] = dom;
717 rnndec->base.dom[1] = NULL;
718 rnndec->dwords = dwords;
719 rnndec->sizedwords = sizedwords;
720
721 luaL_newmetatable(L, "rnnmetadom");
722 luaL_setfuncs(L, l_meta_rnn_dom, 0);
723 lua_pop(L, 1);
724
725 luaL_setmetatable(L, "rnnmetadom");
726
727 lua_pushnumber(L, sizedwords);
728
729 if (lua_pcall(L, 2, 0, 0) != 0)
730 error("error running function `f': %s\n");
731 }
732
733 /* helper to call fxn that takes and returns void: */
734 static void
simple_call(const char * name)735 simple_call(const char *name)
736 {
737 if (!L)
738 return;
739
740 lua_getglobal(L, name);
741
742 /* if no handler just ignore it: */
743 if (!lua_isfunction(L, -1)) {
744 lua_pop(L, 1);
745 return;
746 }
747
748 /* do the call (0 arguments, 0 result) */
749 if (lua_pcall(L, 0, 0, 0) != 0)
750 error("error running function `f': %s\n");
751 }
752
753 /* called at end of each cmdstream file: */
754 void
script_end_cmdstream(void)755 script_end_cmdstream(void)
756 {
757 simple_call("end_cmdstream");
758 }
759
760 /* called at start of submit/issueibcmds: */
761 void
script_start_submit(void)762 script_start_submit(void)
763 {
764 simple_call("start_submit");
765 }
766
767 /* called at end of submit/issueibcmds: */
768 void
script_end_submit(void)769 script_end_submit(void)
770 {
771 simple_call("end_submit");
772 }
773
774 /* called after last cmdstream file: */
775 void
script_finish(void)776 script_finish(void)
777 {
778 if (!L)
779 return;
780
781 simple_call("finish");
782
783 lua_close(L);
784 L = NULL;
785 }
786