1 /* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */ 2 3 /* 4 * Copyright (C) 2014 Rob Clark <robclark (at) freedesktop.org> 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 <robclark (at) freedesktop.org> 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