diff options
author | niemeyer <devnull@localhost> | 2004-04-18 20:47:29 +0000 |
---|---|---|
committer | niemeyer <devnull@localhost> | 2004-04-18 20:47:29 +0000 |
commit | a018c6e59c4abccce831ddb3a292198721b9a82a (patch) | |
tree | f552050b01afd2254b374b534b0ff44edba61031 /rpmio | |
parent | a19d5569cdbeb72780e7ea694bbf7d31538aaa1c (diff) | |
download | librpm-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
Diffstat (limited to 'rpmio')
-rw-r--r-- | rpmio/rpmhook.c | 46 | ||||
-rw-r--r-- | rpmio/rpmhook.h | 6 | ||||
-rw-r--r-- | rpmio/rpmlua.c | 139 |
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} }; |