00001
00002 #include "system.h"
00003
00004 #ifdef WITH_LUA
00005 #include <rpmio.h>
00006 #include <rpmmacro.h>
00007 #include <rpmerr.h>
00008 #include <rpmurl.h>
00009 #include <rpmhook.h>
00010
00011 #include <lua.h>
00012 #include <lualib.h>
00013 #include <lauxlib.h>
00014 #include <lposix.h>
00015 #include <lrexlib.h>
00016
00017 #include <unistd.h>
00018 #include <assert.h>
00019
00020 #define _RPMLUA_INTERNAL
00021 #include "rpmlua.h"
00022
00023 #include "debug.h"
00024
00025 #if !defined(HAVE_VSNPRINTF)
00026 static inline int vsnprintf(char * buf, int nb,
00027 const char * fmt, va_list ap)
00028 {
00029 return vsprintf(buf, fmt, ap);
00030 }
00031 #endif
00032
00033 #define INITSTATE(_lua, lua) \
00034 rpmlua lua = _lua ? _lua : \
00035 (globalLuaState ? globalLuaState : \
00036 \
00037 (globalLuaState = rpmluaNew()) \
00038 \
00039 )
00040
00041
00042 static rpmlua globalLuaState = NULL;
00043
00044 static int luaopen_rpm(lua_State *L)
00045 ;
00046 static int rpm_print(lua_State *L)
00047
00048 ;
00049
00050 rpmlua rpmluaNew()
00051 {
00052 rpmlua lua = (rpmlua) xcalloc(1, sizeof(*lua));
00053 lua_State *L = lua_open();
00054 struct stat st;
00055
00056
00057 static const luaL_reg lualibs[] = {
00058 {"base", luaopen_base},
00059 {"table", luaopen_table},
00060 {"io", luaopen_io},
00061 {"string", luaopen_string},
00062 {"debug", luaopen_debug},
00063 {"loadlib", luaopen_loadlib},
00064 {"posix", luaopen_posix},
00065 {"rex", luaopen_rex},
00066 {"rpm", luaopen_rpm},
00067 {NULL, NULL},
00068 };
00069
00070 const luaL_reg *lib = lualibs;
00071
00072
00073 lua->L = L;
00074 for (; lib->name; lib++) {
00075
00076 (void) lib->func(L);
00077
00078 lua_settop(L, 0);
00079 }
00080 lua_pushliteral(L, "LUA_PATH");
00081 lua_pushstring(L, RPMCONFIGDIR "/lua/?.lua");
00082 lua_rawset(L, LUA_GLOBALSINDEX);
00083 lua_pushliteral(L, "print");
00084 lua_pushcfunction(L, rpm_print);
00085 lua_rawset(L, LUA_GLOBALSINDEX);
00086 rpmluaSetData(lua, "lua", lua);
00087 if (stat(RPMCONFIGDIR "/init.lua", &st) != -1)
00088 (void)rpmluaRunScriptFile(lua, RPMCONFIGDIR "/init.lua");
00089 return lua;
00090 }
00091
00092 void *rpmluaFree(rpmlua lua)
00093 {
00094 if (lua) {
00095 if (lua->L) lua_close(lua->L);
00096 free(lua->printbuf);
00097 free(lua);
00098 }
00099 return NULL;
00100 }
00101
00102 void rpmluaSetData(rpmlua _lua, const char *key, const void *data)
00103 {
00104 INITSTATE(_lua, lua);
00105 lua_State *L = lua->L;
00106 lua_pushliteral(L, "rpm_");
00107 lua_pushstring(L, key);
00108 lua_concat(L, 2);
00109 if (data == NULL)
00110 lua_pushnil(L);
00111 else
00112 lua_pushlightuserdata(L, (void *)data);
00113 lua_rawset(L, LUA_REGISTRYINDEX);
00114 }
00115
00116 static void *getdata(lua_State *L, const char *key)
00117
00118 {
00119 void *ret = NULL;
00120 lua_pushliteral(L, "rpm_");
00121 lua_pushstring(L, key);
00122 lua_concat(L, 2);
00123 lua_rawget(L, LUA_REGISTRYINDEX);
00124
00125 if (lua_islightuserdata(L, -1))
00126 ret = lua_touserdata(L, -1);
00127
00128 lua_pop(L, 1);
00129 return ret;
00130 }
00131
00132 void *rpmluaGetData(rpmlua _lua, const char *key)
00133 {
00134 INITSTATE(_lua, lua);
00135 return getdata(lua->L, key);
00136 }
00137
00138 void rpmluaSetPrintBuffer(rpmlua _lua, int flag)
00139 {
00140 INITSTATE(_lua, lua);
00141 lua->storeprint = flag;
00142 free(lua->printbuf);
00143 lua->printbuf = NULL;
00144 lua->printbufsize = 0;
00145 }
00146
00147 const char *rpmluaGetPrintBuffer(rpmlua _lua)
00148 {
00149 INITSTATE(_lua, lua);
00150 return lua->printbuf;
00151 }
00152
00153 static int pushvar(lua_State *L, rpmluavType type, void *value)
00154
00155 {
00156 int ret = 0;
00157 switch (type) {
00158 case RPMLUAV_NIL:
00159 lua_pushnil(L);
00160 break;
00161 case RPMLUAV_STRING:
00162 lua_pushstring(L, *((char **)value));
00163 break;
00164 case RPMLUAV_NUMBER:
00165 lua_pushnumber(L, *((double *)value));
00166 break;
00167 default:
00168 ret = -1;
00169 break;
00170 }
00171 return ret;
00172 }
00173
00174 void rpmluaSetVar(rpmlua _lua, rpmluav var)
00175 {
00176 INITSTATE(_lua, lua);
00177 lua_State *L = lua->L;
00178 if (var->listmode && lua->pushsize > 0) {
00179 if (var->keyType != RPMLUAV_NUMBER || var->key.num == (double)0) {
00180 var->keyType = RPMLUAV_NUMBER;
00181 var->key.num = (double) luaL_getn(L, -1);
00182 }
00183 var->key.num++;
00184 }
00185 if (!var->listmode || lua->pushsize > 0) {
00186 if (lua->pushsize == 0)
00187 lua_pushvalue(L, LUA_GLOBALSINDEX);
00188 if (pushvar(L, var->keyType, &var->key) != -1) {
00189 if (pushvar(L, var->valueType, &var->value) != -1)
00190 lua_rawset(L, -3);
00191 else
00192 lua_pop(L, 1);
00193 }
00194 if (lua->pushsize == 0)
00195 lua_pop(L, 1);
00196 }
00197 }
00198
00199 static void popvar(lua_State *L, rpmluavType *type, void *value)
00200
00201 {
00202 switch (lua_type(L, -1)) {
00203 case LUA_TSTRING:
00204 *type = RPMLUAV_STRING;
00205
00206 *((const char **)value) = lua_tostring(L, -1);
00207
00208 break;
00209 case LUA_TNUMBER:
00210 *type = RPMLUAV_NUMBER;
00211 *((double *)value) = lua_tonumber(L, -1);
00212 break;
00213 default:
00214 *type = RPMLUAV_NIL;
00215 *((void **)value) = NULL;
00216 break;
00217 }
00218 lua_pop(L, 1);
00219 }
00220
00221 void rpmluaGetVar(rpmlua _lua, rpmluav var)
00222 {
00223 INITSTATE(_lua, lua);
00224 lua_State *L = lua->L;
00225 if (!var->listmode) {
00226 if (lua->pushsize == 0)
00227 lua_pushvalue(L, LUA_GLOBALSINDEX);
00228 if (pushvar(L, var->keyType, &var->key) != -1) {
00229 lua_rawget(L, -2);
00230 popvar(L, &var->valueType, &var->value);
00231 }
00232 if (lua->pushsize == 0)
00233 lua_pop(L, 1);
00234 } else if (lua->pushsize > 0) {
00235 (void) pushvar(L, var->keyType, &var->key);
00236 if (lua_next(L, -2) != 0)
00237 popvar(L, &var->valueType, &var->value);
00238 }
00239 }
00240
00241 #define FINDKEY_RETURN 0
00242 #define FINDKEY_CREATE 1
00243 #define FINDKEY_REMOVE 2
00244 static int findkey(lua_State *L, int oper, const char *key, va_list va)
00245
00246 {
00247 char buf[BUFSIZ];
00248 const char *s, *e;
00249 int ret = 0;
00250 (void) vsnprintf(buf, BUFSIZ, key, va);
00251 s = e = buf;
00252 lua_pushvalue(L, LUA_GLOBALSINDEX);
00253 for (;;) {
00254 if (*e == '\0' || *e == '.') {
00255 if (e != s) {
00256 lua_pushlstring(L, s, e-s);
00257 switch (oper) {
00258 case FINDKEY_REMOVE:
00259 if (*e == '\0') {
00260 lua_pushnil(L);
00261 lua_rawset(L, -3);
00262 lua_pop(L, 1);
00263 break;
00264 }
00265
00266 case FINDKEY_RETURN:
00267 lua_rawget(L, -2);
00268 lua_remove(L, -2);
00269 break;
00270 case FINDKEY_CREATE:
00271 lua_rawget(L, -2);
00272 if (!lua_istable(L, -1)) {
00273 lua_pop(L, 1);
00274 lua_newtable(L);
00275 lua_pushlstring(L, s, e-s);
00276 lua_pushvalue(L, -2);
00277 lua_rawset(L, -4);
00278 }
00279 lua_remove(L, -2);
00280 break;
00281 }
00282 }
00283 if (*e == '\0')
00284 break;
00285 if (!lua_istable(L, -1)) {
00286 lua_pop(L, 1);
00287 ret = -1;
00288 break;
00289 }
00290 s = e+1;
00291 }
00292 e++;
00293 }
00294
00295 return ret;
00296 }
00297
00298 void rpmluaDelVar(rpmlua _lua, const char *key, ...)
00299 {
00300 INITSTATE(_lua, lua);
00301 va_list va;
00302 va_start(va, key);
00303 (void) findkey(lua->L, FINDKEY_REMOVE, key, va);
00304 va_end(va);
00305 }
00306
00307 int rpmluaVarExists(rpmlua _lua, const char *key, ...)
00308 {
00309 INITSTATE(_lua, lua);
00310 lua_State *L = lua->L;
00311 int ret = 0;
00312 va_list va;
00313 va_start(va, key);
00314 if (findkey(L, FINDKEY_RETURN, key, va) == 0) {
00315 if (!lua_isnil(L, -1))
00316 ret = 1;
00317 lua_pop(L, 1);
00318 }
00319 va_end(va);
00320 return ret;
00321 }
00322
00323 void rpmluaPushTable(rpmlua _lua, const char *key, ...)
00324 {
00325 INITSTATE(_lua, lua);
00326 va_list va;
00327 va_start(va, key);
00328 (void) findkey(lua->L, FINDKEY_CREATE, key, va);
00329 lua->pushsize++;
00330 va_end(va);
00331 }
00332
00333 void rpmluaPop(rpmlua _lua)
00334 {
00335 INITSTATE(_lua, lua);
00336 assert(lua->pushsize > 0);
00337 lua->pushsize--;
00338 lua_pop(lua->L, 1);
00339 }
00340
00341 rpmluav rpmluavNew(void)
00342 {
00343 rpmluav var = (rpmluav) xcalloc(1, sizeof(*var));
00344 return var;
00345 }
00346
00347 void *rpmluavFree(rpmluav var)
00348 {
00349 free(var);
00350 return NULL;
00351 }
00352
00353 void rpmluavSetListMode(rpmluav var, int flag)
00354 {
00355 var->listmode = flag;
00356 var->keyType = RPMLUAV_NIL;
00357 }
00358
00359 void rpmluavSetKey(rpmluav var, rpmluavType type, const void *value)
00360 {
00361 var->keyType = type;
00362
00363 switch (type) {
00364 case RPMLUAV_NUMBER:
00365 var->key.num = *((double *)value);
00366 break;
00367 case RPMLUAV_STRING:
00368 var->key.str = (char *)value;
00369 break;
00370 default:
00371 break;
00372 }
00373
00374 }
00375
00376 void rpmluavSetValue(rpmluav var, rpmluavType type, const void *value)
00377 {
00378 var->valueType = type;
00379
00380 switch (type) {
00381 case RPMLUAV_NUMBER:
00382 var->value.num = *((const double *)value);
00383 break;
00384 case RPMLUAV_STRING:
00385 var->value.str = (const char *)value;
00386 break;
00387 default:
00388 break;
00389 }
00390
00391 }
00392
00393 void rpmluavGetKey(rpmluav var, rpmluavType *type, void **value)
00394 {
00395 *type = var->keyType;
00396
00397 switch (var->keyType) {
00398 case RPMLUAV_NUMBER:
00399 *((double **)value) = &var->key.num;
00400 break;
00401 case RPMLUAV_STRING:
00402 *((const char **)value) = var->key.str;
00403 break;
00404 default:
00405 break;
00406 }
00407
00408 }
00409
00410 void rpmluavGetValue(rpmluav var, rpmluavType *type, void **value)
00411 {
00412 *type = var->valueType;
00413
00414 switch (var->valueType) {
00415 case RPMLUAV_NUMBER:
00416 *((double **)value) = &var->value.num;
00417 break;
00418 case RPMLUAV_STRING:
00419 *((const char **)value) = var->value.str;
00420 break;
00421 default:
00422 break;
00423 }
00424
00425 }
00426
00427 void rpmluavSetKeyNum(rpmluav var, double value)
00428 {
00429 rpmluavSetKey(var, RPMLUAV_NUMBER, &value);
00430 }
00431
00432 void rpmluavSetValueNum(rpmluav var, double value)
00433 {
00434 rpmluavSetValue(var, RPMLUAV_NUMBER, &value);
00435 }
00436
00437 double rpmluavGetKeyNum(rpmluav var)
00438 {
00439 rpmluavType type;
00440 void *value;
00441 rpmluavGetKey(var, &type, &value);
00442 if (type == RPMLUAV_NUMBER)
00443 return *((double *)value);
00444 return (double) 0;
00445 }
00446
00447 double rpmluavGetValueNum(rpmluav var)
00448 {
00449 rpmluavType type;
00450 void *value;
00451 rpmluavGetValue(var, &type, &value);
00452 if (type == RPMLUAV_NUMBER)
00453 return *((double *)value);
00454 return (double) 0;
00455 }
00456
00457 int rpmluavKeyIsNum(rpmluav var)
00458 {
00459 return (var->keyType == RPMLUAV_NUMBER) ? 1 : 0;
00460 }
00461
00462 int rpmluavValueIsNum(rpmluav var)
00463 {
00464 return (var->valueType == RPMLUAV_NUMBER) ? 1 : 0;
00465 }
00466
00467 int rpmluaCheckScript(rpmlua _lua, const char *script, const char *name)
00468 {
00469 INITSTATE(_lua, lua);
00470 lua_State *L = lua->L;
00471 int ret = 0;
00472
00473 if (name == NULL)
00474 name = "<lua>";
00475
00476 if (luaL_loadbuffer(L, script, strlen(script), name) != 0) {
00477 rpmError(RPMERR_SCRIPT,
00478 _("invalid syntax in lua scriptlet: %s\n"),
00479 lua_tostring(L, -1));
00480 ret = -1;
00481 }
00482 lua_pop(L, 1);
00483 return ret;
00484 }
00485
00486 int rpmluaRunScript(rpmlua _lua, const char *script, const char *name)
00487 {
00488 INITSTATE(_lua, lua);
00489 lua_State *L = lua->L;
00490 int ret = 0;
00491
00492 if (name == NULL)
00493 name = "<lua>";
00494
00495 if (luaL_loadbuffer(L, script, strlen(script), name) != 0) {
00496 rpmError(RPMERR_SCRIPT, _("invalid syntax in lua script: %s\n"),
00497 lua_tostring(L, -1));
00498 lua_pop(L, 1);
00499 ret = -1;
00500 } else if (lua_pcall(L, 0, 0, 0) != 0) {
00501 rpmError(RPMERR_SCRIPT, _("lua script failed: %s\n"),
00502 lua_tostring(L, -1));
00503 lua_pop(L, 1);
00504 ret = -1;
00505 }
00506 return ret;
00507 }
00508
00509 int rpmluaRunScriptFile(rpmlua _lua, const char *filename)
00510 {
00511 INITSTATE(_lua, lua);
00512 lua_State *L = lua->L;
00513 int ret = 0;
00514 if (luaL_loadfile(L, filename) != 0) {
00515 rpmError(RPMERR_SCRIPT, _("invalid syntax in lua file: %s\n"),
00516 lua_tostring(L, -1));
00517 lua_pop(L, 1);
00518 ret = -1;
00519 } else if (lua_pcall(L, 0, 0, 0) != 0) {
00520 rpmError(RPMERR_SCRIPT, _("lua script failed: %s\n"),
00521 lua_tostring(L, -1));
00522 lua_pop(L, 1);
00523 ret = -1;
00524 }
00525 return ret;
00526 }
00527
00528
00529 static int rpmluaReadline(lua_State *L, const char *prompt)
00530
00531
00532 {
00533 static char buffer[1024];
00534 if (prompt) {
00535 (void) fputs(prompt, stdout);
00536 (void) fflush(stdout);
00537 }
00538 if (fgets(buffer, sizeof(buffer), stdin) == NULL) {
00539 return 0;
00540 } else {
00541 lua_pushstring(L, buffer);
00542 return 1;
00543 }
00544 }
00545
00546
00547 static void _rpmluaInteractive(lua_State *L)
00548
00549
00550 {
00551 (void) fputs("\n", stdout);
00552 printf("RPM Interactive %s Interpreter\n", LUA_VERSION);
00553 for (;;) {
00554 int rc = 0;
00555
00556 if (rpmluaReadline(L, "> ") == 0)
00557 break;
00558 if (lua_tostring(L, -1)[0] == '=') {
00559
00560 (void) lua_pushfstring(L, "print(%s)", lua_tostring(L, -1)+1);
00561
00562 lua_remove(L, -2);
00563 }
00564 for (;;) {
00565
00566 rc = luaL_loadbuffer(L, lua_tostring(L, -1),
00567 lua_strlen(L, -1), "<lua>");
00568
00569 if (rc == LUA_ERRSYNTAX &&
00570 strstr(lua_tostring(L, -1), "near `<eof>'") != NULL) {
00571 if (rpmluaReadline(L, ">> ") == 0)
00572 break;
00573 lua_remove(L, -2);
00574 lua_concat(L, 2);
00575 continue;
00576 }
00577 break;
00578 }
00579 if (rc == 0)
00580 rc = lua_pcall(L, 0, 0, 0);
00581 if (rc != 0) {
00582 fprintf(stderr, "%s\n", lua_tostring(L, -1));
00583 lua_pop(L, 1);
00584 }
00585 lua_pop(L, 1);
00586 }
00587 (void) fputs("\n", stdout);
00588 }
00589
00590
00591 void rpmluaInteractive(rpmlua _lua)
00592 {
00593 INITSTATE(_lua, lua);
00594 _rpmluaInteractive(lua->L);
00595 }
00596
00597
00598
00599
00600
00601 static int rpm_expand(lua_State *L)
00602
00603
00604 {
00605 const char *str = luaL_checkstring(L, 1);
00606 lua_pushstring(L, rpmExpand(str, NULL));
00607 return 1;
00608 }
00609
00610 static int rpm_define(lua_State *L)
00611
00612
00613 {
00614 const char *str = luaL_checkstring(L, 1);
00615 (void) rpmDefineMacro(NULL, str, 0);
00616 return 0;
00617 }
00618
00619 static int rpm_interactive(lua_State *L)
00620
00621
00622 {
00623 _rpmluaInteractive(L);
00624 return 0;
00625 }
00626
00627 typedef struct rpmluaHookData_s {
00628
00629 lua_State *L;
00630 int funcRef;
00631 int dataRef;
00632 } * rpmluaHookData;
00633
00634 static int rpmluaHookWrapper(rpmhookArgs args, void *data)
00635
00636 {
00637 rpmluaHookData hookdata = (rpmluaHookData)data;
00638 lua_State *L = hookdata->L;
00639 int ret = 0;
00640 int i;
00641 lua_rawgeti(L, LUA_REGISTRYINDEX, hookdata->funcRef);
00642 lua_newtable(L);
00643 for (i = 0; i != args->argc; i++) {
00644 switch (args->argt[i]) {
00645 case 's':
00646 lua_pushstring(L, args->argv[i].s);
00647 lua_rawseti(L, -2, i+1);
00648 break;
00649 case 'i':
00650 lua_pushnumber(L, (lua_Number)args->argv[i].i);
00651 lua_rawseti(L, -2, i+1);
00652 break;
00653 case 'f':
00654 lua_pushnumber(L, (lua_Number)args->argv[i].f);
00655 lua_rawseti(L, -2, i+1);
00656 break;
00657 case 'p':
00658 lua_pushlightuserdata(L, args->argv[i].p);
00659 lua_rawseti(L, -2, i+1);
00660 break;
00661 default:
00662 (void) luaL_error(L, "unsupported type '%c' as "
00663 "a hook argument\n", args->argt[i]);
00664 break;
00665 }
00666 }
00667 if (lua_pcall(L, 1, 1, 0) != 0) {
00668 rpmError(RPMERR_SCRIPT, _("lua hook failed: %s\n"),
00669 lua_tostring(L, -1));
00670 lua_pop(L, 1);
00671 } else {
00672 if (lua_isnumber(L, -1))
00673 ret = (int)lua_tonumber(L, -1);
00674 lua_pop(L, 1);
00675 }
00676 return ret;
00677 }
00678
00679 static int rpm_register(lua_State *L)
00680
00681
00682 {
00683 if (!lua_isstring(L, 1)) {
00684 (void) luaL_argerror(L, 1, "hook name expected");
00685 } else if (!lua_isfunction(L, 2)) {
00686 (void) luaL_argerror(L, 2, "function expected");
00687 } else {
00688 rpmluaHookData hookdata =
00689 lua_newuserdata(L, sizeof(struct rpmluaHookData_s));
00690 lua_pushvalue(L, -1);
00691 hookdata->dataRef = luaL_ref(L, LUA_REGISTRYINDEX);
00692 lua_pushvalue(L, 2);
00693 hookdata->funcRef = luaL_ref(L, LUA_REGISTRYINDEX);
00694
00695 hookdata->L = L;
00696
00697 rpmhookRegister(lua_tostring(L, 1), rpmluaHookWrapper, hookdata);
00698 return 1;
00699 }
00700 return 0;
00701 }
00702
00703 static int rpm_unregister(lua_State *L)
00704
00705 {
00706 if (!lua_isstring(L, 1)) {
00707 (void) luaL_argerror(L, 1, "hook name expected");
00708 } else if (!lua_islightuserdata(L, 2)) {
00709 (void) luaL_argerror(L, 2, "hook information expected");
00710 } else {
00711 rpmluaHookData hookdata = (rpmluaHookData)lua_touserdata(L, 2);
00712 luaL_unref(L, LUA_REGISTRYINDEX, hookdata->funcRef);
00713 luaL_unref(L, LUA_REGISTRYINDEX, hookdata->dataRef);
00714 rpmhookUnregister(lua_tostring(L, 1), rpmluaHookWrapper, hookdata);
00715 }
00716 return 0;
00717 }
00718
00719 static int rpm_call(lua_State *L)
00720
00721
00722 {
00723 if (!lua_isstring(L, 1)) {
00724 (void) luaL_argerror(L, 1, "hook name expected");
00725 } else {
00726 rpmhookArgs args = rpmhookArgsNew(lua_gettop(L)-1);
00727 const char *name = lua_tostring(L, 1);
00728 char *argt = (char *)xmalloc(args->argc+1);
00729 int i;
00730 for (i = 0; i != args->argc; i++) {
00731 switch (lua_type(L, i+1)) {
00732 case LUA_TNIL:
00733 argt[i] = 'p';
00734 args->argv[i].p = NULL;
00735 break;
00736 case LUA_TNUMBER: {
00737 float f = (float)lua_tonumber(L, i+1);
00738
00739 if (f == (int)f) {
00740 argt[i] = 'i';
00741 args->argv[i].i = (int)f;
00742 } else {
00743 argt[i] = 'f';
00744 args->argv[i].f = f;
00745 }
00746
00747 } break;
00748 case LUA_TSTRING:
00749 argt[i] = 's';
00750 args->argv[i].s = lua_tostring(L, i+1);
00751 break;
00752 case LUA_TUSERDATA:
00753 case LUA_TLIGHTUSERDATA:
00754 argt[i] = 'p';
00755 args->argv[i].p = lua_touserdata(L, i+1);
00756 break;
00757 default:
00758 (void) luaL_error(L, "unsupported Lua type passed to hook");
00759 argt[i] = 'p';
00760 args->argv[i].p = NULL;
00761 break;
00762 }
00763 }
00764
00765 args->argt = argt;
00766 rpmhookCallArgs(name, args);
00767 free(argt);
00768 (void) rpmhookArgsFree(args);
00769
00770 }
00771 return 0;
00772 }
00773
00774
00775 static int rpm_print (lua_State *L)
00776
00777
00778 {
00779 rpmlua lua = (rpmlua)getdata(L, "lua");
00780 int n = lua_gettop(L);
00781 int i;
00782 if (!lua) return 0;
00783 lua_getglobal(L, "tostring");
00784 for (i = 1; i <= n; i++) {
00785 const char *s;
00786 lua_pushvalue(L, -1);
00787 lua_pushvalue(L, i);
00788 lua_call(L, 1, 1);
00789 s = lua_tostring(L, -1);
00790 if (s == NULL)
00791 return luaL_error(L, "`tostring' must return a string to `print'");
00792 if (lua->storeprint) {
00793 int sl = lua_strlen(L, -1);
00794 if (lua->printbufused+sl+1 > lua->printbufsize) {
00795 lua->printbufsize += sl+512;
00796 lua->printbuf = xrealloc(lua->printbuf, lua->printbufsize);
00797 }
00798 if (i > 1)
00799 lua->printbuf[lua->printbufused++] = '\t';
00800 memcpy(lua->printbuf+lua->printbufused, s, sl+1);
00801 lua->printbufused += sl;
00802 } else {
00803 if (i > 1)
00804 (void) fputs("\t", stdout);
00805 (void) fputs(s, stdout);
00806 }
00807 lua_pop(L, 1);
00808 }
00809 lua_pop(L, 1);
00810 if (!lua->storeprint) {
00811 (void) fputs("\n", stdout);
00812 } else {
00813 if (lua->printbufused+1 >= lua->printbufsize) {
00814 lua->printbufsize += 512;
00815 lua->printbuf = xrealloc(lua->printbuf, lua->printbufsize);
00816 }
00817 lua->printbuf[lua->printbufused++] = '\n';
00818 lua->printbuf[lua->printbufused] = '\0';
00819 }
00820 return 0;
00821 }
00822
00823
00824
00825 static const luaL_reg rpmlib[] = {
00826 {"expand", rpm_expand},
00827 {"define", rpm_define},
00828 {"register", rpm_register},
00829 {"unregister", rpm_unregister},
00830 {"call", rpm_call},
00831 {"interactive", rpm_interactive},
00832 {NULL, NULL}
00833 };
00834
00835
00836 static int luaopen_rpm(lua_State *L)
00837
00838 {
00839 lua_pushvalue(L, LUA_GLOBALSINDEX);
00840 luaL_openlib(L, "rpm", rpmlib, 0);
00841 return 0;
00842 }
00843 #endif
00844
00845