From b5c4c2d4adeb3cfb0ea1fb8b663ac822eeb794f9ddb1dd71609409acf73cb9d7 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Fri, 29 Nov 2019 13:16:53 +0000 Subject: [PATCH 1/2] Accepting request 751850 from home:anag:branches:network:cluster - Update to version 1.27.3: * Fix parsing corner case, newlines are not required at end of lines * Add make target for genders_query.tab.c to fix gentoo build issue. * javadoc fix && to & amp;& amp; * fix testsuite to operate where there isn't a default genders file OBS-URL: https://build.opensuse.org/request/show/751850 OBS-URL: https://build.opensuse.org/package/show/network:cluster/genders?expand=0&rev=21 --- genders-1.26.tar.gz | 3 --- genders-1.27.3.tar.gz | 3 +++ genders.changes | 10 ++++++++++ genders.spec | 12 ++++-------- 4 files changed, 17 insertions(+), 11 deletions(-) delete mode 100644 genders-1.26.tar.gz create mode 100644 genders-1.27.3.tar.gz diff --git a/genders-1.26.tar.gz b/genders-1.26.tar.gz deleted file mode 100644 index 0923bb5..0000000 --- a/genders-1.26.tar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d690d9e57e2f2b97809b0dbc689b8812c0b1c9c1dcb141bb0135f865cc2fd902 -size 1103032 diff --git a/genders-1.27.3.tar.gz b/genders-1.27.3.tar.gz new file mode 100644 index 0000000..fc4cb9b --- /dev/null +++ b/genders-1.27.3.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c176045a7dd125313d44abcb7968ded61826028fe906028a2967442426229894 +size 1142250 diff --git a/genders.changes b/genders.changes index 5721cc9..aa54b26 100644 --- a/genders.changes +++ b/genders.changes @@ -1,3 +1,13 @@ +------------------------------------------------------------------- +Fri Nov 29 09:35:37 UTC 2019 - Ana Guerrero Lopez + +- Update to version 1.27.3: + * Fix parsing corner case, newlines are not required at end + of lines + * Add make target for genders_query.tab.c to fix gentoo build issue. + * javadoc fix && to & amp;& amp; + * fix testsuite to operate where there isn't a default genders file + ------------------------------------------------------------------- Thu Jul 18 14:27:16 UTC 2019 - Christian Goll diff --git a/genders.spec b/genders.spec index be4f0fb..846366a 100644 --- a/genders.spec +++ b/genders.spec @@ -1,7 +1,7 @@ # # spec file for package genders # -# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2019 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -19,10 +19,10 @@ # Check file META in sources: update so_version to (API_CURRENT - API_AGE) %define c_api 0 %define cpp_api 2 -%define slash_ver 1-26-1 +%define slash_ver 1-27-3 Name: genders -Version: 1.26 +Version: 1.27.3 Release: 0 Summary: Static cluster configuration database License: GPL-2.0-or-later @@ -31,7 +31,7 @@ Source: https://github.com/chaos/genders/archive/genders-%{slash_ver}/%{ Patch1: Fix-Python-package-installation-use-root.patch Patch2: Remove-PERL_DESTDIR-use-DESTDIR-instead.patch Patch4: lua_bindings.patch -Url: https://github.com/chaos/genders +URL: https://github.com/chaos/genders BuildRequires: autoconf BuildRequires: autoconf-archive BuildRequires: automake @@ -45,7 +45,6 @@ BuildRequires: python-devel BuildRequires: python3 BuildRequires: python3-devel BuildRequires: perl(ExtUtils::MakeMaker) -BuildRoot: %{_tmppath}/%{name}-%{version}-build Requires: %{name}-base %description @@ -222,19 +221,16 @@ sed -i -e 's/^\([^#]\)/## \1/' %{buildroot}%{_sysconfdir}/genders %{_bindir}/* %files base -%defattr(-,root,root) %doc README NEWS ChangeLog DISCLAIMER DISCLAIMER.UC TUTORIAL genders.sample %license COPYING %config(noreplace) %{_sysconfdir}/genders %files perl-compat -%defattr(-,root,root) %dir %{_prefix}/lib/genders %{_prefix}/lib/genders/* %{_mandir}/man3/gendlib* %files devel -%defattr(-,root,root) %{_includedir}/* %{_libdir}/libgenders.so %if %{?_with_cplusplus_extensions:1}%{!?_with_cplusplus_extensions:0} From 46d9c180408ee8ddbe11e392e9b0c36f7dcc6dd4ad3c8f9dc7ca4ea5b8fe76d0 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Fri, 29 Nov 2019 13:36:18 +0000 Subject: [PATCH 2/2] updated lua patch which works only with lua5.3 OBS-URL: https://build.opensuse.org/package/show/network:cluster/genders?expand=0&rev=22 --- genders.spec | 3 +- lua_bindings.patch | 1226 +++++++++++++++++++++++++++----------------- 2 files changed, 758 insertions(+), 471 deletions(-) diff --git a/genders.spec b/genders.spec index 846366a..3915480 100644 --- a/genders.spec +++ b/genders.spec @@ -143,7 +143,7 @@ mv genders-genders-%{slash_ver}/* . rm -r genders-genders-%{slash_ver} %patch1 -p1 %patch2 -p1 -%patch4 -p1 -R +%patch4 -p1 %build aclocal --force --install -I config @@ -161,6 +161,7 @@ autoconf --force %{?_without_python_extensions} \ %{?_with_cplusplus_extensions} \ %{?_without_cplusplus_extensions} \ + --with-lua-extensions \ --without-java-extensions \ --disable-static diff --git a/lua_bindings.patch b/lua_bindings.patch index 31c2c8e..f68fa8a 100644 --- a/lua_bindings.patch +++ b/lua_bindings.patch @@ -1,508 +1,794 @@ diff --git a/config/ac_lua_extensions.m4 b/config/ac_lua_extensions.m4 -deleted file mode 100644 -index 4dbfb7b..0000000 ---- a/config/ac_lua_extensions.m4 -+++ /dev/null -@@ -1,21 +0,0 @@ -- --AC_DEFUN([AC_LUA_EXTENSIONS], --[ -- AC_MSG_CHECKING(for --with-lua-extensions) -- AC_ARG_WITH(lua-extensions, -- AC_HELP_STRING([--with-lua-extensions=], -- [enable or disable lua extensions build]), -- [ case "$withval" in -- yes) -- ac_with_lua_extensions=yes -- ;; -- no) -- ac_with_lua_extensions=no -- ;; -- *) -- ac_with_lua_extensions=yes -- ;; -- esac ] -- ) -- AC_MSG_RESULT(${ac_with_lua_extensions=yes}) --]) +new file mode 100644 +index 0000000..9421588 +--- /dev/null ++++ b/config/ac_lua_extensions.m4 +@@ -0,0 +1,21 @@ ++ ++AC_DEFUN([AC_LUA_EXTENSIONS], ++[ ++ AC_MSG_CHECKING(for --with-lua-extensions) ++ AC_ARG_WITH(lua-extensions, ++ AC_HELP_STRING([--with-lua-extensions=], ++ [enable or disable lua extensions build]), ++ [ case "$withval" in ++ yes) ++ ac_with_lua_extensions=yes ++ ;; ++ no) ++ ac_with_lua_extensions=no ++ ;; ++ *) ++ ac_with_lua_extensions=yes ++ ;; ++ esac ] ++ ) ++ AC_MSG_RESULT(${ac_with_lua_extensions=no}) ++]) diff --git a/config/x_ac_lua.m4 b/config/x_ac_lua.m4 -deleted file mode 100644 -index 2f5f587..0000000 ---- a/config/x_ac_lua.m4 -+++ /dev/null -@@ -1,60 +0,0 @@ --##***************************************************************************** --# AUTHOR: --# Mark Grondona --# --# SYNOPSIS: --# AC_LUA --# --# DESCRIPTION: --# Check for presence of lua libs and headers --##***************************************************************************** -- -- --AC_DEFUN([X_AC_LUA], --[ -- x_ac_lua_pkg_name="lua" -- #check for 5.3 then 5.2 then 5.1 -- PKG_CHECK_EXISTS([lua5.3], [x_ac_lua_pkg_name=lua5.3], -- [PKG_CHECK_EXISTS([lua-5.3], [x_ac_lua_pkg_name=lua-5.3], -- [PKG_CHECK_EXISTS([lua5.2], [x_ac_lua_pkg_name=lua5.2], -- [PKG_CHECK_EXISTS([lua-5.2], [x_ac_lua_pkg_name=lua-5.2], -- [PKG_CHECK_EXISTS([lua5.1], [x_ac_lua_pkg_name=lua5.1], -- [PKG_CHECK_EXISTS([lua-5.1], [x_ac_lua_pkg_name=lua-5.1], -- [x_ac_lua_pkg_name="lua >= 5.1"])])])])])]) -- PKG_CHECK_MODULES([lua], ${x_ac_lua_pkg_name}, -- [x_ac_have_lua="yes"], -- [x_ac_have_lua="no"]) -- -- if test "x$x_ac_have_lua" = "xyes"; then -- saved_CFLAGS="$CFLAGS" -- saved_LIBS="$LIBS" -- lua_CFLAGS="$lua_CFLAGS" -- CFLAGS="$CFLAGS $lua_CFLAGS" -- LIBS="$LIBS $lua_LIBS" -- AC_MSG_CHECKING([for whether we can link to liblua]) -- AC_TRY_LINK( -- [#include -- #include -- #include -- ], -- [lua_State *L = luaL_newstate (); luaL_openlibs(L); -- ], -- [], [x_ac_have_lua="no"]) -- -- AC_MSG_RESULT([$x_ac_have_lua $x_ac_lua_pkg_name]) -- if test "x$x_ac_have_lua" = "xno"; then -- AC_MSG_WARN([unable to link against lua libraries]) -- else -- AC_DEFINE(HAVE_LUA, 1, [Define to 1 if we have the Lua library]) -- # We can not define something here to determine version for systems -- # that use just liblua we will not know what version we are using. -- # Use LUA_VERSION_NUM as in lua.h it will always be right. -- fi -- CFLAGS="$saved_CFLAGS" -- LIBS="$saved_LIBS" -- else -- AC_MSG_WARN([unable to locate lua package]) -- fi -- -- AM_CONDITIONAL(HAVE_LUA, test "x$x_ac_have_lua" = "xyes") --]) +new file mode 100644 +index 0000000..2f5f587 +--- /dev/null ++++ b/config/x_ac_lua.m4 +@@ -0,0 +1,60 @@ ++##***************************************************************************** ++# AUTHOR: ++# Mark Grondona ++# ++# SYNOPSIS: ++# AC_LUA ++# ++# DESCRIPTION: ++# Check for presence of lua libs and headers ++##***************************************************************************** ++ ++ ++AC_DEFUN([X_AC_LUA], ++[ ++ x_ac_lua_pkg_name="lua" ++ #check for 5.3 then 5.2 then 5.1 ++ PKG_CHECK_EXISTS([lua5.3], [x_ac_lua_pkg_name=lua5.3], ++ [PKG_CHECK_EXISTS([lua-5.3], [x_ac_lua_pkg_name=lua-5.3], ++ [PKG_CHECK_EXISTS([lua5.2], [x_ac_lua_pkg_name=lua5.2], ++ [PKG_CHECK_EXISTS([lua-5.2], [x_ac_lua_pkg_name=lua-5.2], ++ [PKG_CHECK_EXISTS([lua5.1], [x_ac_lua_pkg_name=lua5.1], ++ [PKG_CHECK_EXISTS([lua-5.1], [x_ac_lua_pkg_name=lua-5.1], ++ [x_ac_lua_pkg_name="lua >= 5.1"])])])])])]) ++ PKG_CHECK_MODULES([lua], ${x_ac_lua_pkg_name}, ++ [x_ac_have_lua="yes"], ++ [x_ac_have_lua="no"]) ++ ++ if test "x$x_ac_have_lua" = "xyes"; then ++ saved_CFLAGS="$CFLAGS" ++ saved_LIBS="$LIBS" ++ lua_CFLAGS="$lua_CFLAGS" ++ CFLAGS="$CFLAGS $lua_CFLAGS" ++ LIBS="$LIBS $lua_LIBS" ++ AC_MSG_CHECKING([for whether we can link to liblua]) ++ AC_TRY_LINK( ++ [#include ++ #include ++ #include ++ ], ++ [lua_State *L = luaL_newstate (); luaL_openlibs(L); ++ ], ++ [], [x_ac_have_lua="no"]) ++ ++ AC_MSG_RESULT([$x_ac_have_lua $x_ac_lua_pkg_name]) ++ if test "x$x_ac_have_lua" = "xno"; then ++ AC_MSG_WARN([unable to link against lua libraries]) ++ else ++ AC_DEFINE(HAVE_LUA, 1, [Define to 1 if we have the Lua library]) ++ # We can not define something here to determine version for systems ++ # that use just liblua we will not know what version we are using. ++ # Use LUA_VERSION_NUM as in lua.h it will always be right. ++ fi ++ CFLAGS="$saved_CFLAGS" ++ LIBS="$saved_LIBS" ++ else ++ AC_MSG_WARN([unable to locate lua package]) ++ fi ++ ++ AM_CONDITIONAL(HAVE_LUA, test "x$x_ac_have_lua" = "xyes") ++]) diff --git a/configure.ac b/configure.ac -index 5096c98..9f43805 100644 +index 07496ea..58c6684 100644 --- a/configure.ac +++ b/configure.ac -@@ -68,7 +68,6 @@ PYTHONGENDERS_MINOR=2 +@@ -68,6 +68,7 @@ PYTHONGENDERS_MINOR=2 PYTHONGENDERS_VERSION=$PYTHONGENDERS_MAJOR.$PYTHONGENDERS_MINOR AC_SUBST([PYTHONGENDERS_VERSION]) -- ++ ## # Checks for programs. ## -@@ -87,7 +86,6 @@ AC_PATH_PROG([JAVAH], [javah]) +@@ -86,6 +87,7 @@ AC_PATH_PROG([JAVAH], [javah]) AC_PATH_PROG([JAVA], [java]) AC_PATH_PROG([JAR], [jar]) AC_PATH_PROG([JAVADOC], [javadoc]) --AC_PATH_PROG([JAVADOC], [lua]) ++AC_PATH_PROG([JAVADOC], [lua]) AC_DEBUG ## -@@ -210,21 +208,6 @@ AM_CONDITIONAL(WITH_CPLUSPLUS_EXTENSIONS, [test "$ac_with_cplusplus_extensions" +@@ -206,6 +208,24 @@ AM_CONDITIONAL(WITH_CPLUSPLUS_EXTENSIONS, [test "$ac_with_cplusplus_extensions" AC_JAVA_EXTENSIONS AM_CONDITIONAL(WITH_JAVA_EXTENSIONS, [test "$ac_with_java_extensions" = "yes"]) -- --# --# expand lua --# --AX_PROG_LUA --AX_LUA_HEADERS --AX_LUA_LIBS -- --# --# Check for lua --# -- --AC_LUA_EXTENSIONS --AM_CONDITIONAL(WITH_LUA_EXTENSIONS, [test "$ac_with_lua_extensions" = "yes"]) -- ++# ++# Check for lua, which means create commanline conditional ++# ++AC_LUA_EXTENSIONS ++AM_CONDITIONAL(WITH_LUA_EXTENSIONS, [test "$ac_with_lua_extensions" = "yes"]) ++# ++# expand lua ++# ++if test "x$ac_with_lua_extensions" = "xyes" ; then ++# beware, the ACTION-IF-NOT-FOUND is not working ++AX_PROG_LUA([5.3],,,:) ++# The test of headers fail, if LUA_VERSION is empty ++if test LUA_VERSION ; then ++AX_LUA_HEADERS ++AX_LUA_LIBS ++fi ++fi ++ ## # Checks for typedefs, structures, and compiler characteristics. ## -@@ -265,7 +248,6 @@ AC_CONFIG_FILES( \ +@@ -246,6 +266,7 @@ AC_CONFIG_FILES( \ src/extensions/perl/Genders/Makefile \ src/extensions/perl/Genders/Genders.pm \ src/extensions/python/Makefile \ -- src/extensions/lua/Makefile \ ++ src/extensions/lua/Makefile \ src/extensions/python/genderssetup.py \ src/extensions/java/Makefile \ src/testsuite/Makefile \ +diff --git a/genders.spec b/genders.spec +new file mode 100644 +index 0000000..cd09930 +--- /dev/null ++++ b/genders.spec +@@ -0,0 +1,110 @@ ++Name: genders ++Version: 1.26 ++Release: 1 ++Summary: Static cluster configuration database ++URL: https://github.com/chaos/genders ++Group: System Environment/Base ++License: GPL ++Source: %{name}-%{version}.tar.gz ++Requires: perl ++BuildRequires: bison flex ++BuildRequires: perl(ExtUtils::MakeMaker) ++BuildRequires: python ++BuildRequires: python-devel ++BuildRequires: libtool ++BuildRoot: %{_tmppath}/%{name}-%{version} ++ ++%description ++Genders is a static cluster configuration database used for cluster ++configuration management. It is used by a variety of tools and ++scripts for management of large clusters. The genders database is ++typically replicated on every node of the cluster. It describes the ++layout and configuration of the cluster so that tools and scripts can ++sense the variations of cluster nodes. By abstracting this information ++into a plain text file, it becomes possible to change the ++configuration of a cluster by modifying only one file. ++ ++%package compat ++Summary: Compatibility library ++Group: System Environment/Base ++%description compat ++genders API that is compatible with earlier releases of genders ++ ++%{!?_with_perl_extensions: %{!?_without_perl_extensions: %define _with_perl_extensions --with-perl-extensions}} ++%{!?_with_python_extensions: %{!?_without_python_extensions: %define _with_python_extensions --with-python-extensions}} ++%{!?_with_cplusplus_extensions: %{!?_without_cplusplus_extensions: %define _with_cplusplus_extensions --with-cplusplus-extensions}} ++%{!?_with_java_extensions: %{!?_without_java_extensions: %define _without_java_extensions --without-java-extensions}} ++%{!?_with_lua_extensions: %{!?_without_lua_extensions: %define _without_lua_extensions --without-lua-extensions}} ++ ++# choose vendor arch by default ++%{!?_with_perl_site_arch: %{!?_with_perl_vendor_arch: %define _with_perl_vendor_arch --with-perl-vendor-arch}} ++ ++%prep ++%setup -q -n %{name}-%{version} ++ ++%build ++%configure --program-prefix=%{?_program_prefix:%{_program_prefix}} \ ++ --with-extension-destdir="$RPM_BUILD_ROOT" \ ++ %{?_with_perl_extensions} \ ++ %{?_without_perl_extensions} \ ++ %{?_with_perl_site_arch} \ ++ %{?_without_perl_site_arch} \ ++ %{?_with_perl_vendor_arch} \ ++ %{?_without_perl_vendor_arch} \ ++ %{?_with_python_extensions} \ ++ %{?_without_python_extensions} \ ++ %{?_with_cplusplus_extensions} \ ++ %{?_without_cplusplus_extensions} \ ++ %{?_with_java_extensions} \ ++ %{?_without_java_extensions}\ ++ %{?_with_lua_extensions} \ ++ %{?_without_lua_extension} ++make ++ ++%install ++rm -rf $RPM_BUILD_ROOT ++DESTDIR="$RPM_BUILD_ROOT" make install ++ ++%files ++%defattr(-,root,root) ++%doc README NEWS ChangeLog DISCLAIMER DISCLAIMER.UC COPYING TUTORIAL genders.sample ++%if %{?_with_java_extensions:1}%{!?_with_java_extensions:0} ++%dir %{_datadir}/doc/%{name}-%{version}-javadoc/ ++%doc %{_datadir}/doc/%{name}-%{version}-javadoc/* ++%endif ++# It doesn't matter if the user chooses a 32bit or 64bit target. The ++# packaging must work off whatever Perl is installed. ++%if %{?_with_perl_site_arch:1}%{!?_with_perl_site_arch:0} ++%define _perldir %(perl -e 'use Config; $T=$Config{installsitearch}; $P=$Config{siteprefix}; $T=~/$P\\/(.*)/; print "%{_prefix}/$1\\n"') ++%endif ++%if %{?_with_perl_vendor_arch:1}%{!?_with_perl_vendor_arch:0} ++%define _perldir %(perl -e 'use Config; $T=$Config{installvendorarch}; $P=$Config{vendorprefix}; $T=~/$P\\/(.*)/; print "%{_prefix}/$1\\n"') ++%endif ++%{_mandir}/man1/* ++%{_mandir}/man3/genders* ++%{_mandir}/man3/libgenders* ++%{_includedir}/* ++%{_bindir}/* ++%{_libdir}/libgenders.* ++%if %{?_with_perl_extensions:1}%{!?_with_perl_extensions:0} ++%{_mandir}/man3/Libgenders* ++%{_mandir}/man3/Genders* ++%{_perldir}/* ++%endif ++%if %{?_with_python_extensions:1}%{!?_with_python_extensions:0} ++%{_exec_prefix}/lib*/python* ++%endif ++%if %{?_with_cplusplus_extensions:1}%{!?_with_cplusplus_extensions:0} ++%{_libdir}/libgendersplusplus.* ++%endif ++%if %{?_with_java_extensions:1}%{!?_with_java_extensions:0} ++%{_javadir}/* ++%{_libdir}/libGendersjni.* ++%endif ++ ++%files compat ++%defattr(-,root,root) ++%{_mandir}/man3/gendlib* ++%{_prefix}/lib/genders/* ++ ++ diff --git a/src/extensions/Makefile.am b/src/extensions/Makefile.am -index e85f6c2..ec963c4 100644 +index ec963c4..e85f6c2 100644 --- a/src/extensions/Makefile.am +++ b/src/extensions/Makefile.am @@ -4,4 +4,4 @@ ## Process this file with automake to produce Makefile.in. ##***************************************************************************** --SUBDIRS = cplusplus java perl python lua -+SUBDIRS = cplusplus java perl python +-SUBDIRS = cplusplus java perl python ++SUBDIRS = cplusplus java perl python lua +diff --git a/src/extensions/lua/GendersTest/GendersTest.lua b/src/extensions/lua/GendersTest/GendersTest.lua +new file mode 100755 +index 0000000..7e28473 +--- /dev/null ++++ b/src/extensions/lua/GendersTest/GendersTest.lua +@@ -0,0 +1,134 @@ ++#!/usr/bin/lua ++ ++db_file = "testgenders" ++ ++genders_lib = require("genders") ++genders_handle = nil ++ ++-- wrapper to for using pcall ++function wrapper_new() ++ genders_handle = genders_lib.new(db_file) ++end ++ ++str_err = "" ++str_out = "" ++ ++no_load = nil ++error_status = 0 ++ ++getter_funcs = {"getnumattrs","getnumnodes","getnodes"} ++list_nodes = {"foobar","hype355","null"} ++list_attr = {"foobar","mgmt"} ++-- attr <-> value mismatch as this is dict! ++list_attrval = {["foobaar"] = "cfhost", ["hypei"] = "cfhost"} ++list_query = { "mgmt","mgmt||login","mhmt&&login","~mgmt"} ++ ++local open_lib, genders_handle = pcall(genders_lib.new,db_file,genders_lib) ++if open_lib then ++ print("Loaded database \""..db_file.."\"") ++ for _, func_name in ipairs(getter_funcs) do ++ local str = "return function(handle) return pcall(handle."..func_name..",handle) end" ++ local wrap_func = assert(load(str)) ++ local func = wrap_func() ++ local ok,ret_val = func(genders_handle) ++ if ok then ++ if type(ret_val) ~= "table" then ++ print(func_name.." :: "..ret_val) ++ else ++ local tmp_str = func_name.." :: " ++ for _,val in ipairs(ret_val) do ++ tmp_str = tmp_str..val..", " ++ end ++ print(tmp_str) ++ end ++ else ++ error_status = 1 ++ str_err = "Could not call "..func_name..": "..ret_val ++ end ++ end ++ local ok, ret_val = pcall(genders_handle.getnodes,genders_handle,"mgmt") ++ if ok then ++ local tmp_str = "getnodes(\"mgmt\") :: " for _,val in ipairs(ret_val) do tmp_str = tmp_str..val..", " end ++ print(tmp_str) ++ else ++ error_status = 1 ++ str_err = "Could not call: getnodes(\"mgmt\")"..ret_val ++ end ++ local ok, ret_val = pcall(genders_handle.getnodes,genders_handle,"foobarlalala") ++ if ok then ++ local tmp_str = "getnodes(\"foobarlalala\") :: " for _,val in ipairs(ret_val) do tmp_str = tmp_str..val..", " end ++ print(tmp_str) ++ else ++ error_status = 1 ++ str_err = "Could not call: getnodes(\"foobarlalala\")"..ret_val ++ end ++ local ok, ret_val = pcall(genders_handle.getnodes,genders_handle,"cfhost","foobar") ++ if ok then ++ local tmp_str = "getnodes(\"cfhost\",\"foobar\") :: " for _,val in ipairs(ret_val) do tmp_str = tmp_str..val..", " end ++ print(tmp_str) ++ else ++ error_status = 1 ++ str_err = "Could not call: getnodes(\"cfhost\",\"foobar\")"..ret_val ++ end ++ local ok, ret_val = pcall(genders_handle.getnodes,genders_handle,"cfhost","hypei") ++ if ok then ++ local tmp_str = "getnodes(\"cfhost\",\"hypei\") :: " for _,val in ipairs(ret_val) do tmp_str = tmp_str..val..", " end ++ print(tmp_str) ++ else ++ error_status = 1 ++ str_err = "Could not call: getnodes(\"cfhost\",\"hypei\")"..ret_val ++ end ++ local ok, ret_val = pcall(genders_handle.getattr,genders_handle,"hype355") ++ if ok then ++ local tmp_str = "getattr(\"hype355\") :: " for key,value in pairs(ret_val) do tmp_str = tmp_str..key if value == "" then tmp_str = tmp_str..", " else tmp_str = tmp_str.."="..value.."," end end ++ print(tmp_str) ++ else ++ error_status = 1 ++ str_err = "Could not call: getattr(\"hype355\")"..ret_val ++ end ++ for _,node in ipairs(list_nodes) do ++ local ok, ret_val = pcall(genders_handle.isnode,genders_handle,node) ++ if ok then ++ if ret_val then print("isnode("..node..") = true") else print("isnode("..node..") = false") end ++ else ++ error_status = 1 ++ str_err = "Could not call: isnode("..node..") "..ret_val ++ end ++ end ++ for _,attr in ipairs(list_attr) do ++ local ok, ret_val = pcall(genders_handle.isattr,genders_handle,attr) ++ if ok then ++ if ret_val then print("isattr("..attr..") = true") else print("isattr("..attr..") = false") end ++ else ++ error_status = 1 ++ str_err = "Could not call: isattr("..attr..") "..ret_val ++ end ++ end ++ for value,attr in pairs(list_attrval) do ++ local ok, ret_val = pcall(genders_handle.isattrval,genders_handle,attr,value) ++ if ok then ++ if ret_val then print("isattrval("..attr..","..value..") = true") else print("isattrval("..attr..","..value..") = false") end ++ else ++ error_status = 1 ++ str_err = "Could not call: isattr("..attr..") "..ret_val ++ end ++ end ++ for _,qry in ipairs(list_query) do ++ local ok, ret_val = pcall(genders_handle.query,genders_handle,qry) ++ if ok then ++ local tmp_str = "query("..qry..") :: " for _,val in pairs(ret_val) do tmp_str = tmp_str..val..", " end ++ print(tmp_str) ++ else ++ error_status = 1 ++ str_err = "Could not call: query("..qry..")"..ret_val ++ end ++ end ++else ++ str_err = "Failure in loading database \""..db_file.."\"" ++ error_status = 1 ++end ++if error_status == 0 then ++ print("No errors") ++else ++ print("Collected errors are: "..str_err) ++end +diff --git a/src/extensions/lua/GendersTest/testgenders b/src/extensions/lua/GendersTest/testgenders +new file mode 100644 +index 0000000..4d17db1 +--- /dev/null ++++ b/src/extensions/lua/GendersTest/testgenders +@@ -0,0 +1,21 @@ ++########################################################################## ++# $URL: file:///var/svn/cfengine/clusters/hype/genders $ ++# $Author: tdhooge $ ++# $Date: 2012-06-29 17:05:40 -0700 (Fri, 29 Jun 2012) $ ++# $Rev: 3594 $ ++########################################################################### ++ ++# Mgmt ++hype[137,355] pdsh_all_skip,mgmt,dhcpd,sshd,tftp,named,nfs,ntpserv ++hype[137,355] networker,crond,rsshd ++ ++hype355 primgmt,opensmd,powerman,conman,sendmail,sysloghost,moab ++hype355 passwdhost=hype:hypei,sshkeyhost,cfhost=hypei,mysqld ++hype355 skummee,perfmgr,httpd,logarch ++hype137 httpd ++hype137 altmgmt ++ ++# Login ++hype[136,356] login,cups,iptables,ksshd,ksshd_client,bluenet,atd ++hype136 ipforw,skummee,mysqld ++hype[136,356] crond,rsshd,psacct diff --git a/src/extensions/lua/Makefile.am b/src/extensions/lua/Makefile.am -deleted file mode 100644 -index 4512cee..0000000 ---- a/src/extensions/lua/Makefile.am -+++ /dev/null -@@ -1,21 +0,0 @@ --# DESTDIR is usually set during make install time, not configure or --# make time, so we work around it with the --with-extension-destdir --# autoconf option. -- -- --if WITH_LUA_EXTENSIONS -- --luaexec_LTLIBRARIES = genders.la -- --genders_la_SOURCES = genderslua.c -- --genders_la_CFLAGS = @LUA_INCLUDE@ -I../../libgenders/ -- --genders_la_LDFLAGS = -module -avoid-version -- --genders_la_LIBADD = ../../libgenders/libgenders.la $(OTHER_FLAGS) @LUA_LIB@ -- -- --endif -- --EXTRA_DIST = genderslua.c +new file mode 100644 +index 0000000..4512cee +--- /dev/null ++++ b/src/extensions/lua/Makefile.am +@@ -0,0 +1,21 @@ ++# DESTDIR is usually set during make install time, not configure or ++# make time, so we work around it with the --with-extension-destdir ++# autoconf option. ++ ++ ++if WITH_LUA_EXTENSIONS ++ ++luaexec_LTLIBRARIES = genders.la ++ ++genders_la_SOURCES = genderslua.c ++ ++genders_la_CFLAGS = @LUA_INCLUDE@ -I../../libgenders/ ++ ++genders_la_LDFLAGS = -module -avoid-version ++ ++genders_la_LIBADD = ../../libgenders/libgenders.la $(OTHER_FLAGS) @LUA_LIB@ ++ ++ ++endif ++ ++EXTRA_DIST = genderslua.c diff --git a/src/extensions/lua/genderslua.c b/src/extensions/lua/genderslua.c -deleted file mode 100644 -index f2364af..0000000 ---- a/src/extensions/lua/genderslua.c -+++ /dev/null -@@ -1,322 +0,0 @@ --/***************************************************************************** -- * Copyright (C) 2018 SUSE LLC -- * Written by Christian Goll -- * -- * This file is part of Genders, a cluster configuration database. -- * For details, see . -- * -- * Genders is free software; you can redistribute it and/or modify it under -- * the terms of the GNU General Public License as published by the Free -- * Software Foundation; either version 2 of the License, or (at your option) -- * any later version. -- * -- * Genders 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. -- * -- * You should have received a copy of the GNU General Public License along -- * with Genders. If not, see . --\*****************************************************************************/ --#if HAVE_CONFIG_H --#include "config.h" --#endif /* HAVE_CONFIG_H */ --#include --#include --#include --#include --#include --#include -- --typedef struct { -- /* genders_t itself is a pointer */ -- genders_t handle; -- char *db_name; -- } lgenders_userdata_t; -- --static int lgenders_new(lua_State *L) { -- lgenders_userdata_t *dbh; -- const char *db_name, *g_error; -- /* check for argument vailidy */ -- db_name = luaL_checkstring(L,1); -- if (db_name == NULL) -- luaL_error(L,"database name could not be empty"); -- /* Create the user data pushing it onto the stack. We also pre-initialize -- * the member of the userdata in case initialization fails in some way. If -- * that happens we want the userdata to be in a consistent state for __gc. -- */ -- dbh = (lgenders_userdata_t *)lua_newuserdata(L, sizeof(*dbh)); -- dbh->handle = NULL; -- dbh->db_name = NULL; -- /* Add the metatable to the stack. */ -- luaL_getmetatable(L, "LGenders"); -- /* Set the metatable on the userdata. */ -- lua_setmetatable(L, -2); -- /* Create the handle */ -- dbh->handle = genders_handle_create(); -- dbh->db_name = strdup(db_name); -- if(genders_load_data(dbh->handle,dbh->db_name) != 0) { -- g_error = strdup(genders_errormsg(dbh->handle)); -- luaL_error(L,g_error); -- } -- return 1; --} --static int lgenders_reload(lua_State *L) { -- lgenders_userdata_t *dbh; -- const char *db_name, *g_error; -- dbh = (lgenders_userdata_t *)luaL_checkudata(L, 1, "LGenders"); -- /* check for argument vailidy */ -- db_name = luaL_checkstring(L,2); -- if (db_name == NULL) -- db_name = strdup(dbh->db_name); -- if (dbh->handle != NULL) -- genders_handle_destroy(dbh->handle); -- dbh->db_name = NULL; -- /* Create the handle */ -- dbh->handle = genders_handle_create(); -- dbh->db_name = strdup(db_name); -- if(genders_load_data(dbh->handle,dbh->db_name) != 0) { -- g_error = strdup(genders_errormsg(dbh->handle)); -- luaL_error(L,g_error); -- } -- return 0; --} --static int lgenders_destroy(lua_State *L) { -- lgenders_userdata_t *dbh; -- dbh = (lgenders_userdata_t *)luaL_checkudata(L, 1, "LGenders"); -- /* pass return value to lus */ -- if (dbh->handle != NULL) -- genders_handle_destroy(dbh->handle); -- -- if (dbh->db_name != NULL) -- free(dbh->db_name); -- dbh->db_name = NULL; -- return 0; --} -- --static int lgenders_getnumnodes(lua_State *L) { -- lgenders_userdata_t *dbh; -- dbh = (lgenders_userdata_t *)luaL_checkudata(L, 1, "LGenders"); -- lua_pushinteger(L,genders_getnumnodes(dbh->handle)); -- return 1; --} -- --static int lgenders_getnumattrs(lua_State *L) { -- lgenders_userdata_t *dbh; -- dbh = (lgenders_userdata_t *)luaL_checkudata(L, 1, "LGenders"); -- lua_pushinteger(L,genders_getnumattrs(dbh->handle)); -- return 1; --} -- --static int lgenders_getnodes(lua_State *L) { -- char** nodelist; -- const char *g_error, *attr, *val; -- int size, nr_nodes, i, nr_args = 0; -- lgenders_userdata_t *dbh; -- dbh = (lgenders_userdata_t *)luaL_checkudata(L, 1, "LGenders"); -- /* create space for the genders stuff */ -- size = genders_nodelist_create(dbh->handle,&nodelist); -- if(size == -1) { -- g_error = strdup(genders_errormsg(dbh->handle)); -- luaL_error(L,g_error); -- } -- attr = NULL; val = NULL; -- /* check for attr and val */ -- nr_args = lua_gettop(L); -- if(nr_args > 1) -- attr = luaL_checkstring(L,2); -- if(nr_args > 2) -- val = luaL_checkstring(L,3); -- if(nr_args > 3) -- luaL_error(L,"getnodes accepts none,one or two arguments"); -- nr_nodes = genders_getnodes(dbh->handle,nodelist,size,attr,val); -- lua_newtable(L); -- for(i = 0; i < nr_nodes; i++) { -- lua_pushstring(L,nodelist[i]); -- lua_rawseti(L,-2,i+1); -- } -- /* destroy list of nodes */ -- if(genders_nodelist_destroy(dbh->handle,nodelist) == -1) { -- g_error = strdup(genders_errormsg(dbh->handle)); -- luaL_error(L,g_error); -- } -- return 1; --} -- --static int lgenders_query(lua_State *L) { -- char** nodelist; -- const char *g_error, *query; -- int size, nr_nodes, i, nr_args = 0; -- lgenders_userdata_t *dbh; -- dbh = (lgenders_userdata_t *)luaL_checkudata(L, 1, "LGenders"); -- /* create space for the genders stuff */ -- size = genders_nodelist_create(dbh->handle,&nodelist); -- if(size == -1) { -- g_error = strdup(genders_errormsg(dbh->handle)); -- luaL_error(L,g_error); -- } -- nr_args = lua_gettop(L); -- if(nr_args == 2) -- query = luaL_checkstring(L,2); -- else -- luaL_error(L,"query must be called with one argument"); -- nr_nodes = genders_query(dbh->handle,nodelist,size,query); -- lua_newtable(L); -- for(i = 0; i < nr_nodes; i++) { -- lua_pushstring(L,nodelist[i]); -- lua_rawseti(L,-2,i+1); -- } -- /* destroy list of nodes */ -- if(genders_nodelist_destroy(dbh->handle,nodelist) == -1) { -- g_error = strdup(genders_errormsg(dbh->handle)); -- luaL_error(L,g_error); -- } -- return 1; --} --static int lgenders_getattr(lua_State *L) { -- char **attr_list, **val_list; -- const char *node, *g_error; -- int ret_code, nr_args, size_attr, i = 0; -- lgenders_userdata_t *dbh; -- dbh = (lgenders_userdata_t *)luaL_checkudata(L, 1, "LGenders"); -- nr_args = lua_gettop(L); -- if(nr_args == 2) -- node = luaL_checkstring(L,2); -- else -- luaL_error(L,"query must be called with one argument"); -- /* create space for the lists */ -- ret_code = genders_attrlist_create(dbh->handle,&attr_list); -- if(ret_code == -1) { -- g_error = strdup(genders_errormsg(dbh->handle)); -- luaL_error(L,g_error); -- } -- ret_code = genders_vallist_create(dbh->handle,&val_list); -- if(ret_code == -1) { -- g_error = strdup(genders_errormsg(dbh->handle)); -- luaL_error(L,g_error); -- } -- /* hopefully size (which is in ret_code) of attr_list and val_list are the same */ -- size_attr = genders_getattr(dbh->handle,attr_list,val_list,ret_code,node); -- if(size_attr == -1) { -- g_error = strdup(genders_errormsg(dbh->handle)); -- luaL_error(L,g_error); -- } -- lua_newtable(L); -- for(i = 0; i < size_attr; i++) { -- lua_pushstring(L, attr_list[i]); -- lua_pushstring(L, val_list[i]); -- lua_settable(L, -3); -- } -- /* destroy list of nodes */ -- if(genders_vallist_destroy(dbh->handle,val_list) == -1) { -- g_error = strdup(genders_errormsg(dbh->handle)); -- luaL_error(L,g_error); -- } -- if(genders_attrlist_destroy(dbh->handle,attr_list) == -1) { -- g_error = strdup(genders_errormsg(dbh->handle)); -- luaL_error(L,g_error); -- } -- return 1; --} -- --static int lgenders_isnode(lua_State *L) { -- const char *node, *g_error; -- int ret_code, nr_args; -- lgenders_userdata_t *dbh; -- dbh = (lgenders_userdata_t *)luaL_checkudata(L, 1, "LGenders"); -- nr_args = lua_gettop(L); -- if(nr_args == 2) -- node = luaL_checkstring(L,2); -- else -- luaL_error(L,"isnode must be called with one argument"); -- ret_code = genders_isnode(dbh->handle,node); -- if(ret_code == -1) { -- g_error = strdup(genders_errormsg(dbh->handle)); -- luaL_error(L,g_error); -- } -- lua_pushboolean(L,ret_code); -- return 1; --} -- --static int lgenders_isattr(lua_State *L) { -- const char *attr, *g_error; -- int ret_code, nr_args; -- lgenders_userdata_t *dbh; -- dbh = (lgenders_userdata_t *)luaL_checkudata(L, 1, "LGenders"); -- nr_args = lua_gettop(L); -- if(nr_args == 2) -- attr = luaL_checkstring(L,2); -- else -- luaL_error(L,"isattr must be called with one argument"); -- ret_code = genders_isattr(dbh->handle,attr); -- if(ret_code == -1) { -- g_error = strdup(genders_errormsg(dbh->handle)); -- luaL_error(L,g_error); -- } -- lua_pushboolean(L,ret_code); -- return 1; --} -- --static int lgenders_isattrval(lua_State *L) { -- const char *attr, *val, *g_error; -- int ret_code, nr_args; -- lgenders_userdata_t *dbh; -- dbh = (lgenders_userdata_t *)luaL_checkudata(L, 1, "LGenders"); -- nr_args = lua_gettop(L); -- if(nr_args == 3) { -- attr = luaL_checkstring(L,2); -- val = luaL_checkstring(L,3); -- } -- else -- luaL_error(L,"isattrval must be called with two arguments"); -- ret_code = genders_isattrval(dbh->handle,attr,val); -- if(ret_code == -1) { -- g_error = strdup(genders_errormsg(dbh->handle)); -- luaL_error(L,g_error); -- } -- lua_pushboolean(L,ret_code); -- return 1; --} -- --static const struct luaL_Reg genders_methods[] = { -- {"getnumattrs",lgenders_getnumattrs}, -- {"getnumnodes",lgenders_getnumnodes}, -- {"getnodes",lgenders_getnodes}, -- {"getattr",lgenders_getattr}, -- {"query",lgenders_query}, -- {"isnode",lgenders_isnode}, -- {"isattr",lgenders_isattr}, -- {"isattrval",lgenders_isattrval}, -- {"reload",lgenders_reload}, -- {"__gc",lgenders_destroy}, -- {NULL,NULL}, --}; -- --static const struct luaL_Reg genders_functions[] = { -- { "new", lgenders_new }, -- { NULL, NULL} --}; -- -- --int luaopen_genders(lua_State *L) { -- /* Create the metatable and put it on the stack. */ -- luaL_newmetatable(L, "LGenders"); -- /* Duplicate the metatable on the stack (We know have 2). */ -- lua_pushvalue(L, -1); -- /* Pop the first metatable off the stack and assign it to __index -- * of the second one. We set the metatable for the table to itself. -- * This is equivalent to the following in lua: -- * metatable = {} -- * metatable.__index = metatable -- */ -- lua_setfield(L, -2, "__index"); -- -- /* Set the methods to the metatable that should be accessed via object:func */ -- luaL_setfuncs(L, genders_methods, 0); -- -- /* Register the object.func functions into the table that is at the top of the -- * stack. */ -- luaL_newlib(L, genders_functions); -- -- return 1; --} +new file mode 100644 +index 0000000..f2364af +--- /dev/null ++++ b/src/extensions/lua/genderslua.c +@@ -0,0 +1,322 @@ ++/***************************************************************************** ++ * Copyright (C) 2018 SUSE LLC ++ * Written by Christian Goll ++ * ++ * This file is part of Genders, a cluster configuration database. ++ * For details, see . ++ * ++ * Genders is free software; you can redistribute it and/or modify it under ++ * the terms of the GNU General Public License as published by the Free ++ * Software Foundation; either version 2 of the License, or (at your option) ++ * any later version. ++ * ++ * Genders 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. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with Genders. If not, see . ++\*****************************************************************************/ ++#if HAVE_CONFIG_H ++#include "config.h" ++#endif /* HAVE_CONFIG_H */ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++typedef struct { ++ /* genders_t itself is a pointer */ ++ genders_t handle; ++ char *db_name; ++ } lgenders_userdata_t; ++ ++static int lgenders_new(lua_State *L) { ++ lgenders_userdata_t *dbh; ++ const char *db_name, *g_error; ++ /* check for argument vailidy */ ++ db_name = luaL_checkstring(L,1); ++ if (db_name == NULL) ++ luaL_error(L,"database name could not be empty"); ++ /* Create the user data pushing it onto the stack. We also pre-initialize ++ * the member of the userdata in case initialization fails in some way. If ++ * that happens we want the userdata to be in a consistent state for __gc. ++ */ ++ dbh = (lgenders_userdata_t *)lua_newuserdata(L, sizeof(*dbh)); ++ dbh->handle = NULL; ++ dbh->db_name = NULL; ++ /* Add the metatable to the stack. */ ++ luaL_getmetatable(L, "LGenders"); ++ /* Set the metatable on the userdata. */ ++ lua_setmetatable(L, -2); ++ /* Create the handle */ ++ dbh->handle = genders_handle_create(); ++ dbh->db_name = strdup(db_name); ++ if(genders_load_data(dbh->handle,dbh->db_name) != 0) { ++ g_error = strdup(genders_errormsg(dbh->handle)); ++ luaL_error(L,g_error); ++ } ++ return 1; ++} ++static int lgenders_reload(lua_State *L) { ++ lgenders_userdata_t *dbh; ++ const char *db_name, *g_error; ++ dbh = (lgenders_userdata_t *)luaL_checkudata(L, 1, "LGenders"); ++ /* check for argument vailidy */ ++ db_name = luaL_checkstring(L,2); ++ if (db_name == NULL) ++ db_name = strdup(dbh->db_name); ++ if (dbh->handle != NULL) ++ genders_handle_destroy(dbh->handle); ++ dbh->db_name = NULL; ++ /* Create the handle */ ++ dbh->handle = genders_handle_create(); ++ dbh->db_name = strdup(db_name); ++ if(genders_load_data(dbh->handle,dbh->db_name) != 0) { ++ g_error = strdup(genders_errormsg(dbh->handle)); ++ luaL_error(L,g_error); ++ } ++ return 0; ++} ++static int lgenders_destroy(lua_State *L) { ++ lgenders_userdata_t *dbh; ++ dbh = (lgenders_userdata_t *)luaL_checkudata(L, 1, "LGenders"); ++ /* pass return value to lus */ ++ if (dbh->handle != NULL) ++ genders_handle_destroy(dbh->handle); ++ ++ if (dbh->db_name != NULL) ++ free(dbh->db_name); ++ dbh->db_name = NULL; ++ return 0; ++} ++ ++static int lgenders_getnumnodes(lua_State *L) { ++ lgenders_userdata_t *dbh; ++ dbh = (lgenders_userdata_t *)luaL_checkudata(L, 1, "LGenders"); ++ lua_pushinteger(L,genders_getnumnodes(dbh->handle)); ++ return 1; ++} ++ ++static int lgenders_getnumattrs(lua_State *L) { ++ lgenders_userdata_t *dbh; ++ dbh = (lgenders_userdata_t *)luaL_checkudata(L, 1, "LGenders"); ++ lua_pushinteger(L,genders_getnumattrs(dbh->handle)); ++ return 1; ++} ++ ++static int lgenders_getnodes(lua_State *L) { ++ char** nodelist; ++ const char *g_error, *attr, *val; ++ int size, nr_nodes, i, nr_args = 0; ++ lgenders_userdata_t *dbh; ++ dbh = (lgenders_userdata_t *)luaL_checkudata(L, 1, "LGenders"); ++ /* create space for the genders stuff */ ++ size = genders_nodelist_create(dbh->handle,&nodelist); ++ if(size == -1) { ++ g_error = strdup(genders_errormsg(dbh->handle)); ++ luaL_error(L,g_error); ++ } ++ attr = NULL; val = NULL; ++ /* check for attr and val */ ++ nr_args = lua_gettop(L); ++ if(nr_args > 1) ++ attr = luaL_checkstring(L,2); ++ if(nr_args > 2) ++ val = luaL_checkstring(L,3); ++ if(nr_args > 3) ++ luaL_error(L,"getnodes accepts none,one or two arguments"); ++ nr_nodes = genders_getnodes(dbh->handle,nodelist,size,attr,val); ++ lua_newtable(L); ++ for(i = 0; i < nr_nodes; i++) { ++ lua_pushstring(L,nodelist[i]); ++ lua_rawseti(L,-2,i+1); ++ } ++ /* destroy list of nodes */ ++ if(genders_nodelist_destroy(dbh->handle,nodelist) == -1) { ++ g_error = strdup(genders_errormsg(dbh->handle)); ++ luaL_error(L,g_error); ++ } ++ return 1; ++} ++ ++static int lgenders_query(lua_State *L) { ++ char** nodelist; ++ const char *g_error, *query; ++ int size, nr_nodes, i, nr_args = 0; ++ lgenders_userdata_t *dbh; ++ dbh = (lgenders_userdata_t *)luaL_checkudata(L, 1, "LGenders"); ++ /* create space for the genders stuff */ ++ size = genders_nodelist_create(dbh->handle,&nodelist); ++ if(size == -1) { ++ g_error = strdup(genders_errormsg(dbh->handle)); ++ luaL_error(L,g_error); ++ } ++ nr_args = lua_gettop(L); ++ if(nr_args == 2) ++ query = luaL_checkstring(L,2); ++ else ++ luaL_error(L,"query must be called with one argument"); ++ nr_nodes = genders_query(dbh->handle,nodelist,size,query); ++ lua_newtable(L); ++ for(i = 0; i < nr_nodes; i++) { ++ lua_pushstring(L,nodelist[i]); ++ lua_rawseti(L,-2,i+1); ++ } ++ /* destroy list of nodes */ ++ if(genders_nodelist_destroy(dbh->handle,nodelist) == -1) { ++ g_error = strdup(genders_errormsg(dbh->handle)); ++ luaL_error(L,g_error); ++ } ++ return 1; ++} ++static int lgenders_getattr(lua_State *L) { ++ char **attr_list, **val_list; ++ const char *node, *g_error; ++ int ret_code, nr_args, size_attr, i = 0; ++ lgenders_userdata_t *dbh; ++ dbh = (lgenders_userdata_t *)luaL_checkudata(L, 1, "LGenders"); ++ nr_args = lua_gettop(L); ++ if(nr_args == 2) ++ node = luaL_checkstring(L,2); ++ else ++ luaL_error(L,"query must be called with one argument"); ++ /* create space for the lists */ ++ ret_code = genders_attrlist_create(dbh->handle,&attr_list); ++ if(ret_code == -1) { ++ g_error = strdup(genders_errormsg(dbh->handle)); ++ luaL_error(L,g_error); ++ } ++ ret_code = genders_vallist_create(dbh->handle,&val_list); ++ if(ret_code == -1) { ++ g_error = strdup(genders_errormsg(dbh->handle)); ++ luaL_error(L,g_error); ++ } ++ /* hopefully size (which is in ret_code) of attr_list and val_list are the same */ ++ size_attr = genders_getattr(dbh->handle,attr_list,val_list,ret_code,node); ++ if(size_attr == -1) { ++ g_error = strdup(genders_errormsg(dbh->handle)); ++ luaL_error(L,g_error); ++ } ++ lua_newtable(L); ++ for(i = 0; i < size_attr; i++) { ++ lua_pushstring(L, attr_list[i]); ++ lua_pushstring(L, val_list[i]); ++ lua_settable(L, -3); ++ } ++ /* destroy list of nodes */ ++ if(genders_vallist_destroy(dbh->handle,val_list) == -1) { ++ g_error = strdup(genders_errormsg(dbh->handle)); ++ luaL_error(L,g_error); ++ } ++ if(genders_attrlist_destroy(dbh->handle,attr_list) == -1) { ++ g_error = strdup(genders_errormsg(dbh->handle)); ++ luaL_error(L,g_error); ++ } ++ return 1; ++} ++ ++static int lgenders_isnode(lua_State *L) { ++ const char *node, *g_error; ++ int ret_code, nr_args; ++ lgenders_userdata_t *dbh; ++ dbh = (lgenders_userdata_t *)luaL_checkudata(L, 1, "LGenders"); ++ nr_args = lua_gettop(L); ++ if(nr_args == 2) ++ node = luaL_checkstring(L,2); ++ else ++ luaL_error(L,"isnode must be called with one argument"); ++ ret_code = genders_isnode(dbh->handle,node); ++ if(ret_code == -1) { ++ g_error = strdup(genders_errormsg(dbh->handle)); ++ luaL_error(L,g_error); ++ } ++ lua_pushboolean(L,ret_code); ++ return 1; ++} ++ ++static int lgenders_isattr(lua_State *L) { ++ const char *attr, *g_error; ++ int ret_code, nr_args; ++ lgenders_userdata_t *dbh; ++ dbh = (lgenders_userdata_t *)luaL_checkudata(L, 1, "LGenders"); ++ nr_args = lua_gettop(L); ++ if(nr_args == 2) ++ attr = luaL_checkstring(L,2); ++ else ++ luaL_error(L,"isattr must be called with one argument"); ++ ret_code = genders_isattr(dbh->handle,attr); ++ if(ret_code == -1) { ++ g_error = strdup(genders_errormsg(dbh->handle)); ++ luaL_error(L,g_error); ++ } ++ lua_pushboolean(L,ret_code); ++ return 1; ++} ++ ++static int lgenders_isattrval(lua_State *L) { ++ const char *attr, *val, *g_error; ++ int ret_code, nr_args; ++ lgenders_userdata_t *dbh; ++ dbh = (lgenders_userdata_t *)luaL_checkudata(L, 1, "LGenders"); ++ nr_args = lua_gettop(L); ++ if(nr_args == 3) { ++ attr = luaL_checkstring(L,2); ++ val = luaL_checkstring(L,3); ++ } ++ else ++ luaL_error(L,"isattrval must be called with two arguments"); ++ ret_code = genders_isattrval(dbh->handle,attr,val); ++ if(ret_code == -1) { ++ g_error = strdup(genders_errormsg(dbh->handle)); ++ luaL_error(L,g_error); ++ } ++ lua_pushboolean(L,ret_code); ++ return 1; ++} ++ ++static const struct luaL_Reg genders_methods[] = { ++ {"getnumattrs",lgenders_getnumattrs}, ++ {"getnumnodes",lgenders_getnumnodes}, ++ {"getnodes",lgenders_getnodes}, ++ {"getattr",lgenders_getattr}, ++ {"query",lgenders_query}, ++ {"isnode",lgenders_isnode}, ++ {"isattr",lgenders_isattr}, ++ {"isattrval",lgenders_isattrval}, ++ {"reload",lgenders_reload}, ++ {"__gc",lgenders_destroy}, ++ {NULL,NULL}, ++}; ++ ++static const struct luaL_Reg genders_functions[] = { ++ { "new", lgenders_new }, ++ { NULL, NULL} ++}; ++ ++ ++int luaopen_genders(lua_State *L) { ++ /* Create the metatable and put it on the stack. */ ++ luaL_newmetatable(L, "LGenders"); ++ /* Duplicate the metatable on the stack (We know have 2). */ ++ lua_pushvalue(L, -1); ++ /* Pop the first metatable off the stack and assign it to __index ++ * of the second one. We set the metatable for the table to itself. ++ * This is equivalent to the following in lua: ++ * metatable = {} ++ * metatable.__index = metatable ++ */ ++ lua_setfield(L, -2, "__index"); ++ ++ /* Set the methods to the metatable that should be accessed via object:func */ ++ luaL_setfuncs(L, genders_methods, 0); ++ ++ /* Register the object.func functions into the table that is at the top of the ++ * stack. */ ++ luaL_newlib(L, genders_functions); ++ ++ return 1; ++}