summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorniemeyer <devnull@localhost>2004-04-18 20:47:29 +0000
committerniemeyer <devnull@localhost>2004-04-18 20:47:29 +0000
commita018c6e59c4abccce831ddb3a292198721b9a82a (patch)
treef552050b01afd2254b374b534b0ff44edba61031
parenta19d5569cdbeb72780e7ea694bbf7d31538aaa1c (diff)
downloadlibrpm-tizen-a018c6e59c4abccce831ddb3a292198721b9a82a.tar.gz
librpm-tizen-a018c6e59c4abccce831ddb3a292198721b9a82a.tar.bz2
librpm-tizen-a018c6e59c4abccce831ddb3a292198721b9a82a.zip
Implemented Lua support for the hooking system.
CVS patchset: 7239 CVS date: 2004/04/18 20:47:29
-rw-r--r--rpmio/rpmhook.c46
-rw-r--r--rpmio/rpmhook.h6
-rw-r--r--rpmio/rpmlua.c139
3 files changed, 175 insertions, 16 deletions
diff --git a/rpmio/rpmhook.c b/rpmio/rpmhook.c
index 74938801d..647e30386 100644
--- a/rpmio/rpmhook.c
+++ b/rpmio/rpmhook.c
@@ -28,6 +28,21 @@ typedef struct rpmhookTable_s {
struct rpmhookBucket_s bucket[1];
} * rpmhookTable;
+
+rpmhookArgs rpmhookArgsNew(int argc)
+{
+ rpmhookArgs args = (rpmhookArgs)xcalloc(1, sizeof(struct rpmhookArgs_s)+
+ (argc-1)*sizeof(rpmhookArgv));
+ args->argc = argc;
+ return args;
+}
+
+rpmhookArgs rpmhookArgsFree(rpmhookArgs args)
+{
+ free(args);
+ return NULL;
+}
+
static rpmhookTable rpmhookTableNew(int size)
{
rpmhookTable table =
@@ -154,13 +169,10 @@ static void rpmhookTableDelItem(rpmhookTable *table, const char *name,
static rpmhookArgs rpmhookArgsParse(const char *argt, va_list ap)
{
- int argc = strlen(argt);
+ rpmhookArgs args = rpmhookArgsNew(strlen(argt));
int i;
- rpmhookArgs args = (rpmhookArgs)malloc(sizeof(struct rpmhookArgs_s)+
- (argc-1)*sizeof(rpmhookArgv));
- args->argc = argc;
args->argt = argt;
- for (i = 0; i != argc; i++) {
+ for (i = 0; i != args->argc; i++) {
switch (argt[i]) {
case 's':
args->argv[i].s = va_arg(ap, char *);
@@ -183,21 +195,16 @@ static rpmhookArgs rpmhookArgsParse(const char *argt, va_list ap)
return args;
}
-static void rpmhookTableCallV(rpmhookTable *table, const char *name,
- const char *argt, va_list ap)
+static void rpmhookTableCallArgs(rpmhookTable *table, const char *name,
+ rpmhookArgs args)
{
- rpmhookItem item;
- rpmhookArgs args;
- int n;
- args = rpmhookArgsParse(argt, ap);
- n = rpmhookTableFindBucket(table, name);
- item = (*table)->bucket[n].item;
+ int n = rpmhookTableFindBucket(table, name);
+ rpmhookItem item = (*table)->bucket[n].item;
while (item) {
if (item->func(args, item->data) != 0)
break;
item = item->next;
}
- free(args);
}
static rpmhookTable globalTable = NULL;
@@ -230,12 +237,21 @@ void rpmhookUnregisterAll(const char *name)
void rpmhookCall(const char *name, const char *argt, ...)
{
if (globalTable) {
+ rpmhookArgs args;
va_list ap;
va_start(ap, argt);
- rpmhookTableCallV(&globalTable, name, argt, ap);
+ args = rpmhookArgsParse(argt, ap);
+ rpmhookTableCallArgs(&globalTable, name, args);
+ rpmhookArgsFree(args);
va_end(ap);
}
}
+void rpmhookCallArgs(const char *name, rpmhookArgs args)
+{
+ if (globalTable)
+ rpmhookTableCallArgs(&globalTable, name, args);
+}
+
/* vim:ts=4:sw=4:et
*/
diff --git a/rpmio/rpmhook.h b/rpmio/rpmhook.h
index b80f496e0..78f8e5a8d 100644
--- a/rpmio/rpmhook.h
+++ b/rpmio/rpmhook.h
@@ -2,7 +2,7 @@
#define RPMHOOK_H
typedef union {
- char *s;
+ const char *s;
int i;
float f;
void *p;
@@ -16,11 +16,15 @@ typedef struct rpmhookArgs_s {
typedef int (*rpmhookFunc)(rpmhookArgs args, void *data);
+rpmhookArgs rpmhookArgsNew(int argc);
+rpmhookArgs rpmhookArgsFree(rpmhookArgs args);
+
void rpmhookRegister(const char *name, rpmhookFunc func, void *data);
void rpmhookUnregister(const char *name, rpmhookFunc func, void *data);
void rpmhookUnregisterAny(const char *name, rpmhookFunc func);
void rpmhookUnregisterAll(const char *name);
void rpmhookCall(const char *name, const char *argt, ...);
+void rpmhookCallArgs(const char *name, rpmhookArgs args);
#endif
diff --git a/rpmio/rpmlua.c b/rpmio/rpmlua.c
index e77b4181d..66473aff6 100644
--- a/rpmio/rpmlua.c
+++ b/rpmio/rpmlua.c
@@ -4,6 +4,7 @@
#include <rpmmacro.h>
#include <rpmerr.h>
#include <rpmurl.h>
+#include <rpmhook.h>
#include "../lua/include/lua.h"
#include "../lua/include/lualib.h"
@@ -621,6 +622,141 @@ static int rpm_interactive(lua_State *L)
return 0;
}
+typedef struct rpmluaHookData_s {
+ lua_State *L;
+ int funcRef;
+ int dataRef;
+} * rpmluaHookData;
+
+static int rpmluaHookWrapper(rpmhookArgs args, void *data)
+{
+ rpmluaHookData hookdata = (rpmluaHookData)data;
+ lua_State *L = hookdata->L;
+ int ret = 0;
+ int i;
+ lua_rawgeti(L, LUA_REGISTRYINDEX, hookdata->funcRef);
+ lua_newtable(L);
+ for (i = 0; i != args->argc; i++) {
+ switch (args->argt[i]) {
+ case 's':
+ lua_pushstring(L, args->argv[i].s);
+ lua_rawseti(L, -2, i+1);
+ break;
+ case 'i':
+ lua_pushnumber(L, args->argv[i].i);
+ lua_rawseti(L, -2, i+1);
+ break;
+ case 'f':
+ lua_pushnumber(L, args->argv[i].f);
+ lua_rawseti(L, -2, i+1);
+ break;
+ case 'p':
+ lua_pushlightuserdata(L, args->argv[i].p);
+ lua_rawseti(L, -2, i+1);
+ break;
+ default:
+ luaL_error(L, "unsupported type '%c' as "
+ "a hook argument\n", args->argt[i]);
+ break;
+ }
+ }
+ if (lua_pcall(L, 1, 1, 0) != 0) {
+ rpmError(RPMERR_SCRIPT, _("lua hook failed: %s\n"),
+ lua_tostring(L, -1));
+ lua_pop(L, 1);
+ } else {
+ if (lua_isnumber(L, -1))
+ ret = (int)lua_tonumber(L, -1);
+ lua_pop(L, 1);
+ }
+ return ret;
+}
+
+static int rpm_register(lua_State *L)
+{
+ if (!lua_isstring(L, 1)) {
+ luaL_argerror(L, 1, "hook name expected");
+ } else if (!lua_isfunction(L, 2)) {
+ luaL_argerror(L, 2, "function expected");
+ } else {
+ rpmluaHookData hookdata =
+ lua_newuserdata(L, sizeof(struct rpmluaHookData_s));
+ lua_pushvalue(L, -1);
+ hookdata->dataRef = luaL_ref(L, LUA_REGISTRYINDEX);
+ lua_pushvalue(L, 2);
+ hookdata->funcRef = luaL_ref(L, LUA_REGISTRYINDEX);
+ hookdata->L = L;
+ rpmhookRegister(lua_tostring(L, 1), rpmluaHookWrapper, hookdata);
+ return 1;
+ }
+ return 0;
+}
+
+static int rpm_unregister(lua_State *L)
+{
+ if (!lua_isstring(L, 1)) {
+ luaL_argerror(L, 1, "hook name expected");
+ } else if (!lua_islightuserdata(L, 2)) {
+ luaL_argerror(L, 2, "hook information expected");
+ } else {
+ rpmluaHookData hookdata = (rpmluaHookData)lua_touserdata(L, 2);
+ luaL_unref(L, LUA_REGISTRYINDEX, hookdata->funcRef);
+ luaL_unref(L, LUA_REGISTRYINDEX, hookdata->dataRef);
+ rpmhookUnregister(lua_tostring(L, 1), rpmluaHookWrapper, hookdata);
+ }
+ return 0;
+}
+
+static int rpm_call(lua_State *L)
+{
+ if (!lua_isstring(L, 1)) {
+ luaL_argerror(L, 1, "hook name expected");
+ } else {
+ rpmhookArgs args = rpmhookArgsNew(lua_gettop(L)-1);
+ const char *name = lua_tostring(L, 1);
+ char *argt = (char *)xmalloc(args->argc+1);
+ int i;
+ for (i = 0; i != args->argc; i++) {
+ switch (lua_type(L, i+1)) {
+ case LUA_TNIL:
+ argt[i] = 'p';
+ args->argv[i].p = NULL;
+ break;
+ case LUA_TNUMBER: {
+ float f = (float)lua_tonumber(L, i+1);
+ if (f == (int)f) {
+ argt[i] = 'i';
+ args->argv[i].i = (int)f;
+ } else {
+ argt[i] = 'f';
+ args->argv[i].f = f;
+ }
+ break;
+ }
+ case LUA_TSTRING:
+ argt[i] = 's';
+ args->argv[i].s = lua_tostring(L, i+1);
+ break;
+ case LUA_TUSERDATA:
+ case LUA_TLIGHTUSERDATA:
+ argt[i] = 'p';
+ args->argv[i].p = lua_touserdata(L, i+1);
+ break;
+ default:
+ luaL_error(L, "unsupported Lua type passed to hook");
+ argt[i] = 'p';
+ args->argv[i].p = NULL;
+ break;
+ }
+ }
+ args->argt = argt;
+ rpmhookCallArgs(name, args);
+ free(argt);
+ rpmhookArgsFree(args);
+ }
+ return 0;
+}
+
/* Based on luaB_print. */
static int rpm_print (lua_State *L)
/*@globals fileSystem @*/
@@ -675,6 +811,9 @@ static int rpm_print (lua_State *L)
static const luaL_reg rpmlib[] = {
{"expand", rpm_expand},
{"define", rpm_define},
+ {"register", rpm_register},
+ {"unregister", rpm_unregister},
+ {"call", rpm_call},
{"interactive", rpm_interactive},
{NULL, NULL}
};