+ char *s = NULL;
+ int n;
+
+ n = lua_gettop(L);
+ luaL_checkstring(L, 1 + offset);
+ s = strdup(lua_tostring(L, 1 + offset));
+ if (!s)
+ goto error;
+
+ memset(ptr, 0, sizeof(struct uci_ptr));
+ if (!find_package(L, ctx, s, true))
+ goto error;
+
+ switch (n - offset) {
+ case 4:
+ case 3:
+ ptr->option = luaL_checkstring(L, 3 + offset);
+ /* fall through */
+ case 2:
+ ptr->section = luaL_checkstring(L, 2 + offset);
+ ptr->package = luaL_checkstring(L, 1 + offset);
+ if (uci_lookup_ptr(ctx, ptr, NULL, true) != UCI_OK)
+ goto error;
+ break;
+ case 1:
+ if (uci_lookup_ptr(ctx, ptr, s, true) != UCI_OK)
+ goto error;
+ break;
+ default:
+ luaL_error(L, "invalid argument count");
+ goto error;
+ }
+
+ *buf = s;
+ return 0;
+
+error:
+ if (s)
+ free(s);
+ return 1;
+}
+
+static int
+uci_push_status(lua_State *L, struct uci_context *ctx, bool hasarg)
+{
+ char *str = NULL;
+
+ if (!hasarg)
+ lua_pushboolean(L, (ctx->err == UCI_OK));
+ if (ctx->err) {
+ uci_get_errorstr(ctx, &str, MODNAME);
+ if (str) {
+ lua_pushstring(L, str);
+ free(str);
+ return 2;
+ }
+ }
+ return 1;
+}
+
+static void
+uci_push_option(lua_State *L, struct uci_option *o)
+{
+ struct uci_element *e;
+ int i = 0;
+
+ switch(o->type) {
+ case UCI_TYPE_STRING:
+ lua_pushstring(L, o->v.string);
+ break;
+ case UCI_TYPE_LIST:
+ lua_newtable(L);
+ uci_foreach_element(&o->v.list, e) {
+ i++;
+ lua_pushstring(L, e->name);
+ lua_rawseti(L, -2, i);
+ }
+ break;
+ default:
+ lua_pushnil(L);
+ break;
+ }
+}
+
+static void
+uci_push_section(lua_State *L, struct uci_section *s, int index)
+{
+ struct uci_element *e;
+
+ lua_newtable(L);
+ lua_pushboolean(L, s->anonymous);
+ lua_setfield(L, -2, ".anonymous");
+ lua_pushstring(L, s->type);
+ lua_setfield(L, -2, ".type");
+ lua_pushstring(L, s->e.name);
+ lua_setfield(L, -2, ".name");
+ if (index >= 0) {
+ lua_pushinteger(L, index);
+ lua_setfield(L, -2, ".index");
+ }
+
+ uci_foreach_element(&s->options, e) {
+ struct uci_option *o = uci_to_option(e);
+ uci_push_option(L, o);
+ lua_setfield(L, -2, o->e.name);
+ }
+}
+
+static void
+uci_push_package(lua_State *L, struct uci_package *p)
+{
+ struct uci_element *e;
+ int i = 0;
+
+ lua_newtable(L);
+ uci_foreach_element(&p->sections, e) {
+ uci_push_section(L, uci_to_section(e), i);
+ lua_setfield(L, -2, e->name);
+ i++;
+ }