From 42c5188ed499746fc09917707c929bd96339be14 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 13 Apr 2008 13:06:54 +0200 Subject: [PATCH] add rudimentary lua binding for uci (can only do "load" and "get" at the moment and does not free memory on gc) --- lua/Makefile | 27 +++++++++ lua/uci.c | 166 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 193 insertions(+) create mode 100644 lua/Makefile create mode 100644 lua/uci.c diff --git a/lua/Makefile b/lua/Makefile new file mode 100644 index 0000000..29d7fbd --- /dev/null +++ b/lua/Makefile @@ -0,0 +1,27 @@ +CC=gcc +LD=ld +CFLAGS=-O2 -Wall -Werror -pedantic --std=gnu99 -Wno-unused +CPPFLAGS=-I.. +LIBS=-L.. -luci +OS=$(shell uname) +LINK=$(CC) +ifeq ($(OS),Darwin) + SHLIB_FLAGS=-bundle -undefined dynamic_lookup +else + SHLIB_FLAGS=-shared -Wl,-soname,$(SHLIB_FILE) +endif + +all: uci.so + +uci.so: uci.o + $(LINK) $(SHLIB_FLAGS) -o $@ $^ $(LIBS) + +%.o: %.c + $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $< + +install: + mkdir -p $(DESTDIR)/usr/lib/lua + install -m0644 uci.so $(DESTDIR)/usr/lib/lua/ + +clean: + rm -f *.so *.o uci.so diff --git a/lua/uci.c b/lua/uci.c new file mode 100644 index 0000000..026569f --- /dev/null +++ b/lua/uci.c @@ -0,0 +1,166 @@ +/* + * libuci plugin for Lua + * Copyright (C) 2008 Felix Fietkau + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define MODNAME "uci" +//#define DEBUG 1 + +#ifdef DEBUG +#define DPRINTF(...) fprintf(stderr, __VA_ARGS__) +#else +#define DPRINTF(...) do {} while (0) +#endif + +static struct uci_context *ctx = NULL; + +static struct uci_package * +find_package(const char *name) +{ + struct uci_package *p = NULL; + struct uci_element *e; + uci_foreach_element(&ctx->root, e) { + if (strcmp(e->name, name) != 0) + continue; + + p = uci_to_package(e); + break; + } + return p; +} + +static void uci_lua_perror(lua_State *L, char *name) +{ + lua_getfield(L, LUA_GLOBALSINDEX, "uci"); + lua_getfield(L, -1, "warn"); + if (!lua_isboolean(L, -1)) + goto done; + if (lua_toboolean(L, -1) != 1) + goto done; + uci_perror(ctx, name); +done: + lua_pop(L, 2); +} + +static int +uci_lua_load(lua_State *L) +{ + struct uci_package *p; + const char *s; + + luaL_checkany(L, 1); + s = lua_tostring(L, -1); + p = find_package(s); + if (p) { + uci_unload(ctx, p); + p = NULL; + } + if (uci_load(ctx, s, &p)) { + uci_lua_perror(L, "uci.load"); + lua_pushboolean(L, 0); + } else { + lua_pushboolean(L, 1); + } + + return 1; +} + +static int +uci_lua_get(lua_State *L) +{ + struct uci_lua_context *f; + struct uci_element *e = NULL; + struct uci_package *p = NULL; + char *package = NULL; + char *section = NULL; + char *option = NULL; + char *s; + int err = UCI_ERR_MEM; + + luaL_checkany(L, 1); + s = strdup(lua_tostring(L, -1)); + if (!s) + goto error; + + if ((err = uci_parse_tuple(ctx, s, &package, §ion, &option, NULL))) + goto error; + + if (section == NULL) { + err = UCI_ERR_INVAL; + goto error; + } + + p = find_package(package); + if (!p) { + err = UCI_ERR_NOTFOUND; + goto error; + } + + if ((err = uci_lookup(ctx, &e, p, section, option))) + goto error; + + switch(e->type) { + case UCI_TYPE_SECTION: + lua_pushstring(L, uci_to_section(e)->type); + break; + case UCI_TYPE_OPTION: + lua_pushstring(L, uci_to_option(e)->value); + break; + default: + err = UCI_ERR_INVAL; + goto error; + } +error: + if (s) + free(s); + + switch(err) { + default: + ctx->err = err; + uci_lua_perror(L, "uci.get"); + /* fall through */ + case UCI_ERR_NOTFOUND: + lua_pushnil(L); + /* fall through */ + case 0: + return 1; + } +} + + +static const luaL_Reg uci[] = { + { "load", uci_lua_load }, + { "get", uci_lua_get }, + { NULL, NULL }, +}; + + +int +luaopen_uci(lua_State *L) +{ + ctx = uci_alloc_context(); + if (!ctx) + luaL_error(L, "Cannot allocate UCI context\n"); + luaL_register(L, MODNAME, uci); + return 0; +} -- 2.41.1