12 #define lua_open() luaL_newstate()
15 /* defined as lua_objlen in 5.1 */
17 #define lua_strlen(L,i) lua_rawlen(L, (i))
20 /* deprecated in 5.1, defined as lua_objlen in 5.1 */
22 #define luaL_getn(L,i) ((int)lua_rawlen(L, i))
25 /* define added in 5.2 */
26 #ifndef lua_pushglobaltable
27 #define lua_pushglobaltable(L) lua_pushvalue(L, LUA_GLOBALSINDEX)
33 #include <rpm/rpmio.h>
34 #include <rpm/rpmmacro.h>
35 #include <rpm/rpmlog.h>
36 #include <rpm/rpmurl.h>
37 #include <rpm/rpmfileutil.h>
38 #include <rpm/rpmbase64.h>
39 #include "rpmio/rpmhook.h"
41 #define _RPMLUA_INTERNAL
42 #include "rpmio/rpmlua.h"
46 #define INITSTATE(_lua, lua) \
47 rpmlua lua = _lua ? _lua : \
48 (globalLuaState ? globalLuaState : \
50 (globalLuaState = rpmluaNew()) \
61 static rpmlua globalLuaState = NULL;
63 static char *(*nextFileFunc)(void *) = NULL;
64 static void *nextFileFuncParam = NULL;
66 static int luaopen_rpm(lua_State *L);
67 static int rpm_print(lua_State *L);
69 rpmlua rpmluaGetGlobalState(void)
77 rpmlua lua = (rpmlua) xcalloc(1, sizeof(*lua));
80 char *initlua = rpmGenPath(rpmConfigDir(), "init.lua", NULL);
82 static const luaL_Reg extlibs[] = {
83 {"posix", luaopen_posix},
86 {"os", luaopen_rpm_os},
90 lua_State *L = lua_open();
94 for (lib = extlibs; lib->name; lib++) {
95 lua_pushcfunction(L, lib->func);
96 lua_pushstring(L, lib->name);
100 #ifndef LUA_GLOBALSINDEX
101 lua_pushglobaltable(L);
103 lua_pushliteral(L, "LUA_PATH");
104 lua_pushfstring(L, "%s/%s", rpmConfigDir(), "/lua/?.lua");
105 #ifdef LUA_GLOBALSINDEX
106 lua_rawset(L, LUA_GLOBALSINDEX);
110 lua_pushliteral(L, "print");
111 lua_pushcfunction(L, rpm_print);
112 #ifdef LUA_GLOBALSINDEX
113 lua_rawset(L, LUA_GLOBALSINDEX);
117 #ifndef LUA_GLOBALSINDEX
120 rpmluaSetData(lua, "lua", lua);
121 if (stat(initlua, &st) != -1)
122 (void)rpmluaRunScriptFile(lua, initlua);
127 rpmlua rpmluaFree(rpmlua lua)
130 if (lua->L) lua_close(lua->L);
133 if (lua == globalLuaState) globalLuaState = NULL;
138 void rpmluaSetData(rpmlua _lua, const char *key, const void *data)
140 INITSTATE(_lua, lua);
141 lua_State *L = lua->L;
142 lua_pushliteral(L, "rpm_");
143 lua_pushstring(L, key);
148 lua_pushlightuserdata(L, (void *)data);
149 lua_rawset(L, LUA_REGISTRYINDEX);
152 static void *getdata(lua_State *L, const char *key)
155 lua_pushliteral(L, "rpm_");
156 lua_pushstring(L, key);
158 lua_rawget(L, LUA_REGISTRYINDEX);
159 if (lua_islightuserdata(L, -1))
160 ret = lua_touserdata(L, -1);
165 void *rpmluaGetData(rpmlua _lua, const char *key)
167 INITSTATE(_lua, lua);
168 return getdata(lua->L, key);
171 void rpmluaPushPrintBuffer(rpmlua _lua)
173 INITSTATE(_lua, lua);
174 rpmluapb prbuf = xcalloc(1, sizeof(*prbuf));
178 prbuf->next = lua->printbuf;
180 lua->printbuf = prbuf;
183 char *rpmluaPopPrintBuffer(rpmlua _lua)
185 INITSTATE(_lua, lua);
186 rpmluapb prbuf = lua->printbuf;
191 lua->printbuf = prbuf->next;
198 static int pushvar(lua_State *L, rpmluavType type, void *value)
206 lua_pushstring(L, *((char **)value));
209 lua_pushnumber(L, *((double *)value));
218 void rpmluaSetNextFileFunc(char *(*func)(void *), void *funcParam)
221 nextFileFuncParam = funcParam;
224 void rpmluaSetVar(rpmlua _lua, rpmluav var)
226 INITSTATE(_lua, lua);
227 lua_State *L = lua->L;
228 if (var->listmode && lua->pushsize > 0) {
229 if (var->keyType != RPMLUAV_NUMBER || var->key.num == (double)0) {
230 var->keyType = RPMLUAV_NUMBER;
231 var->key.num = (double) luaL_getn(L, -1);
235 if (!var->listmode || lua->pushsize > 0) {
236 if (lua->pushsize == 0)
237 lua_pushglobaltable(L);
238 if (pushvar(L, var->keyType, &var->key) != -1) {
239 if (pushvar(L, var->valueType, &var->value) != -1)
244 if (lua->pushsize == 0)
249 static void popvar(lua_State *L, rpmluavType *type, void *value)
251 switch (lua_type(L, -1)) {
253 *type = RPMLUAV_STRING;
254 *((const char **)value) = lua_tostring(L, -1);
257 *type = RPMLUAV_NUMBER;
258 *((double *)value) = lua_tonumber(L, -1);
262 *((void **)value) = NULL;
268 void rpmluaGetVar(rpmlua _lua, rpmluav var)
270 INITSTATE(_lua, lua);
271 lua_State *L = lua->L;
272 if (!var->listmode) {
273 if (lua->pushsize == 0)
274 lua_pushglobaltable(L);
275 if (pushvar(L, var->keyType, &var->key) != -1) {
277 popvar(L, &var->valueType, &var->value);
279 if (lua->pushsize == 0)
281 } else if (lua->pushsize > 0) {
282 (void) pushvar(L, var->keyType, &var->key);
283 if (lua_next(L, -2) != 0)
284 popvar(L, &var->valueType, &var->value);
288 #define FINDKEY_RETURN 0
289 #define FINDKEY_CREATE 1
290 #define FINDKEY_REMOVE 2
291 static int findkey(lua_State *L, int oper, const char *key, va_list va)
298 blen = vsnprintf(NULL, 0, key, va);
303 buf = xmalloc(blen + 1);
304 vsnprintf(buf, blen + 1, key, va);
307 lua_pushglobaltable(L);
309 if (*e == '\0' || *e == '.') {
311 lua_pushlstring(L, s, e-s);
326 if (!lua_istable(L, -1)) {
329 lua_pushlstring(L, s, e-s);
330 lua_pushvalue(L, -2);
339 if (!lua_istable(L, -1)) {
353 void rpmluaDelVar(rpmlua _lua, const char *key, ...)
355 INITSTATE(_lua, lua);
358 (void) findkey(lua->L, FINDKEY_REMOVE, key, va);
362 int rpmluaVarExists(rpmlua _lua, const char *key, ...)
364 INITSTATE(_lua, lua);
365 lua_State *L = lua->L;
369 if (findkey(L, FINDKEY_RETURN, key, va) == 0) {
370 if (!lua_isnil(L, -1))
378 void rpmluaPushTable(rpmlua _lua, const char *key, ...)
380 INITSTATE(_lua, lua);
383 (void) findkey(lua->L, FINDKEY_CREATE, key, va);
388 void rpmluaPop(rpmlua _lua)
390 INITSTATE(_lua, lua);
391 assert(lua->pushsize > 0);
396 rpmluav rpmluavNew(void)
398 rpmluav var = (rpmluav) xcalloc(1, sizeof(*var));
402 rpmluav rpmluavFree(rpmluav var)
408 void rpmluavSetListMode(rpmluav var, int flag)
410 var->listmode = flag;
411 var->keyType = RPMLUAV_NIL;
414 void rpmluavSetKey(rpmluav var, rpmluavType type, const void *value)
419 var->key.num = *((double *)value);
422 var->key.str = (char *)value;
429 void rpmluavSetValue(rpmluav var, rpmluavType type, const void *value)
431 var->valueType = type;
434 var->value.num = *((const double *)value);
437 var->value.str = (const char *)value;
444 void rpmluavGetKey(rpmluav var, rpmluavType *type, void **value)
446 *type = var->keyType;
447 switch (var->keyType) {
449 *((double **)value) = &var->key.num;
452 *((const char **)value) = var->key.str;
459 void rpmluavGetValue(rpmluav var, rpmluavType *type, void **value)
461 *type = var->valueType;
462 switch (var->valueType) {
464 *((double **)value) = &var->value.num;
467 *((const char **)value) = var->value.str;
474 void rpmluavSetKeyNum(rpmluav var, double value)
476 rpmluavSetKey(var, RPMLUAV_NUMBER, &value);
479 void rpmluavSetValueNum(rpmluav var, double value)
481 rpmluavSetValue(var, RPMLUAV_NUMBER, &value);
484 double rpmluavGetKeyNum(rpmluav var)
488 rpmluavGetKey(var, &type, &value);
489 if (type == RPMLUAV_NUMBER)
490 return *((double *)value);
494 double rpmluavGetValueNum(rpmluav var)
498 rpmluavGetValue(var, &type, &value);
499 if (type == RPMLUAV_NUMBER)
500 return *((double *)value);
504 int rpmluavKeyIsNum(rpmluav var)
506 return (var->keyType == RPMLUAV_NUMBER) ? 1 : 0;
509 int rpmluavValueIsNum(rpmluav var)
511 return (var->valueType == RPMLUAV_NUMBER) ? 1 : 0;
514 int rpmluaCheckScript(rpmlua _lua, const char *script, const char *name)
516 INITSTATE(_lua, lua);
517 lua_State *L = lua->L;
521 if (luaL_loadbuffer(L, script, strlen(script), name) != 0) {
523 _("invalid syntax in lua scriptlet: %s\n"),
524 lua_tostring(L, -1));
527 lua_pop(L, 1); /* Error or chunk. */
531 int rpmluaRunScript(rpmlua _lua, const char *script, const char *name)
533 INITSTATE(_lua, lua);
534 lua_State *L = lua->L;
540 if (luaL_loadbuffer(L, script, strlen(script), name) != 0) {
541 rpmlog(RPMLOG_ERR, _("invalid syntax in lua script: %s\n"),
542 lua_tostring(L, -1));
545 } else if (lua_pcall(L, 0, 0, 0) != 0) {
546 rpmlog(RPMLOG_ERR, _("lua script failed: %s\n"),
547 lua_tostring(L, -1));
554 int rpmluaRunScriptFile(rpmlua _lua, const char *filename)
556 INITSTATE(_lua, lua);
557 lua_State *L = lua->L;
559 if (luaL_loadfile(L, filename) != 0) {
560 rpmlog(RPMLOG_ERR, _("invalid syntax in lua file: %s\n"),
561 lua_tostring(L, -1));
564 } else if (lua_pcall(L, 0, 0, 0) != 0) {
565 rpmlog(RPMLOG_ERR, _("lua script failed: %s\n"),
566 lua_tostring(L, -1));
574 static int rpmluaReadline(lua_State *L, const char *prompt)
576 static char buffer[1024];
578 (void) fputs(prompt, stdout);
579 (void) fflush(stdout);
581 if (fgets(buffer, sizeof(buffer), stdin) == NULL) {
582 return 0; /* read fails */
584 lua_pushstring(L, buffer);
590 static void _rpmluaInteractive(lua_State *L)
592 (void) fputs("\n", stdout);
593 printf("RPM Interactive %s Interpreter\n", LUA_VERSION);
597 if (rpmluaReadline(L, "> ") == 0)
599 if (lua_tostring(L, -1)[0] == '=') {
600 (void) lua_pushfstring(L, "print(%s)", lua_tostring(L, -1)+1);
604 rc = luaL_loadbuffer(L, lua_tostring(L, -1),
605 lua_strlen(L, -1), "<lua>");
606 if (rc == LUA_ERRSYNTAX &&
607 strstr(lua_tostring(L, -1), "near `<eof>'") != NULL) {
608 if (rpmluaReadline(L, ">> ") == 0)
610 lua_remove(L, -2); /* Remove error */
617 rc = lua_pcall(L, 0, 0, 0);
619 fprintf(stderr, "%s\n", lua_tostring(L, -1));
622 lua_pop(L, 1); /* Remove line */
624 (void) fputs("\n", stdout);
627 void rpmluaInteractive(rpmlua _lua)
629 INITSTATE(_lua, lua);
630 _rpmluaInteractive(lua->L);
633 /* ------------------------------------------------------------------ */
636 static int rpm_b64encode(lua_State *L)
638 const char *str = luaL_checkstring(L, 1);
639 size_t len = lua_strlen(L, 1);
641 if (lua_gettop(L) == 2)
642 linelen = luaL_checkinteger(L, 2);
644 char *data = rpmBase64Encode(str, len, linelen);
645 lua_pushstring(L, data);
651 static int rpm_b64decode(lua_State *L)
653 const char *str = luaL_checkstring(L, 1);
657 if (rpmBase64Decode(str, &data, &len) == 0) {
658 lua_pushlstring(L, data, len);
667 static int rpm_expand(lua_State *L)
669 const char *str = luaL_checkstring(L, 1);
671 if (rpmExpandMacros(NULL, str, &val, 0) < 0)
672 return luaL_error(L, "error expanding macro");
673 lua_pushstring(L, val);
678 static int rpm_define(lua_State *L)
680 const char *str = luaL_checkstring(L, 1);
681 if (rpmDefineMacro(NULL, str, 0))
682 return luaL_error(L, "error defining macro");
686 static int rpm_undefine(lua_State *L)
688 const char *str = luaL_checkstring(L, 1);
689 rpmPopMacro(NULL, str);
693 static int rpm_load(lua_State *L)
695 const char *str = luaL_checkstring(L, 1);
696 int rc = rpmLoadMacroFile(NULL, str);
697 lua_pushnumber(L, rc);
701 static int rpm_interactive(lua_State *L)
703 _rpmluaInteractive(L);
707 static int rpm_next_file(lua_State *L)
710 lua_pushstring(L, nextFileFunc(nextFileFuncParam));
712 lua_pushstring(L, NULL);
717 typedef struct rpmluaHookData_s {
723 static int rpmluaHookWrapper(rpmhookArgs args, void *data)
725 rpmluaHookData hookdata = (rpmluaHookData)data;
726 lua_State *L = hookdata->L;
729 lua_rawgeti(L, LUA_REGISTRYINDEX, hookdata->funcRef);
731 for (i = 0; i != args->argc; i++) {
732 switch (args->argt[i]) {
734 lua_pushstring(L, args->argv[i].s);
735 lua_rawseti(L, -2, i+1);
738 lua_pushnumber(L, (lua_Number)args->argv[i].i);
739 lua_rawseti(L, -2, i+1);
742 lua_pushnumber(L, (lua_Number)args->argv[i].f);
743 lua_rawseti(L, -2, i+1);
746 lua_pushlightuserdata(L, args->argv[i].p);
747 lua_rawseti(L, -2, i+1);
750 (void) luaL_error(L, "unsupported type '%c' as "
751 "a hook argument\n", args->argt[i]);
755 if (lua_pcall(L, 1, 1, 0) != 0) {
756 rpmlog(RPMLOG_ERR, _("lua hook failed: %s\n"),
757 lua_tostring(L, -1));
760 if (lua_isnumber(L, -1))
761 ret = (int)lua_tonumber(L, -1);
767 static int rpm_register(lua_State *L)
769 if (!lua_isstring(L, 1)) {
770 (void) luaL_argerror(L, 1, "hook name expected");
771 } else if (!lua_isfunction(L, 2)) {
772 (void) luaL_argerror(L, 2, "function expected");
774 rpmluaHookData hookdata =
775 lua_newuserdata(L, sizeof(struct rpmluaHookData_s));
776 lua_pushvalue(L, -1);
777 hookdata->dataRef = luaL_ref(L, LUA_REGISTRYINDEX);
779 hookdata->funcRef = luaL_ref(L, LUA_REGISTRYINDEX);
781 rpmhookRegister(lua_tostring(L, 1), rpmluaHookWrapper, hookdata);
787 static int rpm_unregister(lua_State *L)
789 if (!lua_isstring(L, 1)) {
790 (void) luaL_argerror(L, 1, "hook name expected");
791 } else if (!lua_isuserdata(L, 2)) {
792 (void) luaL_argerror(L, 2, "hook information expected");
794 rpmluaHookData hookdata = (rpmluaHookData)lua_touserdata(L, 2);
795 luaL_unref(L, LUA_REGISTRYINDEX, hookdata->funcRef);
796 luaL_unref(L, LUA_REGISTRYINDEX, hookdata->dataRef);
797 rpmhookUnregister(lua_tostring(L, 1), rpmluaHookWrapper, hookdata);
802 static int rpm_call(lua_State *L)
804 if (!lua_isstring(L, 1)) {
805 (void) luaL_argerror(L, 1, "hook name expected");
807 rpmhookArgs args = rpmhookArgsNew(lua_gettop(L)-1);
808 const char *name = lua_tostring(L, 1);
809 char *argt = (char *)xmalloc(args->argc+1);
811 for (i = 0; i != args->argc; i++) {
812 switch (lua_type(L, i+1)) {
815 args->argv[i].p = NULL;
818 float f = (float)lua_tonumber(L, i+1);
821 args->argv[i].i = (int)f;
829 args->argv[i].s = lua_tostring(L, i+1);
832 case LUA_TLIGHTUSERDATA:
834 args->argv[i].p = lua_touserdata(L, i+1);
837 (void) luaL_error(L, "unsupported Lua type passed to hook");
839 args->argv[i].p = NULL;
844 rpmhookCallArgs(name, args);
846 (void) rpmhookArgsFree(args);
851 /* Based on luaB_print. */
852 static int rpm_print (lua_State *L)
854 rpmlua lua = (rpmlua)getdata(L, "lua");
855 int n = lua_gettop(L); /* number of arguments */
858 lua_getglobal(L, "tostring");
859 for (i = 1; i <= n; i++) {
861 lua_pushvalue(L, -1); /* function to be called */
862 lua_pushvalue(L, i); /* value to print */
864 s = lua_tostring(L, -1); /* get result */
866 return luaL_error(L, "`tostring' must return a string to `print'");
868 rpmluapb prbuf = lua->printbuf;
869 int sl = lua_strlen(L, -1);
870 if (prbuf->used+sl+1 > prbuf->alloced) {
871 prbuf->alloced += sl+512;
872 prbuf->buf = xrealloc(prbuf->buf, prbuf->alloced);
875 prbuf->buf[prbuf->used++] = '\t';
876 memcpy(prbuf->buf+prbuf->used, s, sl+1);
880 (void) fputs("\t", stdout);
881 (void) fputs(s, stdout);
883 lua_pop(L, 1); /* pop result */
885 if (!lua->printbuf) {
886 (void) fputs("\n", stdout);
888 rpmluapb prbuf = lua->printbuf;
889 if (prbuf->used+1 > prbuf->alloced) {
890 prbuf->alloced += 512;
891 prbuf->buf = xrealloc(prbuf->buf, prbuf->alloced);
893 prbuf->buf[prbuf->used] = '\0';
898 static const luaL_Reg rpmlib[] = {
899 {"b64encode", rpm_b64encode},
900 {"b64decode", rpm_b64decode},
901 {"expand", rpm_expand},
902 {"define", rpm_define},
903 {"undefine", rpm_undefine},
905 {"register", rpm_register},
906 {"unregister", rpm_unregister},
908 {"interactive", rpm_interactive},
909 {"next_file", rpm_next_file},
913 static int luaopen_rpm(lua_State *L)
915 lua_pushglobaltable(L);
916 luaL_openlib(L, "rpm", rpmlib, 0);
919 #endif /* WITH_LUA */