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