summaryrefslogtreecommitdiff
path: root/rpmio/rpmlua.c
diff options
context:
space:
mode:
authorniemeyer <devnull@localhost>2004-03-19 20:08:20 +0000
committerniemeyer <devnull@localhost>2004-03-19 20:08:20 +0000
commit635edd95230e17e8ada5793719d7e385e729df30 (patch)
tree09290ba08b74c4ad43a9d67b6f0f8eaa18413006 /rpmio/rpmlua.c
parenta1a283837a6b70c9ee4731f9172cfc614a1a7c6b (diff)
downloadlibrpm-tizen-635edd95230e17e8ada5793719d7e385e729df30.tar.gz
librpm-tizen-635edd95230e17e8ada5793719d7e385e729df30.tar.bz2
librpm-tizen-635edd95230e17e8ada5793719d7e385e729df30.zip
- New internal Lua support scheme, laying under rpmio.
- New API abstracting access to Lua state (rpmlua is abstract to everyone but rpmlua.c). - New %{lua: ... } macro. Modified Files: lib/Makefile.am lib/psm.c lib/rpmts.c lua/local/linit.lch lua/local/linit.lua rpmio/Makefile.am rpmio/macro.c Added Files: rpmio/rpmlua.c rpmio/rpmlua.h Removed Files: lib/rpmlua.c lib/rpmlua.h CVS patchset: 7178 CVS date: 2004/03/19 20:08:20
Diffstat (limited to 'rpmio/rpmlua.c')
-rw-r--r--rpmio/rpmlua.c588
1 files changed, 588 insertions, 0 deletions
diff --git a/rpmio/rpmlua.c b/rpmio/rpmlua.c
new file mode 100644
index 000000000..6b545b4a1
--- /dev/null
+++ b/rpmio/rpmlua.c
@@ -0,0 +1,588 @@
+#include "system.h"
+#include <rpmio.h>
+#include <rpmmacro.h>
+#include <rpmerr.h>
+#include <rpmurl.h>
+
+#include <lua.h>
+#include <lualib.h>
+#include <lauxlib.h>
+#include <lposix.h>
+#include <lrexlib.h>
+
+#include <unistd.h>
+#include <assert.h>
+
+#define _RPMLUA_INTERNAL
+#include "rpmlua.h"
+
+#if !defined(HAVE_VSNPRINTF)
+static inline int vsnprintf(char * buf, /*@unused@*/ int nb,
+ const char * fmt, va_list ap)
+{
+ return vsprintf(buf, fmt, ap);
+}
+#endif
+
+static int luaopen_rpm(lua_State *L);
+static int rpm_print(lua_State *L);
+
+rpmlua rpmluaNew()
+{
+ rpmlua lua = (rpmlua) xcalloc(1, sizeof(struct rpmlua_s));
+ lua_State *L = lua_open();
+ lua->L = L;
+ const luaL_reg lualibs[] = {
+ {"base", luaopen_base},
+ {"table", luaopen_table},
+ {"io", luaopen_io},
+ {"string", luaopen_string},
+ {"debug", luaopen_debug},
+ {"loadlib", luaopen_loadlib},
+ {"posix", luaopen_posix},
+ {"rex", luaopen_rex},
+ {"rpm", luaopen_rpm},
+ {NULL, NULL},
+ };
+ const luaL_reg *lib = lualibs;
+ for (; lib->name; lib++) {
+ lib->func(L);
+ lua_settop(L, 0);
+ }
+ lua_pushliteral(L, "LUA_PATH");
+ lua_pushstring(L, RPMCONFIGDIR "/lua/?.lua");
+ lua_rawset(L, LUA_GLOBALSINDEX);
+ lua_pushliteral(L, "print");
+ lua_pushcfunction(L, rpm_print);
+ lua_rawset(L, LUA_GLOBALSINDEX);
+ rpmluaSetData(lua, "lua", lua);
+ return lua;
+}
+
+void *rpmluaFree(rpmlua lua)
+{
+ if (lua) {
+ if (lua->L) lua_close(lua->L);
+ free(lua->printbuf);
+ free(lua);
+ }
+ return NULL;
+}
+
+void rpmluaSetData(rpmlua lua, const char *key, const void *data)
+{
+ lua_State *L = lua->L;
+ lua_pushliteral(L, "rpm_");
+ lua_pushstring(L, key);
+ lua_concat(L, 2);
+ if (data == NULL)
+ lua_pushnil(L);
+ else
+ lua_pushlightuserdata(L, (void *)data);
+ lua_rawset(L, LUA_REGISTRYINDEX);
+}
+
+static void *getdata(lua_State *L, const char *key)
+{
+ void *ret = NULL;
+ lua_pushliteral(L, "rpm_");
+ lua_pushstring(L, key);
+ lua_concat(L, 2);
+ lua_rawget(L, LUA_REGISTRYINDEX);
+ if (lua_islightuserdata(L, -1))
+ ret = lua_touserdata(L, -1);
+ lua_pop(L, 1);
+ return ret;
+}
+
+void *rpmluaGetData(rpmlua lua, const char *key)
+{
+ return getdata(lua->L, key);
+}
+
+void rpmluaSetPrintBuffer(rpmlua lua, int flag)
+{
+ lua->storeprint = flag;
+ free(lua->printbuf);
+ lua->printbuf = NULL;
+ lua->printbufsize = 0;
+}
+
+const char *rpmluaGetPrintBuffer(rpmlua lua)
+{
+ return lua->printbuf;
+}
+
+static int pushvar(lua_State *L, rpmluavType type, void *value)
+{
+ int ret = 0;
+ switch (type) {
+ case RPMLUAV_NIL:
+ lua_pushnil(L);
+ break;
+ case RPMLUAV_STRING:
+ lua_pushstring(L, *((char **)value));
+ break;
+ case RPMLUAV_NUMBER:
+ lua_pushnumber(L, *((double *)value));
+ break;
+ default:
+ ret = -1;
+ break;
+ }
+ return ret;
+}
+
+void rpmluaSetVar(rpmlua lua, rpmluav var)
+{
+ lua_State *L = lua->L;
+ if (var->listmode && lua->pushsize > 0) {
+ if (var->keyType != RPMLUAV_NUMBER || var->key.num == 0) {
+ var->keyType = RPMLUAV_NUMBER;
+ var->key.num = luaL_getn(L, -1);
+ }
+ var->key.num++;
+ }
+ if (!var->listmode || lua->pushsize > 0) {
+ if (lua->pushsize == 0)
+ lua_pushvalue(L, LUA_GLOBALSINDEX);
+ if (pushvar(L, var->keyType, &var->key) != -1) {
+ if (pushvar(L, var->valueType, &var->value) != -1)
+ lua_rawset(L, -3);
+ else
+ lua_pop(L, 1);
+ }
+ if (lua->pushsize == 0)
+ lua_pop(L, 1);
+ }
+}
+
+static void popvar(lua_State *L, rpmluavType *type, void *value)
+{
+ switch (lua_type(L, -1)) {
+ case LUA_TSTRING:
+ *type = RPMLUAV_STRING;
+ *((const char **)value) = lua_tostring(L, -1);
+ break;
+ case LUA_TNUMBER:
+ *type = RPMLUAV_NUMBER;
+ *((double *)value) = lua_tonumber(L, -1);
+ break;
+ default:
+ *type = RPMLUAV_NIL;
+ *((void **)value) = NULL;
+ break;
+ }
+ lua_pop(L, 1);
+}
+
+void rpmluaGetVar(rpmlua lua, rpmluav var)
+{
+ lua_State *L = lua->L;
+ if (!var->listmode) {
+ if (lua->pushsize == 0)
+ lua_pushvalue(L, LUA_GLOBALSINDEX);
+ if (pushvar(L, var->keyType, &var->key) != -1) {
+ lua_rawget(L, -2);
+ popvar(L, &var->valueType, &var->value);
+ }
+ if (lua->pushsize == 0)
+ lua_pop(L, 1);
+ } else if (lua->pushsize > 0) {
+ pushvar(L, var->keyType, &var->key);
+ if (lua_next(L, -2) != 0)
+ popvar(L, &var->valueType, &var->value);
+ }
+}
+
+#define FINDKEY_RETURN 0
+#define FINDKEY_CREATE 1
+#define FINDKEY_REMOVE 2
+static int findkey(lua_State *L, int oper, const char *key, va_list va)
+{
+ char buf[BUFSIZ];
+ const char *s, *e;
+ int ret = 0;
+ vsnprintf(buf, BUFSIZ, key, va);
+ s = e = buf;
+ lua_pushvalue(L, LUA_GLOBALSINDEX);
+ for (;;) {
+ if (*e == '\0' || *e == '.') {
+ if (e != s) {
+ lua_pushlstring(L, s, e-s);
+ switch (oper) {
+ case FINDKEY_REMOVE:
+ if (*e == '\0') {
+ lua_pushnil(L);
+ lua_rawset(L, -3);
+ lua_pop(L, 1);
+ break;
+ }
+ /* @fallthrough@ */
+ case FINDKEY_RETURN:
+ lua_rawget(L, -2);
+ lua_remove(L, -2);
+ break;
+ case FINDKEY_CREATE:
+ lua_rawget(L, -2);
+ if (!lua_istable(L, -1)) {
+ lua_pop(L, 1);
+ lua_newtable(L);
+ lua_pushlstring(L, s, e-s);
+ lua_pushvalue(L, -2);
+ lua_rawset(L, -4);
+ }
+ lua_remove(L, -2);
+ break;
+ }
+ }
+ if (*e == '\0')
+ break;
+ if (!lua_istable(L, -1)) {
+ lua_pop(L, 1);
+ ret = -1;
+ break;
+ }
+ s = e+1;
+ }
+ e++;
+ }
+
+ return ret;
+}
+
+void rpmluaDelVar(rpmlua lua, const char *key, ...)
+{
+ va_list va;
+ va_start(va, key);
+ findkey(lua->L, FINDKEY_REMOVE, key, va);
+ va_end(va);
+}
+
+int rpmluaVarExists(rpmlua lua, const char *key, ...)
+{
+ int ret = 0;
+ va_list va;
+ va_start(va, key);
+ if (findkey(lua->L, FINDKEY_RETURN, key, va) == 0) {
+ if (!lua_isnil(lua->L, -1))
+ ret = 1;
+ lua_pop(lua->L, 1);
+ }
+ va_end(va);
+ return ret;
+}
+
+void rpmluaPushTable(rpmlua lua, const char *key, ...)
+{
+ va_list va;
+ va_start(va, key);
+ findkey(lua->L, FINDKEY_CREATE, key, va);
+ lua->pushsize++;
+ va_end(va);
+}
+
+void rpmluaPop(rpmlua lua)
+{
+ assert(lua->pushsize > 0);
+ lua->pushsize--;
+ lua_pop(lua->L, 1);
+}
+
+rpmluav rpmluavNew(void)
+{
+ rpmluav var = (rpmluav) xcalloc(1, sizeof(struct rpmluav_s));
+ return var;
+}
+
+void *rpmluavFree(rpmluav var)
+{
+ free(var);
+ return NULL;
+}
+
+void rpmluavSetListMode(rpmluav var, int flag)
+{
+ var->listmode = flag;
+ var->keyType = RPMLUAV_NIL;
+}
+
+void rpmluavSetKey(rpmluav var, rpmluavType type, const void *value)
+{
+ var->keyType = type;
+ switch (type) {
+ case RPMLUAV_NUMBER:
+ var->key.num = *((double *)value);
+ break;
+ case RPMLUAV_STRING:
+ var->key.str = (char *)value;
+ break;
+ default:
+ break;
+ }
+}
+
+void rpmluavSetValue(rpmluav var, rpmluavType type, const void *value)
+{
+ var->valueType = type;
+ switch (type) {
+ case RPMLUAV_NUMBER:
+ var->value.num = *((const double *)value);
+ break;
+ case RPMLUAV_STRING:
+ var->value.str = (const char *)value;
+ break;
+ default:
+ break;
+ }
+}
+
+void rpmluavGetKey(rpmluav var, rpmluavType *type, void **value)
+{
+ *type = var->keyType;
+ switch (var->keyType) {
+ case RPMLUAV_NUMBER:
+ *((double **)value) = &var->key.num;
+ break;
+ case RPMLUAV_STRING:
+ *((const char **)value) = var->key.str;
+ break;
+ default:
+ break;
+ }
+}
+
+void rpmluavGetValue(rpmluav var, rpmluavType *type, void **value)
+{
+ *type = var->valueType;
+ switch (var->valueType) {
+ case RPMLUAV_NUMBER:
+ *((double **)value) = &var->value.num;
+ break;
+ case RPMLUAV_STRING:
+ *((const char **)value) = var->value.str;
+ break;
+ default:
+ break;
+ }
+}
+
+void rpmluavSetKeyNum(rpmluav var, double value)
+{
+ rpmluavSetKey(var, RPMLUAV_NUMBER, &value);
+}
+
+void rpmluavSetValueNum(rpmluav var, double value)
+{
+ rpmluavSetValue(var, RPMLUAV_NUMBER, &value);
+}
+
+double rpmluavGetKeyNum(rpmluav var)
+{
+ rpmluavType type;
+ void *value;
+ rpmluavGetKey(var, &type, &value);
+ if (type == RPMLUAV_NUMBER)
+ return *((double *)value);
+ return 0;
+}
+
+double rpmluavGetValueNum(rpmluav var)
+{
+ rpmluavType type;
+ void *value;
+ rpmluavGetValue(var, &type, &value);
+ if (type == RPMLUAV_NUMBER)
+ return *((double *)value);
+ return 0;
+}
+
+int rpmluavKeyIsNum(rpmluav var)
+{
+ return (var->keyType == RPMLUAV_NUMBER) ? 1 : 0;
+}
+
+int rpmluavValueIsNum(rpmluav var)
+{
+ return (var->valueType == RPMLUAV_NUMBER) ? 1 : 0;
+}
+
+int rpmluaCheckScript(rpmlua lua, const char *script, const char *name)
+{
+ lua_State *L = lua->L;
+ int ret = 0;
+ if (!name)
+ name = "<lua>";
+ if (luaL_loadbuffer(L, script, strlen(script), name) != 0) {
+ rpmError(RPMERR_SCRIPT,
+ _("invalid syntax in lua scriptlet: %s\n"),
+ lua_tostring(L, -1));
+ ret = -1;
+ }
+ lua_pop(L, 1); /* Error or chunk. */
+ return ret;
+}
+
+int rpmluaRunScript(rpmlua lua, const char *script, const char *name)
+{
+ lua_State *L = lua->L;
+ int ret = 0;
+ if (!name)
+ name = "<lua>";
+ if (luaL_loadbuffer(L, script, strlen(script), name) != 0) {
+ rpmError(RPMERR_SCRIPT, _("invalid syntax in lua script: %s\n"),
+ lua_tostring(L, -1));
+ lua_pop(L, 1);
+ ret = -1;
+ } else if (lua_pcall(L, 0, 0, 0) != 0) {
+ rpmError(RPMERR_SCRIPT, _("lua script failed: %s\n"),
+ lua_tostring(L, -1));
+ lua_pop(L, 1);
+ ret = -1;
+ }
+ return ret;
+}
+
+/* From lua.c */
+static int rpmluaReadline(lua_State *l, const char *prompt) {
+ static char buffer[1024];
+ if (prompt) {
+ fputs(prompt, stdout);
+ fflush(stdout);
+ }
+ if (fgets(buffer, sizeof(buffer), stdin) == NULL) {
+ return 0; /* read fails */
+ } else {
+ lua_pushstring(l, buffer);
+ return 1;
+ }
+}
+
+/* Based on lua.c */
+static void _rpmluaInteractive(lua_State *L)
+{
+ fputs("\n", stdout);
+ printf("RPM Interactive %s Interpreter\n", LUA_VERSION);
+ for (;;) {
+ if (rpmluaReadline(L, "> ") == 0)
+ break;
+ if (lua_tostring(L, -1)[0] == '=') {
+ lua_pushfstring(L, "print(%s)", lua_tostring(L, -1)+1);
+ lua_remove(L, -2);
+ }
+ int rc = 0;
+ for (;;) {
+ rc = luaL_loadbuffer(L, lua_tostring(L, -1),
+ lua_strlen(L, -1), "<lua>");
+ if (rc == LUA_ERRSYNTAX &&
+ strstr(lua_tostring(L, -1), "near `<eof>'") != NULL) {
+ if (rpmluaReadline(L, ">> ") == 0)
+ break;
+ lua_remove(L, -2); // Remove error
+ lua_concat(L, 2);
+ continue;
+ }
+ break;
+ }
+ if (rc == 0)
+ rc = lua_pcall(L, 0, 0, 0);
+ if (rc != 0) {
+ fprintf(stderr, "%s\n", lua_tostring(L, -1));
+ lua_pop(L, 1);
+ }
+ lua_pop(L, 1); // Remove line
+ }
+ fputs("\n", stdout);
+}
+
+void rpmluaInteractive(rpmlua lua)
+{
+ _rpmluaInteractive(lua->L);
+}
+
+/* ------------------------------------------------------------------ */
+/* Lua API */
+
+static int rpm_expand(lua_State *L)
+{
+ const char *str = luaL_checkstring(L, 1);
+ lua_pushstring(L, rpmExpand(str, NULL));
+ return 1;
+}
+
+static int rpm_define(lua_State *L)
+{
+ const char *str = luaL_checkstring(L, 1);
+ rpmDefineMacro(NULL, str, 0);
+ return 0;
+}
+
+static int rpm_interactive(lua_State *L)
+{
+ _rpmluaInteractive(L);
+ return 0;
+}
+
+/* Based on luaB_print. */
+static int rpm_print (lua_State *L)
+{
+ rpmlua lua = (rpmlua)getdata(L, "lua");;
+ int n = lua_gettop(L); /* number of arguments */
+ int i;
+ if (!lua) return 0;
+ lua_getglobal(L, "tostring");
+ for (i = 1; i <= n; i++) {
+ const char *s;
+ lua_pushvalue(L, -1); /* function to be called */
+ lua_pushvalue(L, i); /* value to print */
+ lua_call(L, 1, 1);
+ s = lua_tostring(L, -1); /* get result */
+ if (s == NULL)
+ return luaL_error(L, "`tostring' must return a string to `print'");
+ if (lua->storeprint) {
+ int sl = lua_strlen(L, -1);
+ if (lua->printbufused+sl+1 > lua->printbufsize) {
+ lua->printbufsize += sl+512;
+ lua->printbuf = xrealloc(lua->printbuf, lua->printbufsize);
+ }
+ if (i > 1)
+ lua->printbuf[lua->printbufused++] = '\t';
+ memcpy(lua->printbuf+lua->printbufused, s, sl+1);
+ lua->printbufused += sl;
+ } else {
+ if (i > 1)
+ fputs("\t", stdout);
+ fputs(s, stdout);
+ }
+ lua_pop(L, 1); /* pop result */
+ }
+ lua_pop(L, 1);
+ if (!lua->storeprint) {
+ fputs("\n", stdout);
+ } else {
+ if (lua->printbufused+1 >= lua->printbufsize) {
+ lua->printbufsize += 512;
+ lua->printbuf = xrealloc(lua->printbuf, lua->printbufsize);
+ }
+ lua->printbuf[lua->printbufused++] = '\n';
+ lua->printbuf[lua->printbufused] = '\0';
+ }
+ return 0;
+}
+
+static const luaL_reg rpmlib[] = {
+ {"expand", rpm_expand},
+ {"define", rpm_define},
+ {"interactive", rpm_interactive},
+ {NULL, NULL}
+};
+
+static int luaopen_rpm(lua_State *L)
+{
+ lua_pushvalue(L, LUA_GLOBALSINDEX);
+ luaL_openlib(L, "rpm", rpmlib, 0);
+ return 0;
+}
+
+/* vim:sts=4:sw=4
+*/