From 78b9c6eacb935f7b2cb9d7757cffd6f0d23a47a9 Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Thu, 22 Jun 2023 21:55:00 +0800 Subject: [PATCH 01/20] Revert "Update Makefile" This reverts commit dd14102f14a2bb70ec74230f0aee1da553193693. --- luci-app-openmptcprouter/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/luci-app-openmptcprouter/Makefile b/luci-app-openmptcprouter/Makefile index 9e1c5938d..ae4cb6eea 100755 --- a/luci-app-openmptcprouter/Makefile +++ b/luci-app-openmptcprouter/Makefile @@ -6,7 +6,7 @@ include $(TOPDIR)/rules.mk LUCI_TITLE:=LuCI Support for OpenMPTCProuter -LUCI_DEPENDS:=+luci-lib-json +curl +bind-dig +tracebox +LUCI_DEPENDS:=+luci-lib-json +rdisc6 +curl +bind-dig +tracebox PKG_LICENSE:=GPLv3 #include ../luci/luci.mk From 41abdb1b0f7028b923c19110ac5e39a1a9eaa024 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 24 Jun 2023 06:17:38 +0200 Subject: [PATCH 02/20] Remove rdisc6 dependancy --- luci-app-openmptcprouter/Makefile | 2 +- luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/luci-app-openmptcprouter/Makefile b/luci-app-openmptcprouter/Makefile index ae4cb6eea..9e1c5938d 100644 --- a/luci-app-openmptcprouter/Makefile +++ b/luci-app-openmptcprouter/Makefile @@ -6,7 +6,7 @@ include $(TOPDIR)/rules.mk LUCI_TITLE:=LuCI Support for OpenMPTCProuter -LUCI_DEPENDS:=+luci-lib-json +rdisc6 +curl +bind-dig +tracebox +LUCI_DEPENDS:=+luci-lib-json +curl +bind-dig +tracebox PKG_LICENSE:=GPLv3 #include ../luci/luci.mk diff --git a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm index cd1b585b9..07f8a7835 100644 --- a/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm +++ b/luci-app-openmptcprouter/luasrc/view/openmptcprouter/wizard.htm @@ -948,6 +948,7 @@ +
From 55cf527c17a6f9d3ebbe60b8b5dfb21945595965 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 24 Jun 2023 06:25:01 +0200 Subject: [PATCH 03/20] Update v2ray --- v2ray-core/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/v2ray-core/Makefile b/v2ray-core/Makefile index 08d21ae81..f9254e896 100644 --- a/v2ray-core/Makefile +++ b/v2ray-core/Makefile @@ -5,12 +5,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=v2ray-core -PKG_VERSION:=5.4.1 +PKG_VERSION:=5.7.0 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://codeload.github.com/v2fly/v2ray-core/tar.gz/v$(PKG_VERSION)? -PKG_HASH:=e208bca255c4689a30104e965039d73fa138a7a6e902f820cff94b5b772b042b +PKG_HASH:=599fcd264537e39178b6008a11af68816dfd1609e19a9cf8adc8b2a4240ee370 PKG_LICENSE:=MIT PKG_LICENSE_FILES:=LICENSE From 9c253a282393d11ff3e2040b4b0007a572d7b690 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Sat, 24 Jun 2023 08:12:10 +0200 Subject: [PATCH 04/20] Remove xtables-addons --- xtables-addons/Makefile | 200 - .../001-fix-kernel-version-detection.patch | 11 - .../patches/100-add-rtsp-conntrack.patch | 1742 -- .../patches/200-add-lua-packetscript.patch | 18158 ---------------- .../patches/201-fix-lua-packetscript.patch | 136 - ...-packetscript-kernel-5.16-no-isystem.patch | 284 - .../patches/210-freebsd-build-fix.patch | 11 - 7 files changed, 20542 deletions(-) delete mode 100644 xtables-addons/Makefile delete mode 100644 xtables-addons/patches/001-fix-kernel-version-detection.patch delete mode 100644 xtables-addons/patches/100-add-rtsp-conntrack.patch delete mode 100644 xtables-addons/patches/200-add-lua-packetscript.patch delete mode 100644 xtables-addons/patches/201-fix-lua-packetscript.patch delete mode 100644 xtables-addons/patches/202-fix-lua-packetscript-kernel-5.16-no-isystem.patch delete mode 100644 xtables-addons/patches/210-freebsd-build-fix.patch diff --git a/xtables-addons/Makefile b/xtables-addons/Makefile deleted file mode 100644 index cba09357d..000000000 --- a/xtables-addons/Makefile +++ /dev/null @@ -1,200 +0,0 @@ -# -# Copyright (C) 2009-2013 OpenWrt.org -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# - -include $(TOPDIR)/rules.mk -include $(INCLUDE_DIR)/kernel.mk - -PKG_NAME:=xtables-addons -PKG_VERSION:=3.22 -PKG_RELEASE:=$(AUTORELEASE) -PKG_HASH:=faa16a27166275afbfe8df605f55c3a81ac693bf19da674d45ceded4137ae217 - -PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz -PKG_SOURCE_URL:=https://inai.de/files/xtables-addons/ -PKG_BUILD_DEPENDS:=iptables -PKG_INSTALL:=1 -PKG_BUILD_PARALLEL:=1 - -PKG_MAINTAINER:=Jo-Philipp Wich -PKG_LICENSE:=GPL-2.0 - -PKG_FIXUP:=autoreconf -PKG_ASLR_PIE:=0 - -include $(INCLUDE_DIR)/package.mk - -define Package/xtables-addons - SECTION:=net - CATEGORY:=Network - SUBMENU:=Firewall - TITLE:=Extensions not distributed in the main Xtables - URL:=https://inai.de/projects/xtables-addons/ -endef - -# uses GNU configure - -CONFIGURE_ARGS+= \ - --with-kbuild="$(LINUX_DIR)" \ - --with-xtlibdir="/usr/lib/iptables" - -ifdef CONFIG_EXTERNAL_TOOLCHAIN -MAKE_FLAGS:= \ - $(patsubst ARCH=%,ARCH=$(LINUX_KARCH),$(MAKE_FLAGS)) \ - DEPMOD="/bin/true" - -MAKE_INSTALL_FLAGS:= \ - $(patsubst ARCH=%,ARCH=$(LINUX_KARCH),$(MAKE_FLAGS)) \ - DEPMOD="/bin/true" -else -define Build/Compile - +$(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) \ - $(KERNEL_MAKE_FLAGS) \ - DESTDIR="$(PKG_INSTALL_DIR)" \ - DEPMOD="/bin/true" \ - all -endef - -define Build/Install - $(MAKE) -C $(PKG_BUILD_DIR) \ - $(KERNEL_MAKE_FLAGS) \ - DESTDIR="$(PKG_INSTALL_DIR)" \ - DEPMOD="/bin/true" \ - install -endef -endif - -# 1: extension/module suffix used in package name -# 2: extension/module display name used in package title/description -# 3: list of extensions to package -# 4: list of modules to package -# 5: module load priority -# 6: module depends -define BuildTemplate - - ifneq ($(3),) - define Package/iptables-mod-$(1) - $$(call Package/xtables-addons) - CATEGORY:=Network - TITLE:=$(2) iptables extension - DEPENDS:=iptables $(if $(4),+kmod-ipt-$(1)) - endef - - define Package/iptables-mod-$(1)/install - $(INSTALL_DIR) $$(1)/usr/lib/iptables - for m in $(3); do \ - $(CP) \ - $(PKG_INSTALL_DIR)/usr/lib/iptables/lib$$$$$$$${m}.so \ - $$(1)/usr/lib/iptables/ ; \ - done - endef - - $$(eval $$(call BuildPackage,iptables-mod-$(1))) - endif - - ifneq ($(4),) - define KernelPackage/ipt-$(1) - SUBMENU:=Netfilter Extensions - TITLE:=$(2) netfilter module - DEPENDS:=+kmod-ipt-core $(5) - FILES:=$(foreach mod,$(4),$(PKG_BUILD_DIR)/extensions/$(mod).$(LINUX_KMOD_SUFFIX)) - AUTOLOAD:=$(call AutoProbe,$(notdir $(4))) - endef - - $$(eval $$(call KernelPackage,ipt-$(1))) - endif - -endef - - -define Package/iptaccount - $(call Package/xtables-addons) - CATEGORY:=Network - TITLE:=iptables-mod-account control utility - DEPENDS:=iptables +iptables-mod-account -endef - -define Package/iptaccount/install - $(INSTALL_DIR) $(1)/usr/lib - $(INSTALL_DIR) $(1)/usr/sbin - $(CP) \ - $(PKG_INSTALL_DIR)/usr/lib/libxt_ACCOUNT_cl.so* \ - $(1)/usr/lib/ - $(CP) \ - $(PKG_INSTALL_DIR)/usr/sbin/iptaccount \ - $(1)/usr/sbin/ -endef - - -define Package/iptgeoip - $(call Package/xtables-addons) - CATEGORY:=Network - TITLE:=iptables-mod-geoip support scripts for MaxMind GeoIP databases - DEPENDS:=iptables +iptables-mod-geoip \ - +perl +perlbase-getopt +perlbase-io +perl-text-csv_xs \ - +perl-net-cidr-lite \ - +wget-ssl +!BUSYBOX_CONFIG_ZCAT:gzip -endef - -define Package/iptgeoip/config - menu "Select iptgeoip options" - config IPTGEOIP_PRESERVE - bool "Preserve across sysupgrades" - default n - help - Backup and restore during sysupgrade (requires >7MB) - endmenu -endef - -ifeq ($(CONFIG_IPTGEOIP_PRESERVE),y) -define Package/iptgeoip/conffiles -/usr/share/xt_geoip/ -endef -endif - -define Package/iptgeoip/install - $(INSTALL_DIR) $(1)/usr/lib/xtables-addons - $(CP) \ - $(PKG_INSTALL_DIR)/usr/lib/xtables-addons/xt_geoip_{build,dl} \ - $(1)/usr/lib/xtables-addons/ - $(INSTALL_DIR) $(1)/usr/bin - $(CP) \ - $(PKG_INSTALL_DIR)/usr/bin/xt_geoip_fetch \ - $(1)/usr/bin/ - $(INSTALL_DIR) $(1)/usr/share/xt_geoip - touch $(1)/usr/share/xt_geoip/.keep -endef - - -#$(eval $(call BuildTemplate,SUFFIX,DESCRIPTION,EXTENSION,MODULE,PRIORITY,DEPENDS)) - -$(eval $(call BuildTemplate,compat-xtables,API compatibilty layer,,compat_xtables,+IPV6:kmod-ip6tables)) -$(eval $(call BuildTemplate,nathelper-rtsp,RTSP Conntrack and NAT,,rtsp/nf_conntrack_rtsp rtsp/nf_nat_rtsp,+kmod-ipt-conntrack-extra +kmod-ipt-nat)) - -$(eval $(call BuildTemplate,account,ACCOUNT,xt_ACCOUNT,ACCOUNT/xt_ACCOUNT,+kmod-ipt-compat-xtables)) -$(eval $(call BuildTemplate,chaos,CHAOS,xt_CHAOS,xt_CHAOS,+kmod-ipt-compat-xtables +kmod-ipt-delude +kmod-ipt-tarpit)) -$(eval $(call BuildTemplate,condition,Condition,xt_condition,xt_condition,)) -$(eval $(call BuildTemplate,delude,DELUDE,xt_DELUDE,xt_DELUDE,+kmod-ipt-compat-xtables)) -$(eval $(call BuildTemplate,dhcpmac,DHCPMAC,xt_DHCPMAC,xt_DHCPMAC,+kmod-ipt-compat-xtables)) -$(eval $(call BuildTemplate,dnetmap,DNETMAP,xt_DNETMAP,xt_DNETMAP,+kmod-ipt-compat-xtables +kmod-ipt-nat)) -$(eval $(call BuildTemplate,fuzzy,fuzzy,xt_fuzzy,xt_fuzzy,)) -$(eval $(call BuildTemplate,geoip,geoip,xt_geoip,xt_geoip,)) -$(eval $(call BuildTemplate,iface,iface,xt_iface,xt_iface,)) -$(eval $(call BuildTemplate,ipmark,IPMARK,xt_IPMARK,xt_IPMARK,+kmod-ipt-compat-xtables)) -$(eval $(call BuildTemplate,ipp2p,IPP2P,xt_ipp2p,xt_ipp2p,+kmod-ipt-compat-xtables)) -$(eval $(call BuildTemplate,ipv4options,ipv4options,xt_ipv4options,xt_ipv4options,)) -$(eval $(call BuildTemplate,length2,length2,xt_length2,xt_length2,+kmod-ipt-compat-xtables)) -$(eval $(call BuildTemplate,logmark,LOGMARK,xt_LOGMARK,xt_LOGMARK,+kmod-ipt-compat-xtables)) -$(eval $(call BuildTemplate,lscan,lscan,xt_lscan,xt_lscan,)) -$(eval $(call BuildTemplate,lua,Lua PacketScript,xt_LUA,LUA/xt_LUA,+kmod-ipt-conntrack-extra)) -$(eval $(call BuildTemplate,proto,PROTO,xt_PROTO,xt_PROTO,)) -$(eval $(call BuildTemplate,psd,psd,xt_psd,xt_psd,)) -$(eval $(call BuildTemplate,quota2,quota2,xt_quota2,xt_quota2,)) -$(eval $(call BuildTemplate,sysrq,SYSRQ,xt_SYSRQ,xt_SYSRQ,+kmod-ipt-compat-xtables +kmod-crypto-hash)) -$(eval $(call BuildTemplate,tarpit,TARPIT,xt_TARPIT,xt_TARPIT,+kmod-ipt-compat-xtables)) - -$(eval $(call BuildPackage,iptaccount)) -$(eval $(call BuildPackage,iptgeoip)) diff --git a/xtables-addons/patches/001-fix-kernel-version-detection.patch b/xtables-addons/patches/001-fix-kernel-version-detection.patch deleted file mode 100644 index 775ccf657..000000000 --- a/xtables-addons/patches/001-fix-kernel-version-detection.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/configure.ac -+++ b/configure.ac -@@ -44,7 +44,7 @@ regular_CFLAGS="-Wall -Waggregate-return - - if test -n "$kbuilddir"; then - AC_MSG_CHECKING([kernel version that we will build against]) -- krel="$(make -sC "$kbuilddir" M=$PWD kernelrelease | $AWK -v 'FS=[[^0-9.]]' '{print $1; exit}')" -+ krel="$(make -sC "$kbuilddir" M=$PWD kernelversion | $AWK -v 'FS=[[^0-9.]]' '{print $1; exit}')" - save_IFS="$IFS" - IFS='.' - set x $krel diff --git a/xtables-addons/patches/100-add-rtsp-conntrack.patch b/xtables-addons/patches/100-add-rtsp-conntrack.patch deleted file mode 100644 index dbdc52e94..000000000 --- a/xtables-addons/patches/100-add-rtsp-conntrack.patch +++ /dev/null @@ -1,1742 +0,0 @@ ---- /dev/null -+++ b/extensions/rtsp/Kbuild -@@ -0,0 +1,4 @@ -+# -*- Makefile -*- -+ -+obj-m += nf_nat_rtsp.o -+obj-m += nf_conntrack_rtsp.o ---- /dev/null -+++ b/extensions/rtsp/netfilter_helpers.h -@@ -0,0 +1,144 @@ -+/* -+ * Helpers for netfiler modules. This file provides implementations for basic -+ * functions such as strncasecmp(), etc. -+ * -+ * gcc will warn for defined but unused functions, so we only include the -+ * functions requested. The following macros are used: -+ * NF_NEED_STRNCASECMP nf_strncasecmp() -+ * NF_NEED_STRTOU16 nf_strtou16() -+ * NF_NEED_STRTOU32 nf_strtou32() -+ */ -+#ifndef _NETFILTER_HELPERS_H -+#define _NETFILTER_HELPERS_H -+ -+/* Only include these functions for kernel code. */ -+#ifdef __KERNEL__ -+ -+#include -+ -+#include -+#define iseol(c) ( (c) == '\r' || (c) == '\n' ) -+ -+/* -+ * The standard strncasecmp() -+ */ -+#ifdef NF_NEED_STRNCASECMP -+static int -+nf_strncasecmp(const char* s1, const char* s2, u_int32_t len) -+{ -+ if (s1 == NULL || s2 == NULL) -+ { -+ if (s1 == NULL && s2 == NULL) -+ { -+ return 0; -+ } -+ return (s1 == NULL) ? -1 : 1; -+ } -+ while (len > 0 && tolower(*s1) == tolower(*s2)) -+ { -+ len--; -+ s1++; -+ s2++; -+ } -+ return ( (len == 0) ? 0 : (tolower(*s1) - tolower(*s2)) ); -+} -+#endif /* NF_NEED_STRNCASECMP */ -+ -+/* -+ * Parse a string containing a 16-bit unsigned integer. -+ * Returns the number of chars used, or zero if no number is found. -+ */ -+#ifdef NF_NEED_STRTOU16 -+static int -+nf_strtou16(const char* pbuf, u_int16_t* pval) -+{ -+ int n = 0; -+ -+ *pval = 0; -+ while (isdigit(pbuf[n])) -+ { -+ *pval = (*pval * 10) + (pbuf[n] - '0'); -+ n++; -+ } -+ -+ return n; -+} -+#endif /* NF_NEED_STRTOU16 */ -+ -+/* -+ * Parse a string containing a 32-bit unsigned integer. -+ * Returns the number of chars used, or zero if no number is found. -+ */ -+#ifdef NF_NEED_STRTOU32 -+static int -+nf_strtou32(const char* pbuf, u_int32_t* pval) -+{ -+ int n = 0; -+ -+ *pval = 0; -+ while (pbuf[n] >= '0' && pbuf[n] <= '9') -+ { -+ *pval = (*pval * 10) + (pbuf[n] - '0'); -+ n++; -+ } -+ -+ return n; -+} -+#endif /* NF_NEED_STRTOU32 */ -+ -+/* -+ * Given a buffer and length, advance to the next line and mark the current -+ * line. -+ */ -+#ifdef NF_NEED_NEXTLINE -+static int -+nf_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen) -+{ -+ uint off = *poff; -+ uint physlen = 0; -+ -+ if (off >= len) -+ { -+ return 0; -+ } -+ -+ while (p[off] != '\n') -+ { -+ if (len-off <= 1) -+ { -+ return 0; -+ } -+ -+ physlen++; -+ off++; -+ } -+ -+ /* if we saw a crlf, physlen needs adjusted */ -+ if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r') -+ { -+ physlen--; -+ } -+ -+ /* advance past the newline */ -+ off++; -+ -+ *plineoff = *poff; -+ *plinelen = physlen; -+ *poff = off; -+ -+ return 1; -+} -+#endif /* NF_NEED_NEXTLINE */ -+ -+static inline int rtsp_nf_ct_expect_related(struct nf_conntrack_expect *expect) -+{ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,3,0) -+ return nf_ct_expect_related(expect, 0); -+#else -+ return nf_ct_expect_related(expect); -+#endif -+} -+ -+#endif /* __KERNEL__ */ -+ -+#endif /* _NETFILTER_HELPERS_H */ ---- /dev/null -+++ b/extensions/rtsp/netfilter_mime.h -@@ -0,0 +1,89 @@ -+/* -+ * MIME functions for netfilter modules. This file provides implementations -+ * for basic MIME parsing. MIME headers are used in many protocols, such as -+ * HTTP, RTSP, SIP, etc. -+ * -+ * gcc will warn for defined but unused functions, so we only include the -+ * functions requested. The following macros are used: -+ * NF_NEED_MIME_NEXTLINE nf_mime_nextline() -+ */ -+#ifndef _NETFILTER_MIME_H -+#define _NETFILTER_MIME_H -+ -+/* Only include these functions for kernel code. */ -+#ifdef __KERNEL__ -+ -+#include -+ -+/* -+ * Given a buffer and length, advance to the next line and mark the current -+ * line. If the current line is empty, *plinelen will be set to zero. If -+ * not, it will be set to the actual line length (including CRLF). -+ * -+ * 'line' in this context means logical line (includes LWS continuations). -+ * Returns 1 on success, 0 on failure. -+ */ -+#ifdef NF_NEED_MIME_NEXTLINE -+static int -+nf_mime_nextline(char* p, uint len, uint* poff, uint* plineoff, uint* plinelen) -+{ -+ uint off = *poff; -+ uint physlen = 0; -+ int is_first_line = 1; -+ -+ if (off >= len) -+ { -+ return 0; -+ } -+ -+ do -+ { -+ while (p[off] != '\n') -+ { -+ if (len-off <= 1) -+ { -+ return 0; -+ } -+ -+ physlen++; -+ off++; -+ } -+ -+ /* if we saw a crlf, physlen needs adjusted */ -+ if (physlen > 0 && p[off] == '\n' && p[off-1] == '\r') -+ { -+ physlen--; -+ } -+ -+ /* advance past the newline */ -+ off++; -+ -+ /* check for an empty line */ -+ if (physlen == 0) -+ { -+ break; -+ } -+ -+ /* check for colon on the first physical line */ -+ if (is_first_line) -+ { -+ is_first_line = 0; -+ if (memchr(p+(*poff), ':', physlen) == NULL) -+ { -+ return 0; -+ } -+ } -+ } -+ while (p[off] == ' ' || p[off] == '\t'); -+ -+ *plineoff = *poff; -+ *plinelen = (physlen == 0) ? 0 : (off - *poff); -+ *poff = off; -+ -+ return 1; -+} -+#endif /* NF_NEED_MIME_NEXTLINE */ -+ -+#endif /* __KERNEL__ */ -+ -+#endif /* _NETFILTER_MIME_H */ ---- /dev/null -+++ b/extensions/rtsp/nf_conntrack_rtsp.c -@@ -0,0 +1,756 @@ -+/* -+ * RTSP extension for IP connection tracking -+ * (C) 2003 by Tom Marshall -+ * -+ * 2005-02-13: Harald Welte -+ * - port to 2.6 -+ * - update to recent post-2.6.11 api changes -+ * 2006-09-14: Steven Van Acker -+ * - removed calls to NAT code from conntrack helper: NAT no longer needed to use rtsp-conntrack -+ * 2007-04-18: Michael Guntsche -+ * - Port to new NF API -+ * 2013-03-04: Il'inykh Sergey . Inango Systems Ltd -+ * - fixed rtcp nat mapping and other port mapping fixes -+ * - simple TEARDOWN request handling -+ * - codestyle fixes and other less significant bug fixes -+ * 2018-04-17: Alin Nastac -+ * Hans Dedecker -+ * - use IP address read from SETUP URI in expected connections -+ * 2018-04-18: Hans Dedecker -+ * - update RTP expected connection source IP based on SOURCE -+ * in the SETUP reply message -+ * 2018-08-03: Alin Nastac -+ * Hans Dedecker -+ * - parse non-standard destination=address:port format -+ * -+ * based on ip_conntrack_irc.c -+ * -+ * This program 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. -+ * -+ * Module load syntax: -+ * insmod nf_conntrack_rtsp.o ports=port1,port2,...port -+ * max_outstanding=n setup_timeout=secs -+ * -+ * If no ports are specified, the default will be port 554. -+ * -+ * With max_outstanding you can define the maximum number of not yet -+ * answered SETUP requests per RTSP session (default 8). -+ * With setup_timeout you can specify how long the system waits for -+ * an expected data channel (default 300 seconds). -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include "nf_conntrack_rtsp.h" -+ -+#define NF_NEED_STRNCASECMP -+#define NF_NEED_STRTOU16 -+#define NF_NEED_STRTOU32 -+#define NF_NEED_NEXTLINE -+#include "netfilter_helpers.h" -+#define NF_NEED_MIME_NEXTLINE -+#include "netfilter_mime.h" -+ -+#include -+ -+#define MAX_PORTS 8 -+static int ports[MAX_PORTS]; -+static int num_ports = 0; -+static int max_outstanding = 8; -+static unsigned int setup_timeout = 300; -+ -+MODULE_AUTHOR("Tom Marshall "); -+MODULE_DESCRIPTION("RTSP connection tracking module"); -+MODULE_LICENSE("GPL"); -+module_param_array(ports, int, &num_ports, 0400); -+MODULE_PARM_DESC(ports, "port numbers of RTSP servers"); -+module_param(max_outstanding, int, 0400); -+MODULE_PARM_DESC(max_outstanding, "max number of outstanding SETUP requests per RTSP session"); -+module_param(setup_timeout, uint, 0400); -+MODULE_PARM_DESC(setup_timeout, "timeout on for unestablished data channels"); -+ -+static char *rtsp_buffer; -+static DEFINE_SPINLOCK(rtsp_buffer_lock); -+ -+static struct nf_conntrack_expect_policy rtsp_exp_policy; -+ -+unsigned int (*nf_nat_rtsp_hook)(struct sk_buff *skb, -+ enum ip_conntrack_info ctinfo, -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+ unsigned int protoff, -+#endif -+ unsigned int matchoff, unsigned int matchlen, -+ struct ip_ct_rtsp_expect* prtspexp, -+ struct nf_conntrack_expect *rtp_exp, -+ struct nf_conntrack_expect *rtcp_exp); -+ -+EXPORT_SYMBOL_GPL(nf_nat_rtsp_hook); -+ -+/* -+ * Max mappings we will allow for one RTSP connection (for RTP, the number -+ * of allocated ports is twice this value). Note that SMIL burns a lot of -+ * ports so keep this reasonably high. If this is too low, you will see a -+ * lot of "no free client map entries" messages. -+ */ -+#define MAX_PORT_MAPS 16 -+ -+/*** default port list was here in the masq code: 554, 3030, 4040 ***/ -+ -+#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; } -+ -+/* -+ * Parse an RTSP packet. -+ * -+ * Returns zero if parsing failed. -+ * -+ * Parameters: -+ * IN ptcp tcp data pointer -+ * IN tcplen tcp data len -+ * IN/OUT ptcpoff points to current tcp offset -+ * OUT phdrsoff set to offset of rtsp headers -+ * OUT phdrslen set to length of rtsp headers -+ * OUT pcseqoff set to offset of CSeq header -+ * OUT pcseqlen set to length of CSeq header -+ */ -+static int -+rtsp_parse_message(char* ptcp, uint tcplen, uint* ptcpoff, -+ uint* phdrsoff, uint* phdrslen, -+ uint* pcseqoff, uint* pcseqlen, -+ uint* transoff, uint* translen) -+{ -+ uint entitylen = 0; -+ uint lineoff; -+ uint linelen; -+ -+ if (!nf_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen)) -+ return 0; -+ -+ *phdrsoff = *ptcpoff; -+ while (nf_mime_nextline(ptcp, tcplen, ptcpoff, &lineoff, &linelen)) { -+ if (linelen == 0) { -+ if (entitylen > 0) -+ *ptcpoff += min(entitylen, tcplen - *ptcpoff); -+ break; -+ } -+ if (lineoff+linelen > tcplen) { -+ pr_info("!! overrun !!\n"); -+ break; -+ } -+ -+ if (nf_strncasecmp(ptcp+lineoff, "CSeq:", 5) == 0) { -+ *pcseqoff = lineoff; -+ *pcseqlen = linelen; -+ } -+ -+ if (nf_strncasecmp(ptcp+lineoff, "Transport:", 10) == 0) { -+ *transoff = lineoff; -+ *translen = linelen; -+ } -+ -+ if (nf_strncasecmp(ptcp+lineoff, "Content-Length:", 15) == 0) { -+ uint off = lineoff+15; -+ SKIP_WSPACE(ptcp+lineoff, linelen, off); -+ nf_strtou32(ptcp+off, &entitylen); -+ } -+ } -+ *phdrslen = (*ptcpoff) - (*phdrsoff); -+ -+ return 1; -+} -+ -+/* -+ * Find lo/hi client ports and/or source (if any) in transport header -+ * In: -+ * ptcp, tcplen = packet -+ * tranoff, tranlen = buffer to search -+ * -+ * Out: -+ * pport_lo, pport_hi = lo/hi ports (host endian) -+ * srvaddr -+ * -+ * Returns nonzero if any client ports found -+ * -+ * Note: it is valid (and expected) for the client to request multiple -+ * transports, so we need to parse the entire line. -+ */ -+static int -+rtsp_parse_transport(char* ptran, uint tranlen, -+ struct ip_ct_rtsp_expect* prtspexp) -+{ -+ int rc = 0; -+ uint off = 0; -+ -+ if (tranlen < 10 || !iseol(ptran[tranlen-1]) || -+ nf_strncasecmp(ptran, "Transport:", 10) != 0) { -+ pr_info("sanity check failed\n"); -+ return 0; -+ } -+ -+ pr_debug("tran='%.*s'\n", (int)tranlen, ptran); -+ off += 10; -+ SKIP_WSPACE(ptran, tranlen, off); -+ -+ /* Transport: tran;field;field=val,tran;field;field=val,... */ -+ while (off < tranlen) { -+ const char* pparamend; -+ uint nextparamoff; -+ -+ pparamend = memchr(ptran+off, ',', tranlen-off); -+ pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1; -+ nextparamoff = pparamend-ptran; -+ -+ while (off < nextparamoff) { -+ const char* pfieldend; -+ uint nextfieldoff; -+ -+ pfieldend = memchr(ptran+off, ';', nextparamoff-off); -+ nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1; -+ -+ if (strncmp(ptran+off, "client_port=", 12) == 0) { -+ u_int16_t port; -+ uint numlen; -+ -+ off += 12; -+ numlen = nf_strtou16(ptran+off, &port); -+ off += numlen; -+ if (prtspexp->loport != 0 && prtspexp->loport != port) -+ pr_debug("multiple ports found, port %hu ignored\n", port); -+ else { -+ pr_debug("lo port found : %hu\n", port); -+ prtspexp->loport = prtspexp->hiport = port; -+ if (ptran[off] == '-') { -+ off++; -+ numlen = nf_strtou16(ptran+off, &port); -+ off += numlen; -+ prtspexp->pbtype = pb_range; -+ prtspexp->hiport = port; -+ -+ // If we have a range, assume rtp: -+ // loport must be even, hiport must be loport+1 -+ if ((prtspexp->loport & 0x0001) != 0 || -+ prtspexp->hiport != prtspexp->loport+1) { -+ pr_debug("incorrect range: %hu-%hu, correcting\n", -+ prtspexp->loport, prtspexp->hiport); -+ prtspexp->loport &= 0xfffe; -+ prtspexp->hiport = prtspexp->loport+1; -+ } -+ } else if (ptran[off] == '/') { -+ off++; -+ numlen = nf_strtou16(ptran+off, &port); -+ off += numlen; -+ prtspexp->pbtype = pb_discon; -+ prtspexp->hiport = port; -+ } -+ rc = 1; -+ } -+ } else if (strncmp(ptran+off, "source=", 7) == 0) { -+ uint srcaddrlen; -+ -+ off += 7; -+ srcaddrlen = nextfieldoff - off - 1; -+ -+ if (in4_pton(ptran + off, srcaddrlen, -+ (u8 *)&prtspexp->srvaddr.in, -+ -1, NULL)) -+ pr_debug("source found : %pI4\n", -+ &prtspexp->srvaddr.ip); -+ } else if (nextfieldoff - off > 12 && strncmp(ptran+off, "destination=", 12) == 0) { -+ const char *psep; -+ u_int16_t port; -+ -+ off += 12; -+ -+ if (in4_pton(ptran+off, nextfieldoff - off - 1, (u8 *)&prtspexp->cltaddr.in, -1, NULL)) { -+ pr_debug("destination found : %pI4\n", &prtspexp->cltaddr.ip); -+ -+ /* -+ * Some RTSP clients(mostly STBs) use non-standard destination parameters: -+ * destination=address:port -+ */ -+ psep = memchr(ptran+off, ':', nextfieldoff-off); -+ if (psep != NULL && nf_strtou16(psep + 1, &port)) { -+ if (prtspexp->loport != 0 && prtspexp->loport != port) -+ pr_debug("multiple ports found, port %hu ignored\n", port); -+ else { -+ pr_debug("lo port found : %hu\n", port); -+ prtspexp->loport = prtspexp->hiport = port; -+ } -+ } -+ } -+ } -+ -+ /* -+ * Note we don't look for the destination parameter here. -+ * If we are using NAT, the NAT module will handle it. If not, -+ * and the client is sending packets elsewhere, the expectation -+ * will quietly time out. -+ */ -+ -+ off = nextfieldoff; -+ } -+ -+ off = nextparamoff; -+ } -+ -+ return rc; -+} -+ -+ -+/*** conntrack functions ***/ -+ -+/* outbound packet: client->server */ -+ -+static inline int -+help_out(struct sk_buff *skb, unsigned char *rb_ptr, unsigned int datalen, -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+ struct nf_conn *ct, enum ip_conntrack_info ctinfo, -+ unsigned int protoff) -+#else -+ struct nf_conn *ct, enum ip_conntrack_info ctinfo) -+#endif -+{ -+ struct ip_ct_rtsp_expect expinfo; -+ -+ int dir = CTINFO2DIR(ctinfo); /* = IP_CT_DIR_ORIGINAL */ -+ //struct tcphdr* tcph = (void*)iph + iph->ihl * 4; -+ //uint tcplen = pktlen - iph->ihl * 4; -+ char* pdata = rb_ptr; -+ //uint datalen = tcplen - tcph->doff * 4; -+ uint dataoff = 0; -+ int ret = NF_ACCEPT; -+ -+ struct nf_conntrack_expect *rtp_exp; -+ struct nf_conntrack_expect *rtcp_exp = NULL; -+ -+ __be16 be_loport; -+ __be16 be_hiport; -+ -+ typeof(nf_nat_rtsp_hook) nf_nat_rtsp; -+ -+ memset(&expinfo, 0, sizeof(expinfo)); -+ -+ while (dataoff < datalen) { -+ uint cmdoff = dataoff; -+ uint hdrsoff = 0; -+ uint hdrslen = 0; -+ uint cseqoff = 0; -+ uint cseqlen = 0; -+ uint transoff = 0; -+ uint translen = 0; -+ uint off; -+ union nf_inet_addr srvaddr; -+ -+ if (!rtsp_parse_message(pdata, datalen, &dataoff, -+ &hdrsoff, &hdrslen, -+ &cseqoff, &cseqlen, -+ &transoff, &translen)) -+ break; /* not a valid message */ -+ -+ if (strncmp(pdata+cmdoff, "TEARDOWN ", 9) == 0) { -+ pr_debug("teardown handled\n"); -+ nf_ct_remove_expectations(ct); /* FIXME must be session id aware */ -+ break; -+ } -+ -+ if (strncmp(pdata+cmdoff, "SETUP ", 6) != 0) -+ continue; /* not a SETUP message */ -+ -+ srvaddr = ct->tuplehash[!dir].tuple.src.u3; -+ -+ /* try to get RTP media source from SETUP URI */ -+ off = cmdoff + 6; -+ while (off < datalen) { -+ if (strncmp(pdata+off, "://", 3) == 0) { -+ off += 3; -+ cmdoff = off; -+ -+ while (off < datalen) { -+ if (pdata[off] == ':' || -+ pdata[off] == '/' || -+ pdata[off] == ' ') { -+ in4_pton(pdata + cmdoff, -+ off - cmdoff, -+ (u8 *)&srvaddr.in, -+ -1, NULL); -+ break; -+ } -+ off++; -+ } -+ break; -+ } -+ off++; -+ } -+ -+ pr_debug("found a setup message\n"); -+ -+ off = 0; -+ if(translen) -+ rtsp_parse_transport(pdata+transoff, translen, &expinfo); -+ -+ if (expinfo.loport == 0) { -+ pr_debug("no udp transports found\n"); -+ continue; /* no udp transports found */ -+ } -+ -+ pr_debug("udp transport found, ports=(%d,%hu,%hu)\n", -+ (int)expinfo.pbtype, expinfo.loport, expinfo.hiport); -+ -+ -+ be_loport = htons(expinfo.loport); -+ -+ rtp_exp = nf_ct_expect_alloc(ct); -+ if (rtp_exp == NULL) { -+ ret = NF_DROP; -+ goto out; -+ } -+ -+ nf_ct_expect_init(rtp_exp, NF_CT_EXPECT_CLASS_DEFAULT, -+ nf_ct_l3num(ct), NULL, -+ &ct->tuplehash[!dir].tuple.dst.u3, -+ IPPROTO_UDP, NULL, &be_loport); -+ -+ rtp_exp->flags = 0; -+ -+ if (expinfo.pbtype == pb_range || expinfo.pbtype == pb_discon) { -+ pr_debug("setup expectation for rtcp\n"); -+ -+ be_hiport = htons(expinfo.hiport); -+ rtcp_exp = nf_ct_expect_alloc(ct); -+ if (rtcp_exp == NULL) { -+ ret = NF_DROP; -+ goto out1; -+ } -+ -+ nf_ct_expect_init(rtcp_exp, NF_CT_EXPECT_CLASS_DEFAULT, -+ nf_ct_l3num(ct), NULL, -+ &ct->tuplehash[!dir].tuple.dst.u3, -+ IPPROTO_UDP, NULL, &be_hiport); -+ -+ rtcp_exp->flags = 0; -+ -+ pr_debug("expect_related %pI4:%u-%u-%pI4:%u-%u\n", -+ &rtp_exp->tuple.src.u3.ip, -+ ntohs(rtp_exp->tuple.src.u.udp.port), -+ ntohs(rtcp_exp->tuple.src.u.udp.port), -+ &rtp_exp->tuple.dst.u3.ip, -+ ntohs(rtp_exp->tuple.dst.u.udp.port), -+ ntohs(rtcp_exp->tuple.dst.u.udp.port)); -+ } else { -+ pr_debug("expect_related %pI4:%u-%pI4:%u\n", -+ &rtp_exp->tuple.src.u3.ip, -+ ntohs(rtp_exp->tuple.src.u.udp.port), -+ &rtp_exp->tuple.dst.u3.ip, -+ ntohs(rtp_exp->tuple.dst.u.udp.port)); -+ } -+ -+ nf_nat_rtsp = rcu_dereference(nf_nat_rtsp_hook); -+ if (nf_nat_rtsp && ct->status & IPS_NAT_MASK) -+ /* pass the request off to the nat helper */ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+ ret = nf_nat_rtsp(skb, ctinfo, protoff, hdrsoff, hdrslen, -+ &expinfo, rtp_exp, rtcp_exp); -+#else -+ ret = nf_nat_rtsp(skb, ctinfo, hdrsoff, hdrslen, -+ &expinfo, rtp_exp, rtcp_exp); -+#endif -+ else { -+ if (rtsp_nf_ct_expect_related(rtp_exp) == 0) { -+ if (rtcp_exp && rtsp_nf_ct_expect_related(rtcp_exp) != 0) { -+ nf_ct_unexpect_related(rtp_exp); -+ pr_info("nf_conntrack_expect_related failed for rtcp\n"); -+ ret = NF_DROP; -+ } -+ } else { -+ pr_info("nf_conntrack_expect_related failed for rtp\n"); -+ ret = NF_DROP; -+ } -+ } -+ if (rtcp_exp) { -+ nf_ct_expect_put(rtcp_exp); -+ } -+out1: -+ nf_ct_expect_put(rtp_exp); -+ goto out; -+ } -+out: -+ -+ return ret; -+} -+ -+ -+static inline int -+help_in(struct sk_buff *skb, unsigned char *rb_ptr, unsigned int datalen, -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+ struct nf_conn *ct, enum ip_conntrack_info ctinfo, -+ unsigned int protoff) -+#else -+ struct nf_conn *ct, enum ip_conntrack_info ctinfo) -+#endif -+ { -+ struct ip_ct_rtsp_expect expinfo; -+ union nf_inet_addr srvaddr; -+ int dir = CTINFO2DIR(ctinfo); /* = IP_CT_DIR_ORIGINAL */ -+ int len; -+ char* pdata = rb_ptr; -+ uint dataoff = 0; -+ int ret = NF_ACCEPT; -+ u_int8_t family; -+ struct nf_conntrack_expect *exp_ct = NULL; -+ struct nf_conntrack_tuple t; -+ struct net *net = nf_ct_net(ct); -+ -+ memset(&expinfo, 0, sizeof(expinfo)); -+ -+ while (dataoff < datalen) { -+ uint cmdoff = dataoff; -+ uint hdrsoff = 0; -+ uint hdrslen = 0; -+ uint cseqoff = 0; -+ uint cseqlen = 0; -+ uint transoff = 0; -+ uint translen = 0; -+ -+ if (!rtsp_parse_message(pdata, datalen, &dataoff, -+ &hdrsoff, &hdrslen, -+ &cseqoff, &cseqlen, -+ &transoff, &translen)) -+ break; /* not a valid message */ -+ -+ if (strncmp(pdata+cmdoff, "RTSP/", 5) == 0 && translen) { -+ union nf_inet_addr zeroaddr; -+ -+ memset(&zeroaddr, 0, sizeof(zeroaddr)); -+ -+ if (!rtsp_parse_transport(pdata+transoff, translen, &expinfo)) -+ continue; -+ -+ srvaddr = expinfo.srvaddr; -+ -+ if (nf_inet_addr_cmp(&srvaddr, &ct->tuplehash[dir].tuple.src.u3) || -+ nf_inet_addr_cmp(&srvaddr, &zeroaddr)) -+ continue; -+ } else -+ continue; /* not valid RTSP reply */ -+ -+ if (expinfo.loport == 0) { -+ pr_debug("no udp transports found\n"); -+ continue; /* no udp transports found */ -+ } -+ -+ family = nf_ct_l3num(ct); -+ if (family == AF_INET) -+ len = 4; -+ else -+ len = 16; -+ -+ /* replace rtp expect src addr */ -+ t.src.l3num = family; -+ t.dst.protonum = IPPROTO_UDP; -+ -+ memcpy(&t.src.u3, &ct->tuplehash[dir].tuple.src.u3, len); -+ if (sizeof(t.src.u3) > len) -+ /* address needs to be cleared for nf_ct_tuple_equal */ -+ memset((void *)&t.src.u3 + len, 0, sizeof(t.src.u3) - len); -+ -+ t.src.u.all = 0; -+ -+ memcpy(&t.dst.u3, &ct->tuplehash[dir].tuple.dst.u3, len); -+ if (sizeof(t.dst.u3) > len) -+ /* address needs to be cleared for nf_ct_tuple_equal */ -+ memset((void *)&t.dst.u3 + len, 0, sizeof(t.dst.u3) - len); -+ -+ t.dst.u.all = htons(expinfo.loport); -+ -+ /* get the rtp expect and replace the srcaddr with RTP server addr */ -+ exp_ct = nf_ct_expect_find_get(net, nf_ct_zone(ct), &t); -+ if (exp_ct) { -+ memcpy(&exp_ct->tuple.src.u3, &srvaddr, len); -+ if (sizeof(exp_ct->tuple.src.u3) > len) -+ /* address needs to be cleared for nf_ct_tuple_equal */ -+ memset((void *)&exp_ct->tuple.src.u3 + len, 0, -+ sizeof(exp_ct->tuple.src.u3) - len); -+ } else -+ goto out; -+ -+ /* replace rtcp expect src addr */ -+ if (expinfo.pbtype == pb_range || expinfo.pbtype == pb_discon) { -+ t.dst.u.all = htons(expinfo.hiport); -+ -+ /* get the rtcp expect and replace the srcaddr with RTP server addr */ -+ exp_ct = nf_ct_expect_find_get(net, nf_ct_zone(ct), &t); -+ if (exp_ct) { -+ memcpy(&exp_ct->tuple.src.u3, &srvaddr, len); -+ if (sizeof(exp_ct->tuple.src.u3) > len) -+ /* address needs to be cleared for nf_ct_tuple_equal */ -+ memset((void *)&exp_ct->tuple.src.u3 + len, 0, -+ sizeof(exp_ct->tuple.src.u3) - len); -+ } else -+ goto out; -+ } -+ -+ goto out; -+ } -+out: -+ return ret; -+ } -+ -+static int help(struct sk_buff *skb, unsigned int protoff, -+ struct nf_conn *ct, enum ip_conntrack_info ctinfo) -+{ -+ struct tcphdr _tcph, *th; -+ unsigned int dataoff, datalen; -+ char *rb_ptr; -+ int ret = NF_DROP; -+ -+ /* Until there's been traffic both ways, don't look in packets. */ -+ if (ctinfo != IP_CT_ESTABLISHED && -+ ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) { -+ pr_debug("conntrackinfo = %u\n", ctinfo); -+ return NF_ACCEPT; -+ } -+ -+ /* Not whole TCP header? */ -+ th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph); -+ -+ if (!th) -+ return NF_ACCEPT; -+ -+ /* No data ? */ -+ dataoff = protoff + th->doff*4; -+ datalen = skb->len - dataoff; -+ if (dataoff >= skb->len) -+ return NF_ACCEPT; -+ -+ spin_lock_bh(&rtsp_buffer_lock); -+ rb_ptr = skb_header_pointer(skb, dataoff, -+ skb->len - dataoff, rtsp_buffer); -+ BUG_ON(rb_ptr == NULL); -+ -+#if 0 -+ /* Checksum invalid? Ignore. */ -+ /* FIXME: Source route IP option packets --RR */ -+ if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr, -+ csum_partial((char*)tcph, tcplen, 0))) -+ { -+ DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n", -+ tcph, tcplen, NIPQUAD(iph->saddr), NIPQUAD(iph->daddr)); -+ return NF_ACCEPT; -+ } -+#endif -+ -+ switch (CTINFO2DIR(ctinfo)) { -+ case IP_CT_DIR_ORIGINAL: -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+ ret = help_out(skb, rb_ptr, datalen, ct, ctinfo, protoff); -+#else -+ ret = help_out(skb, rb_ptr, datalen, ct, ctinfo); -+#endif -+ break; -+ case IP_CT_DIR_REPLY: -+ pr_debug("IP_CT_DIR_REPLY\n"); -+ /* inbound packet: server->client */ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+ ret = help_in(skb, rb_ptr, datalen, ct, ctinfo, protoff); -+#else -+ ret = help_in(skb, rb_ptr, datalen, ct, ctinfo); -+#endif -+ break; -+ default: -+ break; -+ } -+ -+ spin_unlock_bh(&rtsp_buffer_lock); -+ -+ return ret; -+} -+ -+static struct nf_conntrack_helper rtsp_helpers[MAX_PORTS]; -+static char rtsp_names[MAX_PORTS][10]; -+ -+/* This function is intentionally _NOT_ defined as __exit */ -+static void -+fini(void) -+{ -+ int i; -+ for (i = 0; i < num_ports; i++) { -+ pr_debug("unregistering port %d\n", ports[i]); -+ nf_conntrack_helper_unregister(&rtsp_helpers[i]); -+ } -+ kfree(rtsp_buffer); -+} -+ -+static int __init -+init(void) -+{ -+ int i, ret; -+ struct nf_conntrack_helper *hlpr; -+ char *tmpname; -+ -+ printk("nf_conntrack_rtsp v" IP_NF_RTSP_VERSION " loading\n"); -+ -+ if (max_outstanding < 1) { -+ printk("nf_conntrack_rtsp: max_outstanding must be a positive integer\n"); -+ return -EBUSY; -+ } -+ -+ rtsp_exp_policy.max_expected = max_outstanding; -+ rtsp_exp_policy.timeout = setup_timeout; -+ -+ rtsp_buffer = kmalloc(65536, GFP_KERNEL); -+ if (!rtsp_buffer) -+ return -ENOMEM; -+ -+ /* If no port given, default to standard rtsp port */ -+ if (ports[0] == 0) { -+ ports[0] = RTSP_PORT; -+ num_ports = 1; -+ } -+ -+ for (i = 0; (i < MAX_PORTS) && ports[i]; i++) { -+ hlpr = &rtsp_helpers[i]; -+ memset(hlpr, 0, sizeof(struct nf_conntrack_helper)); -+ hlpr->tuple.src.l3num = AF_INET; -+ hlpr->tuple.src.u.tcp.port = htons(ports[i]); -+ hlpr->tuple.dst.protonum = IPPROTO_TCP; -+ hlpr->expect_policy = &rtsp_exp_policy; -+ hlpr->me = THIS_MODULE; -+ hlpr->help = help; -+ -+ tmpname = &rtsp_names[i][0]; -+ if (ports[i] == RTSP_PORT) { -+ sprintf(tmpname, "rtsp"); -+ } else { -+ sprintf(tmpname, "rtsp-%d", i); -+ } -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) -+ strlcpy(hlpr->name, tmpname, sizeof(hlpr->name)); -+#else -+ hlpr->name = tmpname; -+#endif -+ pr_debug("port #%d: %d\n", i, ports[i]); -+ -+ ret = nf_conntrack_helper_register(hlpr); -+ -+ if (ret) { -+ printk("nf_conntrack_rtsp: ERROR registering port %d\n", ports[i]); -+ fini(); -+ return -EBUSY; -+ } -+ } -+ return 0; -+} -+ -+module_init(init); -+module_exit(fini); ---- /dev/null -+++ b/extensions/rtsp/nf_conntrack_rtsp.h -@@ -0,0 +1,74 @@ -+/* -+ * RTSP extension for IP connection tracking. -+ * (C) 2003 by Tom Marshall -+ * based on ip_conntrack_irc.h -+ * -+ * This program 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. -+ * -+ * 2013-03-04: Il'inykh Sergey . Inango Systems Ltd -+ * - conditional compilation for kernel 3.7 -+ * - port mapping improvements -+*/ -+#ifndef _IP_CONNTRACK_RTSP_H -+#define _IP_CONNTRACK_RTSP_H -+ -+#include -+ -+//#define IP_NF_RTSP_DEBUG 1 -+#define IP_NF_RTSP_VERSION "0.7" -+ -+#ifdef __KERNEL__ -+/* port block types */ -+typedef enum { -+ pb_single, /* client_port=x */ -+ pb_range, /* client_port=x-y */ -+ pb_discon /* client_port=x/y (rtspbis) */ -+} portblock_t; -+ -+/* We record seq number and length of rtsp headers here, all in host order. */ -+ -+/* -+ * This structure is per expected connection. It is a member of struct -+ * ip_conntrack_expect. The TCP SEQ for the conntrack expect is stored -+ * there and we are expected to only store the length of the data which -+ * needs replaced. If a packet contains multiple RTSP messages, we create -+ * one expected connection per message. -+ * -+ * We use these variables to mark the entire header block. This may seem -+ * like overkill, but the nature of RTSP requires it. A header may appear -+ * multiple times in a message. We must treat two Transport headers the -+ * same as one Transport header with two entries. -+ */ -+struct ip_ct_rtsp_expect -+{ -+ u_int32_t len; /* length of header block */ -+ portblock_t pbtype; /* Type of port block that was requested */ -+ u_int16_t loport; /* Port that was requested, low or first */ -+ u_int16_t hiport; /* Port that was requested, high or second */ -+ union nf_inet_addr srvaddr; /* src address in SETUP reply */ -+ union nf_inet_addr cltaddr; /* destination address */ -+#if 0 -+ uint method; /* RTSP method */ -+ uint cseq; /* CSeq from request */ -+#endif -+}; -+ -+extern unsigned int (*nf_nat_rtsp_hook)(struct sk_buff *skb, -+ enum ip_conntrack_info ctinfo, -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+ unsigned int protoff, -+#endif -+ unsigned int matchoff, -+ unsigned int matchlen, -+ struct ip_ct_rtsp_expect *prtspexp, -+ struct nf_conntrack_expect *rtp_exp, -+ struct nf_conntrack_expect *rtcp_exp); -+ -+#define RTSP_PORT 554 -+ -+#endif /* __KERNEL__ */ -+ -+#endif /* _IP_CONNTRACK_RTSP_H */ ---- /dev/null -+++ b/extensions/rtsp/nf_nat_rtsp.c -@@ -0,0 +1,640 @@ -+/* -+ * RTSP extension for TCP NAT alteration -+ * (C) 2003 by Tom Marshall -+ * -+ * 2013-03-04: Il'inykh Sergey . Inango Systems Ltd -+ * - fixed rtcp nat mapping and other port mapping fixes -+ * - fixed system hard lock because of bug in the parser -+ * - codestyle fixes and less significant fixes -+ * -+ * based on ip_nat_irc.c -+ * -+ * This program 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. -+ * -+ * Module load syntax: -+ * insmod nf_nat_rtsp.o ports=port1,port2,...port -+ * stunaddr=
-+ * destaction=[auto|strip|none] -+ * -+ * If no ports are specified, the default will be port 554 only. -+ * -+ * stunaddr specifies the address used to detect that a client is using STUN. -+ * If this address is seen in the destination parameter, it is assumed that -+ * the client has already punched a UDP hole in the firewall, so we don't -+ * mangle the client_port. If none is specified, it is autodetected. It -+ * only needs to be set if you have multiple levels of NAT. It should be -+ * set to the external address that the STUN clients detect. Note that in -+ * this case, it will not be possible for clients to use UDP with servers -+ * between the NATs. -+ * -+ * If no destaction is specified, auto is used. -+ * destaction=auto: strip destination parameter if it is not stunaddr. -+ * destaction=strip: always strip destination parameter (not recommended). -+ * destaction=none: do not touch destination parameter (not recommended). -+ */ -+ -+#include -+#include -+#include -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+# include -+#else -+# include -+#endif -+#include -+#include "nf_conntrack_rtsp.h" -+ -+#include -+#include -+#define NF_NEED_STRNCASECMP -+#define NF_NEED_STRTOU16 -+#include "netfilter_helpers.h" -+#define NF_NEED_MIME_NEXTLINE -+#include "netfilter_mime.h" -+ -+#define MAX_PORTS 8 -+#define DSTACT_AUTO 0 -+#define DSTACT_STRIP 1 -+#define DSTACT_NONE 2 -+ -+static char* stunaddr = NULL; -+static char* destaction = NULL; -+ -+static u_int32_t extip = 0; -+static int dstact = 0; -+ -+static void nf_nat_rtsp_expected(struct nf_conn* ct, struct nf_conntrack_expect *exp); -+ -+MODULE_AUTHOR("Tom Marshall "); -+MODULE_DESCRIPTION("RTSP network address translation module"); -+MODULE_LICENSE("GPL"); -+module_param(stunaddr, charp, 0644); -+MODULE_PARM_DESC(stunaddr, "Address for detecting STUN"); -+module_param(destaction, charp, 0644); -+MODULE_PARM_DESC(destaction, "Action for destination parameter (auto/strip/none)"); -+ -+#define SKIP_WSPACE(ptr,len,off) while(off < len && isspace(*(ptr+off))) { off++; } -+ -+/*** helper functions ***/ -+ -+static void -+get_skb_tcpdata(struct sk_buff* skb, char** pptcpdata, uint* ptcpdatalen) -+{ -+ struct iphdr* iph = ip_hdr(skb); -+ struct tcphdr* tcph = (void *)iph + ip_hdrlen(skb); -+ -+ *pptcpdata = (char*)tcph + tcph->doff*4; -+ *ptcpdatalen = ((char*)skb_transport_header(skb) + skb->len) - *pptcpdata; -+} -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+/* copy of sip_sprintf_addr */ -+static int rtsp_sprintf_addr(const struct nf_conn *ct, char *buffer, -+ const union nf_inet_addr *addr, bool delim) -+{ -+ if (nf_ct_l3num(ct) == NFPROTO_IPV4) { -+ return sprintf(buffer, "%pI4", &addr->ip); -+ } else { -+ if (delim) -+ return sprintf(buffer, "[%pI6c]", &addr->ip6); -+ else -+ return sprintf(buffer, "%pI6c", &addr->ip6); -+ } -+} -+#endif -+ -+/*** nat functions ***/ -+ -+/* -+ * Mangle the "Transport:" header: -+ * - Replace all occurences of "client_port=" -+ * - Handle destination parameter -+ * -+ * In: -+ * ct, ctinfo = conntrack context -+ * skb = packet -+ * tranoff = Transport header offset from TCP data -+ * tranlen = Transport header length (incl. CRLF) -+ * rport_lo = replacement low port (host endian) -+ * rport_hi = replacement high port (host endian) -+ * -+ * Returns packet size difference. -+ * -+ * Assumes that a complete transport header is present, ending with CR or LF -+ */ -+static int -+rtsp_mangle_tran(enum ip_conntrack_info ctinfo, -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+ unsigned int protoff, -+#endif -+ struct nf_conntrack_expect* rtp_exp, -+ struct nf_conntrack_expect* rtcp_exp, -+ struct ip_ct_rtsp_expect* prtspexp, -+ struct sk_buff* skb, uint tranoff, uint tranlen) -+{ -+ char* ptcp; -+ uint tcplen; -+ char* ptran; -+ char rbuf1[16]; /* Replacement buffer (one port) */ -+ uint rbuf1len; /* Replacement len (one port) */ -+ char rbufa[16]; /* Replacement buffer (all ports) */ -+ uint rbufalen; /* Replacement len (all ports) */ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+ union nf_inet_addr newip; -+#else -+ u_int32_t newip; -+#endif -+ u_int16_t loport, hiport; -+ uint off = 0; -+ uint diff; /* Number of bytes we removed */ -+ -+ struct nf_conn *ct = rtp_exp->master; -+ /* struct nf_conn *ct = nf_ct_get(skb, &ctinfo); */ -+ struct nf_conntrack_tuple *rtp_t; -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+ char szextaddr[INET6_ADDRSTRLEN + 16]; -+#else -+ char szextaddr[INET_ADDRSTRLEN + 16]; -+#endif -+ uint extaddrlen; -+ int is_stun; -+ -+ get_skb_tcpdata(skb, &ptcp, &tcplen); -+ ptran = ptcp+tranoff; -+ -+ if (tranoff+tranlen > tcplen || tcplen-tranoff < tranlen || -+ tranlen < 10 || !iseol(ptran[tranlen-1]) || -+ nf_strncasecmp(ptran, "Transport:", 10) != 0) { -+ pr_info("sanity check failed\n"); -+ return 0; -+ } -+ off += 10; -+ SKIP_WSPACE(ptcp+tranoff, tranlen, off); -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+ newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3; -+ rtp_t = &rtp_exp->tuple; -+ rtp_t->dst.u3 = newip; -+ if (rtcp_exp) { -+ rtcp_exp->tuple.dst.u3 = newip; -+ } -+ extaddrlen = rtsp_sprintf_addr(ct, szextaddr, &newip, true); // FIXME handle extip -+ pr_debug("stunaddr=%s (auto)\n", szextaddr); -+#else -+ newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip; -+ rtp_t = &rtp_exp->tuple; -+ rtp_t->dst.u3.ip = newip; -+ if (rtcp_exp) { -+ rtcp_exp->tuple.dst.u3.ip = newip; -+ } -+ extaddrlen = extip ? sprintf(szextaddr, "%pI4", &extip) -+ : sprintf(szextaddr, "%pI4", &newip); -+ pr_debug("stunaddr=%s (%s)\n", szextaddr, (extip?"forced":"auto")); -+#endif -+ hiport = 0; -+ rbuf1len = rbufalen = 0; -+ switch (prtspexp->pbtype) { -+ case pb_single: -+ for (loport = prtspexp->loport; loport != 0; loport++) { /* XXX: improper wrap? */ -+ rtp_t->dst.u.udp.port = htons(loport); -+ if (rtsp_nf_ct_expect_related(rtp_exp) == 0) { -+ pr_debug("using port %hu\n", loport); -+ break; -+ } -+ } -+ if (loport != 0) { -+ rbuf1len = sprintf(rbuf1, "%hu", loport); -+ rbufalen = sprintf(rbufa, "%hu", loport); -+ } -+ break; -+ case pb_range: -+ for (loport = prtspexp->loport; loport != 0; loport += 2) { /* XXX: improper wrap? */ -+ rtp_t->dst.u.udp.port = htons(loport); -+ if (rtsp_nf_ct_expect_related(rtp_exp) != 0) { -+ continue; -+ } -+ hiport = loport + 1; -+ rtcp_exp->tuple.dst.u.udp.port = htons(hiport); -+ if (rtsp_nf_ct_expect_related(rtcp_exp) != 0) { -+ nf_ct_unexpect_related(rtp_exp); -+ continue; -+ } -+ -+ /* FIXME: invalid print in case of ipv6 */ -+ pr_debug("nat expect_related %pI4:%u-%u-%pI4:%u-%u\n", -+ &rtp_exp->tuple.src.u3.ip, -+ ntohs(rtp_exp->tuple.src.u.udp.port), -+ ntohs(rtcp_exp->tuple.src.u.udp.port), -+ &rtp_exp->tuple.dst.u3.ip, -+ ntohs(rtp_exp->tuple.dst.u.udp.port), -+ ntohs(rtcp_exp->tuple.dst.u.udp.port)); -+ break; -+ } -+ if (loport != 0) { -+ rbuf1len = sprintf(rbuf1, "%hu", loport); -+ rbufalen = sprintf(rbufa, "%hu-%hu", loport, hiport); -+ } -+ break; -+ case pb_discon: -+ for (loport = prtspexp->loport; loport != 0; loport++) { /* XXX: improper wrap? */ -+ rtp_t->dst.u.udp.port = htons(loport); -+ if (rtsp_nf_ct_expect_related(rtp_exp) == 0) { -+ pr_debug("using port %hu (1 of 2)\n", loport); -+ break; -+ } -+ } -+ for (hiport = prtspexp->hiport; hiport != 0; hiport++) { /* XXX: improper wrap? */ -+ rtcp_exp->tuple.dst.u.udp.port = htons(hiport); -+ if (rtsp_nf_ct_expect_related(rtcp_exp) == 0) { -+ pr_debug("using port %hu (2 of 2)\n", hiport); -+ break; -+ } -+ } -+ if (loport != 0 && hiport != 0) { -+ rbuf1len = sprintf(rbuf1, "%hu", loport); -+ rbufalen = sprintf(rbufa, hiport == loport+1 ? -+ "%hu-%hu":"%hu/%hu", loport, hiport); -+ } else { -+ if (loport != 0) -+ nf_ct_unexpect_related(rtp_exp); -+ if (hiport != 0) -+ nf_ct_unexpect_related(rtcp_exp); -+ } -+ break; -+ } -+ -+ if (rbuf1len == 0) -+ return 0; /* cannot get replacement port(s) */ -+ -+ /* Transport: tran;field;field=val,tran;field;field=val,... -+ `off` is set to the start of Transport value from start of line -+ */ -+ while (off < tranlen) { -+ uint saveoff; -+ const char* pparamend; -+ uint nextparamoff; -+ -+ pparamend = memchr(ptran+off, ',', tranlen-off); -+ pparamend = (pparamend == NULL) ? ptran+tranlen : pparamend+1; -+ nextparamoff = pparamend-ptran; -+ -+ /* -+ * We pass over each param twice. On the first pass, we look for a -+ * destination= field. It is handled by the security policy. If it -+ * is present, allowed, and equal to our external address, we assume -+ * that STUN is being used and we leave the client_port= field alone. -+ */ -+ is_stun = 0; -+ saveoff = off; -+ while (off < nextparamoff) { -+ const char* pfieldend; -+ uint nextfieldoff; -+ -+ pfieldend = memchr(ptran+off, ';', nextparamoff-off); -+ nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1; -+ SKIP_WSPACE(ptran, nextfieldoff, off); -+ -+ if (dstact != DSTACT_NONE && nextfieldoff - off > 12 && strncmp(ptran+off, "destination=", 12) == 0) { -+ if (strncmp(ptran+off+12, szextaddr, extaddrlen) == 0) -+ is_stun = 1; -+ -+ if (dstact == DSTACT_STRIP || (dstact == DSTACT_AUTO && !is_stun)) { -+ uint dstoff = (ptran-ptcp)+off; -+ uint dstlen = nextfieldoff-off; -+ char* pdstrep = NULL; -+ uint dstreplen = 0; -+ diff = dstlen; -+ if (dstact == DSTACT_AUTO && !is_stun) { -+ const char* psep = memchr(ptran+off, ':', dstlen); -+ u_int16_t port; -+ -+ dstoff += 12; -+ dstlen -= 13; -+ pdstrep = szextaddr; -+ -+ if (psep != NULL && nf_strtou16(psep + 1, &port)) { -+ pr_debug("RTSP: replace dst addr&port\n"); -+ -+ if (port != prtspexp->loport) { -+ pr_debug("multiple ports found, port %hu ignored\n", port); -+ dstreplen = extaddrlen; -+ } else { -+ sprintf(szextaddr+extaddrlen, ":%s", rbuf1); -+ dstreplen = extaddrlen+1+rbuf1len; -+ } -+ } else { -+ pr_debug("RTSP: replace dst addr\n"); -+ dstreplen = extaddrlen; -+ } -+ diff = nextfieldoff-off-13-dstreplen; -+ } -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+ if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, protoff, -+ dstoff, dstlen, pdstrep, dstreplen)) { -+#else -+ if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, -+ dstoff, dstlen, pdstrep, dstreplen)) { -+#endif -+ /* mangle failed, all we can do is bail */ -+ nf_ct_unexpect_related(rtp_exp); -+ if (rtcp_exp) -+ nf_ct_unexpect_related(rtcp_exp); -+ return 0; -+ } -+ get_skb_tcpdata(skb, &ptcp, &tcplen); -+ ptran = ptcp+tranoff; -+ tranlen -= diff; -+ nextparamoff -= diff; -+ nextfieldoff -= diff; -+ } -+ } -+ -+ off = nextfieldoff; -+ } -+ -+ if (is_stun) -+ continue; -+ -+ off = saveoff; -+ while (off < nextparamoff) { -+ const char* pfieldend; -+ uint nextfieldoff; -+ -+ pfieldend = memchr(ptran+off, ';', nextparamoff-off); -+ nextfieldoff = (pfieldend == NULL) ? nextparamoff : pfieldend-ptran+1; -+ -+ if (nextfieldoff - off > 12 && strncmp(ptran+off, "client_port=", 12) == 0) { -+ u_int16_t port; -+ uint numlen; -+ uint origoff; -+ uint origlen; -+ char* rbuf = rbuf1; -+ uint rbuflen = rbuf1len; -+ -+ off += 12; -+ origoff = (ptran-ptcp)+off; -+ origlen = 0; -+ numlen = nf_strtou16(ptran+off, &port); -+ off += numlen; -+ origlen += numlen; -+ if (port != prtspexp->loport) { -+ pr_debug("multiple ports found, port %hu ignored\n", port); -+ } else { -+ if (ptran[off] == '-' || ptran[off] == '/') { -+ off++; -+ origlen++; -+ numlen = nf_strtou16(ptran+off, &port); -+ off += numlen; -+ origlen += numlen; -+ rbuf = rbufa; -+ rbuflen = rbufalen; -+ } -+ -+ /* -+ * note we cannot just memcpy() if the sizes are the same. -+ * the mangle function does skb resizing, checks for a -+ * cloned skb, and updates the checksums. -+ * -+ * parameter 4 below is offset from start of tcp data. -+ */ -+ diff = origlen-rbuflen; -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+ if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, protoff, -+ origoff, origlen, rbuf, rbuflen)) { -+#else -+ if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, -+ origoff, origlen, rbuf, rbuflen)) { -+#endif -+ /* mangle failed, all we can do is bail */ -+ nf_ct_unexpect_related(rtp_exp); -+ if (rtcp_exp) -+ nf_ct_unexpect_related(rtcp_exp); -+ return 0; -+ } -+ get_skb_tcpdata(skb, &ptcp, &tcplen); -+ ptran = ptcp+tranoff; -+ tranlen -= diff; -+ nextparamoff -= diff; -+ nextfieldoff -= diff; -+ } -+ } -+ -+ off = nextfieldoff; -+ } -+ -+ off = nextparamoff; -+ } -+ -+ return 1; -+} -+ -+static uint -+help_out(struct sk_buff *skb, enum ip_conntrack_info ctinfo, -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+ unsigned int protoff, -+#endif -+ unsigned int matchoff, unsigned int matchlen, -+ struct ip_ct_rtsp_expect* prtspexp, -+ struct nf_conntrack_expect* rtp_exp, -+ struct nf_conntrack_expect* rtcp_exp) -+{ -+ char* ptcp; -+ uint tcplen; -+ uint hdrsoff; -+ uint hdrslen; -+ uint lineoff; -+ uint linelen; -+ uint off; -+ int dir = CTINFO2DIR(ctinfo); -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+ union nf_inet_addr saddr = rtp_exp->master->tuplehash[dir].tuple.src.u3; -+#else -+ __be32 saddr = rtp_exp->master->tuplehash[dir].tuple.src.u3.ip; -+#endif -+ -+ //struct iphdr* iph = (struct iphdr*)(*pskb)->nh.iph; -+ //struct tcphdr* tcph = (struct tcphdr*)((void*)iph + iph->ihl*4); -+ -+ get_skb_tcpdata(skb, &ptcp, &tcplen); -+ hdrsoff = matchoff;//exp->seq - ntohl(tcph->seq); -+ hdrslen = matchlen; -+ off = hdrsoff; -+ pr_debug("NAT rtsp help_out\n"); -+ -+ while (nf_mime_nextline(ptcp, hdrsoff+hdrslen, &off, &lineoff, &linelen)) { -+ if (linelen == 0) -+ break; -+ -+ if (off > hdrsoff+hdrslen) { -+ pr_info("!! overrun !!"); -+ break; -+ } -+ pr_debug("hdr: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff); -+ -+ if (nf_strncasecmp(ptcp+lineoff, "Transport:", 10) == 0) { -+ uint oldtcplen = tcplen; -+ pr_debug("hdr: Transport\n"); -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+ if (!rtsp_mangle_tran(ctinfo, protoff, rtp_exp, rtcp_exp, -+ prtspexp, skb, lineoff, linelen)) { -+#else -+ if (!rtsp_mangle_tran(ctinfo, rtp_exp, rtcp_exp, prtspexp, -+ skb, lineoff, linelen)) { -+#endif -+ pr_debug("hdr: Transport mangle failed"); -+ break; -+ } -+ rtp_exp->expectfn = nf_nat_rtsp_expected; -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+ rtp_exp->saved_addr = saddr; -+#else -+ rtp_exp->saved_ip = saddr; -+#endif -+ rtp_exp->saved_proto.udp.port = htons(prtspexp->loport); -+ rtp_exp->dir = !dir; -+ if (rtcp_exp) { -+ rtcp_exp->expectfn = nf_nat_rtsp_expected; -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+ rtcp_exp->saved_addr = saddr; -+#else -+ rtcp_exp->saved_ip = saddr; -+#endif -+ rtcp_exp->saved_proto.udp.port = htons(prtspexp->hiport); -+ rtcp_exp->dir = !dir; -+ } -+ get_skb_tcpdata(skb, &ptcp, &tcplen); -+ hdrslen -= (oldtcplen-tcplen); -+ off -= (oldtcplen-tcplen); -+ lineoff -= (oldtcplen-tcplen); -+ linelen -= (oldtcplen-tcplen); -+ pr_debug("rep: len=%u, %.*s", linelen, (int)linelen, ptcp+lineoff); -+ } -+ } -+ -+ return NF_ACCEPT; -+} -+ -+static unsigned int -+nf_nat_rtsp(struct sk_buff *skb, enum ip_conntrack_info ctinfo, -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+ unsigned int protoff, -+#endif -+ unsigned int matchoff, unsigned int matchlen, -+ struct ip_ct_rtsp_expect* prtspexp, -+ struct nf_conntrack_expect* rtp_exp, -+ struct nf_conntrack_expect* rtcp_exp) -+{ -+ int dir = CTINFO2DIR(ctinfo); -+ int rc = NF_ACCEPT; -+ -+ switch (dir) { -+ case IP_CT_DIR_ORIGINAL: -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+ rc = help_out(skb, ctinfo, protoff, matchoff, matchlen, prtspexp, -+ rtp_exp, rtcp_exp); -+#else -+ rc = help_out(skb, ctinfo, matchoff, matchlen, prtspexp, -+ rtp_exp, rtcp_exp); -+#endif -+ break; -+ case IP_CT_DIR_REPLY: -+ pr_debug("unmangle ! %u\n", ctinfo); -+ /* XXX: unmangle */ -+ rc = NF_ACCEPT; -+ break; -+ } -+ //UNLOCK_BH(&ip_rtsp_lock); -+ -+ return rc; -+} -+ -+static void nf_nat_rtsp_expected(struct nf_conn* ct, struct nf_conntrack_expect *exp) -+{ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0) -+ struct nf_nat_range2 range; -+#elif LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+ struct nf_nat_range range; -+#else -+ struct nf_nat_ipv4_range range; -+#endif -+ -+ /* This must be a fresh one. */ -+ BUG_ON(ct->status & IPS_NAT_DONE_MASK); -+ -+ /* For DST manip, map port here to where it's expected. */ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+ range.min_proto = range.max_proto = exp->saved_proto; -+ range.min_addr = range.max_addr = exp->saved_addr; -+#else -+ range.min = range.max = exp->saved_proto; -+ range.min_ip = range.max_ip = exp->saved_ip; -+#endif -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0) -+ range.flags = (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED); -+ nf_nat_setup_info(ct, &range, NF_NAT_MANIP_DST); -+#else -+ range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED); -+ nf_nat_setup_info(ct, &range, IP_NAT_MANIP_DST); -+#endif -+ -+ /* Change src to where master sends to, but only if the connection -+ * actually came from the same source. */ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) -+ if (nf_inet_addr_cmp(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3, -+ &ct->master->tuplehash[exp->dir].tuple.src.u3)) { -+ range.min_addr = range.max_addr -+ = ct->master->tuplehash[!exp->dir].tuple.dst.u3; -+#else -+ if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip == -+ ct->master->tuplehash[exp->dir].tuple.src.u3.ip) { -+ range.min_ip = range.max_ip -+ = ct->master->tuplehash[!exp->dir].tuple.dst.u3.ip; -+#endif -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0) -+ range.flags = NF_NAT_RANGE_MAP_IPS; -+ nf_nat_setup_info(ct, &range, NF_NAT_MANIP_SRC); -+#else -+ range.flags = IP_NAT_RANGE_MAP_IPS; -+ nf_nat_setup_info(ct, &range, IP_NAT_MANIP_SRC); -+#endif -+ } -+} -+ -+ -+static void __exit fini(void) -+{ -+ rcu_assign_pointer(nf_nat_rtsp_hook, NULL); -+ synchronize_net(); -+} -+ -+static int __init init(void) -+{ -+ printk("nf_nat_rtsp v" IP_NF_RTSP_VERSION " loading\n"); -+ -+ BUG_ON(nf_nat_rtsp_hook); -+ rcu_assign_pointer(nf_nat_rtsp_hook, nf_nat_rtsp); -+ -+ if (stunaddr != NULL) -+ extip = in_aton(stunaddr); -+ -+ if (destaction != NULL) { -+ if (strcmp(destaction, "auto") == 0) -+ dstact = DSTACT_AUTO; -+ -+ if (strcmp(destaction, "strip") == 0) -+ dstact = DSTACT_STRIP; -+ -+ if (strcmp(destaction, "none") == 0) -+ dstact = DSTACT_NONE; -+ } -+ -+ return 0; -+} -+ -+module_init(init); -+module_exit(fini); ---- a/extensions/Kbuild -+++ b/extensions/Kbuild -@@ -27,6 +27,7 @@ obj-${build_lscan} += xt_lscan.o - obj-${build_pknock} += pknock/ - obj-${build_psd} += xt_psd.o - obj-${build_quota2} += xt_quota2.o -+obj-${build_rtsp} += rtsp/ - - -include ${M}/*.Kbuild - -include ${M}/Kbuild.* ---- a/mconfig -+++ b/mconfig -@@ -23,3 +23,4 @@ build_lscan=m - build_pknock=m - build_psd=m - build_quota2=m -+build_rtsp=m diff --git a/xtables-addons/patches/200-add-lua-packetscript.patch b/xtables-addons/patches/200-add-lua-packetscript.patch deleted file mode 100644 index 8dd926712..000000000 --- a/xtables-addons/patches/200-add-lua-packetscript.patch +++ /dev/null @@ -1,18158 +0,0 @@ ---- /dev/null -+++ b/extensions/LUA/byte_array.c -@@ -0,0 +1,145 @@ -+/* -+ * Copyright (C) 2010 University of Basel -+ * by Andre Graf -+ * -+ * This program 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. -+ * -+ * 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. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, see . -+ */ -+#include "controller.h" -+ -+/* Initialization helper function. This function should be used whenever -+ * a new byte array need to be initialized. Depending on the arguments it -+ * initializes the array in a different way. Have a look at the inline -+ * comments */ -+lua_packet_segment * init_byte_array(lua_State *L, unsigned char * start, int length, int do_copy) -+{ -+ lua_packet_segment *array; -+ -+ if (length < 0) -+ luaL_error(L, "init_byte_array, requested size < 0"); -+ -+ if (start && do_copy) { -+ /* we have a start address where we copy from */ -+ array = lua_newuserdata(L, sizeof(lua_packet_segment) + length); -+ array->start = (unsigned char *)array + sizeof(lua_packet_segment); /* aligning pointer */ -+ memcpy(array->start, start, length); -+ }else if (start && !do_copy) { -+ /* just link the start pointer, in this case you have to free the memory yourself */ -+ array = lua_newuserdata(L, sizeof(lua_packet_segment)); -+ array->start = start; -+ }else{ -+ /* create an empty array, fully managed by Lua */ -+ array = lua_newuserdata(L, sizeof(lua_packet_segment) + length); -+ array->start = (unsigned char *)array + sizeof(lua_packet_segment); /* aligning pointer */ -+ memset(array->start, 0, length); -+ } -+ -+ array->length = length; -+ array->offset = 0; -+ array->changes = NULL; -+ -+ luaL_getmetatable(L, LUA_BYTE_ARRAY); -+ lua_setmetatable(L, -2); -+ -+ return array; -+} -+ -+ -+ -+/* LUA_API: get one byte of the given byte array -+ * access-pattern: array[] */ -+static int32_t get_byte_array(lua_State *L) -+{ -+ lua_packet_segment * array = checkbytearray(L, 1); -+ int32_t index = luaL_checkinteger(L, 2); /* array starts with index 0 (not 1 as usual in Lua) */ -+ -+ luaL_argcheck(L, 0 <= index && index < array->length, 1, "index out of range"); -+ lua_pushinteger(L, (array->start + array->offset)[index]); -+ -+ return 1; -+} -+ -+/* LUA_API: set one byte of the given byte array -+ * access-pattern: array[]= 0xFF */ -+static int32_t set_byte_array(lua_State *L) -+{ -+ lua_packet_segment * array = checkbytearray(L, 1); -+ uint8_t byte; -+ int32_t index = luaL_checkinteger(L, 2); /* array starts with index 0 (not 1 as usual in Lua) */ -+ int32_t val = luaL_checkinteger(L, 3); -+ uint32_t nob = 1 << CHAR_BIT; /* we should use something like 1 << CHAR_BIT */ -+ -+ luaL_argcheck(L, 0 <= index && index < array->length, 1, "index out of range"); -+ luaL_argcheck(L, 0 <= val && val < nob, 2, "cannot cast value to char"); -+ -+ byte = (uint8_t)val; -+ -+ (array->start + array->offset)[index] = byte; -+ -+ return 0; -+} -+ -+/* LUA_API: get size of the given byte array -+ * access-pattern: #array (__length meta-method) */ -+static int32_t get_byte_array_size(lua_State *L) -+{ -+ lua_packet_segment * array = checkbytearray(L, 1); -+ -+ lua_pushnumber(L, array->length); -+ -+ return 1; -+} -+ -+ -+/* LUA_API: converts a given byte array to a string. -+ * access-pattern: implicit through functions calling the -+ * __to_string() metamethod , e.g. print32_t */ -+static int32_t byte_array_to_string(lua_State *L) -+{ -+ lua_packet_segment * array = checkbytearray(L, 1); -+ uint8_t buf[(array->length * 3) + 255]; -+ uint8_t hexval[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; -+ char res[255 + (array->length * 3)]; /* make sure the buffer is big enough*/ -+ int32_t i, n; -+ uint8_t *ptr = array->start + array->offset; -+ -+ for (i = 0; i < array->length; i++) { -+ buf[i * 3] = hexval[(ptr[i] >> 4) & 0xF]; -+ buf[(i * 3) + 1] = hexval[ptr[i] & 0x0F]; -+ buf[(i * 3) + 2] = ' '; /* seperator */ -+ } -+ -+ buf[array->length * 3] = '\0'; -+ n = sprintf(res, "byte_array: length: %d value: %s", array->length, buf); -+ -+ lua_pushlstring(L, res, n); -+ -+ return 1; -+} -+ -+static const struct luaL_Reg bytearray_lib_m [] = { -+ { "__len", get_byte_array_size }, -+ { "__newindex", set_byte_array }, -+ { "__index", get_byte_array }, -+ { "__tostring", byte_array_to_string }, -+ { NULL, NULL } -+}; -+ -+void luaopen_bytearraylib(lua_State *L) -+{ -+ luaL_newmetatable(L, LUA_BYTE_ARRAY); -+ luaL_register(L, NULL, bytearray_lib_m); -+ lua_pop(L, 1); -+} -+ -+ ---- /dev/null -+++ b/extensions/LUA/controller.c -@@ -0,0 +1,604 @@ -+/* -+ * Copyright (C) 2010 University of Basel -+ * by Andre Graf -+ * -+ * This program 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. -+ * -+ * 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. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, see . -+ */ -+ -+#if defined(__KERNEL__) -+ #include -+#endif -+#include "controller.h" -+ -+/* the array 'supported_protocols' holds all pointers to the -+ * static and dynamic protocol buffers. It is filled by the -+ * call to register_protbuf */ -+static struct protocol_buf * supported_protocols[MAX_NR_OF_PROTOCOLS]; -+ -+/* C_API: the function 'get_protocol_buf' returns the pointer -+ * to the protocol buffer of a given protocol id. */ -+struct protocol_buf * get_protocol_buf(uint32_t protocol_id) -+{ -+ return (struct protocol_buf *)supported_protocols[protocol_id]; -+} -+ -+ -+/* LUA_INT: the function 'gc_packet_segment' is triggered by the -+ * garbage collector whenever a userdata annotated with one of -+ * the protocol buffer metatable should be collected. */ -+static int32_t gc_packet_segment(lua_State *L) -+{ -+ lua_packet_segment * seg = (lua_packet_segment *)lua_touserdata(L, 1); -+ if (seg && seg->changes) { -+ seg->changes->ref_count--; -+ if (seg->changes->ref_count <= 0) { -+ kfree(seg->changes->field_length_changes); -+ kfree(seg->changes->field_offset_changes); -+ kfree(seg->changes); -+ seg->changes = NULL; -+ } -+ } -+ return 0; -+} -+ -+ -+/* LUA_API: the function 'set_raw' is used to set the bytes of a segment -+ * in 'raw' mode. The function is per default available in each protocol -+ * buffer until it gets overridden by a specific setter function inside -+ * a protocol buffer. -+ * -+ * Parameters: -+ * 1. lua_packet_segment (implicit) -+ * 2. int32_t byte_value -+ * -+ * Upvalues: -+ * 1. struct protocol_buf* -+ * 2. int32_t field index, not used in this function -+ * -+ * Return: void -+ */ -+static int32_t set_raw(lua_State *L) -+{ -+ int32_t i; -+ uint32_t nob; -+ uint8_t byte; -+ uint8_t *ptr; -+ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); -+ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); -+ -+ int32_t val = luaL_checkinteger(L, 2); -+ -+ nob = 1 << CHAR_BIT; -+ -+ luaL_argcheck(L, 0 <= val && val < nob, 2, "cannot cast value to char"); -+ -+ byte = (uint8_t)val; -+ ptr = seg->start + seg->offset; -+ -+ for (i = 0; i < seg->length; i++) -+ ptr[i] = byte; -+ -+ return 0; -+} -+ -+/* LUA_API: the function 'get_raw' is used to get the bytes of a segment -+ * in 'raw' mode. The function is per default available in each protocol -+ * buffer until it gets overridden by a specific getter function inside -+ * a protocol buffer. -+ * -+ * Parameters: -+ * 1. lua_packet_segment (implicit) -+ * 2. uint32_t offset -+ * 3. uint32_t length -+ * -+ * Upvalues: -+ * 1. struct protocol_buf* -+ * 2. int32_t field index, not used in this function -+ * -+ * Return: -+ * the byte array representing the given array -+ */ -+static int32_t get_raw(lua_State *L) -+{ -+ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); -+ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); -+ -+ init_byte_array(L, seg->start + seg->offset, seg->length, 1); -+ -+ return 1; -+} -+/* LUA_API: The function 'get_segment' is used to get a new segment in 'raw' mode. -+ * Typically this function is applied on another raw segment in order -+ * to extract a part of the segment as new segment. -+ * -+ * Parameters: -+ * 1. lua_packet_segment, implicit through object oriented access seg:raw(..) -+ * 2. uint32_t offset, this indicates where to start the new segment, see e.g below. -+ * 3. uint32_t length, this indicates the size of the new segment -+ * -+ * Upvalues: -+ * 1. struct protocol_buf* -+ * 2. int32_t field index, not used in this function -+ * -+ * Return: -+ * 1. A lua_packet_segment annotated with the according metatable or False in -+ * case the input data is not valid -+ * -+ * Example: -+ * -+ * +------------------------+---------------------------------------+ -+ * | function call | resulting lua_packet_segment | -+ * +========================+===+===+===+===+===+===+===+===+===+===+ -+ * | seg = packet:raw(0,10) | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -+ * +------------------------+---+---+---+---+---+---+---+---+---+---+ -+ * | 1st_half = seg:raw(0,5)| 0 | 1 | 2 | 3 | 4 | | -+ * +------------------------+---+---+---+---+---+---+---+---+---+---+ -+ * | 2nd_half = seg:raw(5,5)| | 5 | 6 | 7 | 8 | 9 | -+ * +------------------------+-------------------+---+---+---+---+---+ -+ */ -+static int32_t get_segment(lua_State *L) -+{ -+ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); -+ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); -+ uint32_t offset = luaL_checkinteger(L, 2); -+ uint32_t length = luaL_checkinteger(L, 3); -+ lua_packet_segment * new = (lua_packet_segment *)lua_newuserdata(L, sizeof(lua_packet_segment)); -+ -+ new->start = seg->start; -+ new->offset = seg->offset + offset; -+ new->changes = NULL; -+ /* we allow a seg->length == 0 , this enables processing packets where the packetsize is not fixed (0 = not fixed)*/ -+ if (seg->length != 0 && length > seg->length) { -+ lua_pushboolean(L, 0); -+ return 1; -+ } -+ -+ new->length = length; -+ luaL_getmetatable(L, prot_buf->name); -+ lua_setmetatable(L, -2); -+ -+ return 1; -+} -+ -+/* LUA_API: the function 'get_segment_size' is used to get the size of a segment. -+ * -+ * Parameters: -+ * 1. lua_packet_segment, implicit through object oriented access seg:raw(..) -+ * -+ * Upvalues: -+ * 1. struct protocol_buf* -+ * 2. int32_t field index, not used in this function -+ * -+ * Return: -+ * 1. Size as lua_Number -+ */ -+static int32_t get_segment_size(lua_State *L) -+{ -+ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); -+ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); -+ -+ lua_pushnumber(L, seg->length); -+ return 1; -+} -+ -+/* LUA_API: the function 'get_segment_offset' is used to get the real offset -+ * of a segment. This function returns the offset of the segment to the start -+ * of the buffer. This means the following -+ * seg1 = packet:raw(2,10) -+ * seg2 = seg1:raw(3,5) -+ * offset = seg2:get_offset() -+ * -+ * will give an offset of 5, since the seg1 starts at offset 2, and seg2 starts -+ * at offset (seg1:get_offset() + 3). -+ * -+ * Parameters: -+ * 1. lua_packet_segment, implicit through object oriented access seg:raw(..) -+ * -+ * Upvalues: -+ * 1. struct protocol_buf* -+ * 2. int32_t field index, not used in this function -+ * -+ * Return: -+ * 1. Offset as lua_Number -+ */ -+static int32_t get_segment_offset(lua_State *L) -+{ -+ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); -+ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); -+ -+ lua_pushnumber(L, seg->offset); -+ return 1; -+} -+ -+/* LUA_API: overwrites the __tostring function of a lua_packet_segment. -+ * this will print32_t a nicely formated string, including length, -+ * offset and name of the protocol buffer. -+ * -+ * Parameters: -+ * 1. lua_packet_segment (implicit) -+ * -+ * Returns: -+ * 1. the representing string -+ */ -+static int32_t packet_segment_tostring(lua_State *L) -+{ -+ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); -+ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); -+ int32_t n; -+ char buf[128]; -+ -+ n = sprintf(buf, "type: %s, offset: %d, length: %d", prot_buf->name, seg->offset, seg->length); -+ lua_pushlstring(L, buf, n); -+ -+ return 1; -+} -+ -+ -+static const struct luaL_Reg seg_access_functions [] = { -+ { "set", set_raw }, -+ { "get", get_raw }, -+ { "raw", get_segment }, -+ { "get_offset", get_segment_offset }, -+ { "get_size", get_segment_size }, -+ { "to_bytes", get_raw }, -+ { "__tostring", packet_segment_tostring }, -+ { "__gc", gc_packet_segment }, -+ { NULL, NULL } -+}; -+ -+/* C_API: the function 'get_metatable_from_protocol_type' is a helper -+ * used in controller.c as well as it may find usage in the static -+ * protocol buffers and byte array implementation. */ -+void get_metatable_from_protocol_type(lua_State *L, int32_t type) -+{ -+ char * table; -+ lua_getglobal(L, SUPPORTED_PROTOCOL_TABLE); -+ lua_rawgeti(L, -1, type); -+ table = (char *)luaL_checkstring(L, -1); -+ lua_pop(L, 2); /* pop the table SUPPORTED_PROTOCOL_TABLE and the string pushed by lua_gettable */ -+ luaL_getmetatable(L, table); -+ return; -+} -+ -+/* C_INT: the function 'payload_contains_protocol' is used internally. -+ * Depending if static or dynamic protocol buffer it calls the right -+ * validation function. */ -+static int32_t payload_contains_protocol(lua_State *L, struct protocol_buf *prot_buf, lua_packet_segment *seg, uint32_t prot_type) -+{ -+ if (prot_buf->is_dynamic) -+ return has_protocol_dynamic(L, prot_buf, seg, prot_type); -+ else -+ return prot_buf->has_protocol(L, prot_buf, seg, prot_type); -+} -+ -+/* C_INT: the function 'protocol_get_field_changes' is used interally. -+ * It requests the field_changes struct calling the protocol buffers -+ * 'get_field_changes' function. This funciton is called, whenever -+ * the payload field with a given protocol type is requested inside -+ * the function 'get_protocol_field' */ -+static struct field_changes * protocol_get_field_changes(lua_State *L, struct protocol_buf *prot_buf, lua_packet_segment * seg) -+{ -+ struct field_changes * changes = NULL; -+ -+ if (prot_buf->get_field_changes) { -+ if (prot_buf->is_dynamic) -+ changes = get_field_changes_dynamic(L, prot_buf, seg); -+ else -+ changes = prot_buf->get_field_changes(L, seg); -+ /* is already 1 when set by helper 'get_allocated_field_changes, -+ * since not every prot_buf may use this function we enforce it. */ -+ changes->ref_count = 1; -+ } -+ return changes; -+} -+ -+/* C_INT: the function 'get_field_offset_in_bytes' wrapps the logic of -+ * calculating the new length with considering the optional field_changes. */ -+static int32_t get_field_offset_in_bytes(struct protocol_field * field, lua_packet_segment * seg, int32_t field_index) -+{ -+ uint32_t nr_of_bits, nr_of_bytes, field_offset; -+ -+ field_offset = field->offset; -+ /* do we need to manipulate the default values stored inside the protocol buffer ?? */ -+ if (seg->changes) -+ field_offset += seg->changes->field_offset_changes[field_index]; -+ /* how many bits remain */ -+ nr_of_bits = field_offset & (CHAR_BIT - 1); -+ /* assuming CHAR_BIT == 2 ^ 3 */ -+ nr_of_bytes = (field_offset - nr_of_bits) >> 3; -+ -+ return seg->offset + nr_of_bytes; -+} -+ -+/* C_INT: the function 'get_field_length_in_bytes' wrapps the logic of -+ * calculating the new offset with considering the optional field_changes. */ -+static int32_t get_field_length_in_bytes(struct protocol_field * field, lua_packet_segment * seg, int32_t field_index) -+{ -+ uint32_t nr_of_bits, nr_of_bytes, field_length; -+ -+ field_length = field->length; -+ /* if the field length is smaller than 1 byte, we take the size of one byte -+ * we treat the case where field_length == 0 in a special way ...*/ -+ if (field_length < CHAR_BIT && field_length > 0) -+ field_length = CHAR_BIT; -+ -+ /* do we need to manipulate the default values stored inside the protocol buffer ?? */ -+ if (seg->changes) -+ field_length += seg->changes->field_length_changes[field_index]; -+ /* how many bits remain */ -+ nr_of_bits = field_length & (CHAR_BIT - 1); -+ /* assuming CHAR_BIT == 2 ^ 3 */ -+ nr_of_bytes = (field_length - nr_of_bits) >> 3; -+ return nr_of_bytes; -+} -+ -+/* C_INT: the function 'initialize_field_getter_and_setter' initializes -+ * the setter and getter function of the field, considering the optional -+ * field manipulator functions defined inside the protocol buffers. */ -+static void initialize_field_getter_and_setter(lua_State *L, struct protocol_buf *prot_buf, int32_t field_index) -+{ -+ /* lets check if there is a metatable on top of the stack */ -+ struct protocol_field * f = (struct protocol_field *)&prot_buf->protocol_fields[field_index]; -+ -+ if (!lua_istable(L, -1)) luaL_error(L, "cannot initialize getter and setter for field %s->%s, " -+ "not a table on top of the stack, is '%s'", prot_buf->name, f->name, lua_typename(L, lua_type(L, -1))); -+ -+ /* is there a 'getter' to initialize ? */ -+ lua_pushlightuserdata(L, prot_buf); /* push upvalue 1 */ -+ lua_pushinteger(L, field_index); /* push upvalue 2 */ -+ if (f->get) { -+ if (prot_buf->is_dynamic) -+ lua_pushcclosure(L, field_dynamic_getter, 2); -+ else -+ lua_pushcclosure(L, f->get, 2); -+ }else -+ /* there is no specific getter defined - fall back to 'get_raw' */ -+ lua_pushcclosure(L, get_raw, 2); -+ /* set the metatable field 'get' */ -+ lua_setfield(L, -2, "get"); -+ -+ /* is there a 'setter' to initialize ? */ -+ lua_pushlightuserdata(L, prot_buf); /* push upvalue 1 */ -+ lua_pushinteger(L, field_index); /* push upvalue 2 */ -+ if (f->set) { -+ if (prot_buf->is_dynamic) -+ lua_pushcclosure(L, field_dynamic_setter, 2); -+ else -+ lua_pushcclosure(L, f->set, 2); -+ }else -+ /* there is no specific setter defined - fall back to 'set_raw' */ -+ lua_pushcclosure(L, set_raw, 2); -+ /* set the metatable field 'set' */ -+ lua_setfield(L, -2, "set"); -+} -+ -+/* LUA_API: 'get_protocol_field' is used in Lua as a closure for each field of a protocol -+ * buffer. E.g a call to ip = packet:data(packet_ip) will go to this function, -+ * and trigger the conversion of the raw packet to a ip packet. Each call -+ * to a field function of an IP packet, like ip:daddr() uses this function -+ * to to return the right data. In each case you will end up either with a -+ * new packet segment (annotated with the proper metatable) or a boolean -+ * value (False) if something went wrong. In the case everything went fine, -+ * the newly created lua_packet_segment is annotated with the proper -+ * metatable where the fields get and set also contain the specific getter -+ * and setter functions given by the protocol buffer. E.g. the function call -+ * ip:daddr():get() or ip:daddr():set(...) will call the proper function -+ * defined inside the corresponding field definition. -+ * -+ * Parameters: -+ * 1. lua_packet_segment, implicit through object oriented access seg:raw(..) -+ * 2. type of the protocol buffer, optional, and only used if the accessed -+ * field is the payload field. If a type is provided for the access of the -+ * payload field, the function tries to convert the data pointed to by the -+ * payload field to the given type. To check if such a conversion is -+ * possible, it calls the function pointed to by the protocol buffer member -+ * has_protocol. If this function returns True, the conversion takes place. -+ * -+ * Upvalues: -+ * 1. struct protocol_buf* -+ * 2. int32_t field index -+ * -+ * Return: -+ * 1. A lua_packet_segment annotated with the according metatable or False in -+ * case the input data is not valid -+ */ -+static int32_t get_protocol_field(lua_State *L) -+{ -+ int32_t prot_type; -+ lua_packet_segment * seg, *new; -+ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); -+ int32_t field_index = lua_tointeger(L, lua_upvalueindex(2)); -+ struct protocol_field * field = &prot_buf->protocol_fields[field_index]; -+ -+ /* get the current packet segment */ -+ seg = checkpacketseg(L, 1, prot_buf->name); -+ -+ /* initialize the new packet segment */ -+ new = (lua_packet_segment *)lua_newuserdata(L, sizeof(lua_packet_segment)); -+ new->start = seg->start; /* the start is unchanged */ -+ new->offset = get_field_offset_in_bytes(field, seg, field_index); -+ new->length = get_field_length_in_bytes(field, seg, field_index); -+ -+ /* if new->length == 0 then no configuration was done, we guess the size by subtracting the -+ * new offset from the packet length. since the old length is getting initialized by the -+ * netfilter extension this assumption holds for the very last field of the protocol. -+ * this 'feature' should be used by protocol buffers containing a payload, whereas the -+ * payload field is the last field of the buffer. However, at compile-time unknown field -+ * sizes (and offsets) of fields not being placed at the end of the protocol should be -+ * initialized using the 'get_field_changes' hook system. */ -+ if (new->length == 0) -+ new->length = (seg->length + seg->offset) - (new->offset); -+ /* -+ printf("%s->%s:: seg->offset %i, seg->length %i, new->offset %i, new->length %i\n", -+ prot_buf->name, field->name, seg->offset, seg->length, new->offset, new->length); -+ */ -+ /* special care for packet payload requests */ -+ if (prot_buf->payload_field != NULL && strcmp(prot_buf->payload_field, field->name) == 0) { -+ /* we know the payload field is requested */ -+ /* the requested payload can be delivered either as a common segment or as -+ * an other packet type, such a conversion needs an extra protocol parameter -+ * ... so lets check */ -+ -+ if (lua_isnumber(L, 2)) { -+ /* we have an extra parameter, ... lets see if it is a valid protocol -+ * the parameter is the index of the 'supported_protocols'-array member */ -+ prot_type = lua_tointeger(L, 2); -+ if (prot_type >= 0 && prot_type < PACKET_SENTINEL) { -+ /* we are sure the purpose of the request is to get the payload data, -+ * converted to the given protocol. lets check if the payload contains -+ * data of the given protocol */ -+ if (payload_contains_protocol(L, prot_buf, seg, prot_type)) { -+ /* success, we can push the metatable for the given protocol */ -+ get_metatable_from_protocol_type(L, prot_type); -+ if (!lua_isnil(L, -1)) /* check if the metatable was found */ -+ /* perhaps the field offsets and lengths of the containing protocol -+ * are not set correctly. request the optional 'field_changes' structure -+ * holding the changes for lengths and offsets. */ -+ new->changes = protocol_get_field_changes(L, get_protocol_buf(prot_type), new); -+ else{ -+ /* failed, the requested protocol is not available -+ * we push false and return */ -+ lua_pop(L, 1); /* pop the userdata */ -+ lua_pushboolean(L, 0); -+ return 1; -+ } -+ }else{ -+ /* payload does not carry the provided protocol */ -+ /* we push false and return */ -+ lua_pop(L, 1); /* pop the userdata */ -+ lua_pushboolean(L, 0); -+ return 1; -+ } -+ }else{ -+ /* unknown protocol */ -+ lua_pop(L, 1); /* pop the userdata */ -+ luaL_error(L, "provided protocol is unknown"); -+ } -+ } -+ } -+ -+ /* if there is still the 'new' userdata on the top, we push our own metatable */ -+ if (lua_isuserdata(L, -1)) { -+ luaL_getmetatable(L, prot_buf->name); -+ new->changes = seg->changes; -+ if (seg->changes) -+ new->changes->ref_count++; -+ } -+ -+ /* a new packet segment is at index -2 , and the proper metatable at index -1 of the stack -+ * lets set the propper setter and getter function for the requested field */ -+ initialize_field_getter_and_setter(L, prot_buf, field_index); -+ -+ lua_setmetatable(L, -2); -+ return 1; -+} -+ -+/* C_API: 'register_protbuf' is only used internally. This function takes a -+ * pointer to a fully initialized protocol buffer struct and registers it -+ * inside the Lua state. Registering means: -+ * -+ * 1. it creates a new metatable with the name of the protocol buffer. -+ * 2. it registers the default functions which are stored in the luaL_Reg -+ * array seg_access_functions. -+ * 3. it loops over the protocol fields stored at prot_buf->protocol_fields -+ * and registers a new function (using the field name) inside the -+ * metatable. Each field points to the function 'get_protocol_field' -+ * which acts as a closure taking a pointer to the protocol buffer as -+ * well as the index of the field as upvalues. -+ * 4. The protocol index, serves as numerical identifier of this protocol -+ * buffer or even of the protocol itself. This index is stored as a -+ * global value inside the Lua state as well as inside the Lua table -+ * 'supported_protocols'. Assuming the name of a procotol buffer is -+ * "packet_ip" the following statements are true: -+ * -+ * supported_protocols[protocol_index] == "packet_ip" -+ * packet_ip == protocol_index -+ * -+ * This allows you to get all registered protocols from within Lua. This -+ * is especially usefull for the dynamic protocol buffers where you have -+ * to provide your own "has_protocol"-function, which probably needs the -+ * information on which protocols it is able to contain. -+ */ -+void register_protbuf(lua_State *L, struct protocol_buf * prot_buf, uint32_t protocol_index) -+{ -+ int32_t field_index; -+ luaL_Reg *reg = (struct luaL_Reg *)seg_access_functions; -+ struct protocol_field * field = prot_buf->protocol_fields; -+ -+ luaL_newmetatable(L, prot_buf->name); -+ -+ /* metatable.__index = metatable */ -+ lua_pushvalue(L, -1); /* duplicates the metatable */ -+ lua_setfield(L, -2, "__index"); -+ -+ /* pushing default functions */ -+ for (; reg->name; reg++) { -+ lua_pushlightuserdata(L, (void *)prot_buf); -+ lua_pushcclosure(L, reg->func, 1); -+ lua_setfield(L, -2, reg->name); -+ } -+ -+ /* pushing functions specific to the protocol buffer */ -+ for (field_index = 0; field->name; field++, field_index++) { -+ lua_pushlightuserdata(L, (void *)prot_buf); /* upvalue: prot_buf */ -+ lua_pushinteger(L, field_index); /* upvalue: index of protocol field */ -+ lua_pushcclosure(L, get_protocol_field, 2); -+ lua_setfield(L, -2, field->name); -+ } -+ /* pop the metatable */ -+ lua_pop(L, 1); -+ -+ /* registering the array-index as the protocol_id*/ -+ lua_getglobal(L, "_G"); -+ lua_pushinteger(L, protocol_index); -+ lua_setfield(L, -2, prot_buf->name); -+ lua_pop(L, 1); /* pop _G */ -+ -+ lua_getglobal(L, SUPPORTED_PROTOCOL_TABLE); -+ lua_pushstring(L, prot_buf->name); -+ lua_rawseti(L, -2, protocol_index); -+ -+ lua_pop(L, 1); /* pop SUPPORTED_PROTOCOL_TABLE */ -+ -+ supported_protocols[protocol_index] = prot_buf; -+} -+ -+void luaopen_controller(lua_State *L) -+{ -+ /* registering a table inside the _G with table[protocol_index] = prot_buf->name */ -+ lua_getglobal(L, "_G"); -+ lua_newtable(L); -+ lua_setfield(L, -2, SUPPORTED_PROTOCOL_TABLE); -+ lua_pop(L, 1); /* pop _G */ -+ -+ luaopen_protbuf_raw(L); -+ luaopen_protbuf_eth(L); -+ luaopen_protbuf_ip(L); -+ luaopen_protbuf_icmp(L); -+ luaopen_protbuf_tcp(L); -+ luaopen_protbuf_tcp_options(L); -+ luaopen_protbuf_udp(L); -+ luaopen_protbuf_tftp(L); -+ luaopen_protbuf_dynamic(L); -+ /* should follow all other static buffers */ -+#if defined(__KERNEL__) -+ luaopen_nflib(L); -+#endif -+ -+ luaopen_bytearraylib(L); -+} -+ -+ -+ -+ ---- /dev/null -+++ b/extensions/LUA/controller.h -@@ -0,0 +1,264 @@ -+/* -+ * Copyright (C) 2010 University of Basel -+ * by Andre Graf -+ * -+ * This program 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. -+ * -+ * 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. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, see . -+ */ -+ -+#ifndef CONTROLLER_H_ -+#define CONTROLLER_H_ -+ -+#include "stdlib.h" /* wrapper */ -+#include "string.h" /* wrapper */ -+#include "lua.h" -+#include "lualib.h" -+#include "lauxlib.h" -+ -+#if defined(__KERNEL__) -+#include -+#include -+#include -+#endif -+ -+ -+/* to compile the stuff in userspace (for testing)*/ -+#if !defined(__KERNEL__) -+#include -+#define pr_debug printf; -+ -+#define kmalloc(size, type) malloc(size) -+#define kfree(ptr) free(ptr) -+ -+#endif -+ -+ -+/**********************************************************************/ -+/* nf Lua configuration */ -+/**********************************************************************/ -+#define MAX_NR_OF_PROTOCOLS 16 -+#define SUPPORTED_PROTOCOL_TABLE "supported_protocols" -+ -+#define MAX_NR_OF_FIELDS_IN_DYN_PROT_BUF 32 -+ -+ -+/**********************************************************************/ -+/* Static Protocol Buffer configuration */ -+/**********************************************************************/ -+ -+/* the definitions of the stringified expression of the prot_bufs... -+ * make sure all static prot_bufs are listed and are unique */ -+#define LUA_PACKET_SEG_RAW "packet_raw" -+#define LUA_PACKET_SEG_ETH "packet_eth" -+#define LUA_PACKET_SEG_ICMP "packet_icmp" -+#define LUA_PACKET_SEG_IP "packet_ip" -+#define LUA_PACKET_SEG_TCP "packet_tcp" -+#define LUA_PACKET_SEG_TCP_OPT "packet_tcp_opt" -+#define LUA_PACKET_SEG_UDP "packet_udp" -+#define LUA_PACKET_SEG_TFTP "packet_tftp" -+ -+/* the enum holding all static prot_bufs... make sure it contains all -+ * static prot_bufs */ -+enum PROT_BUF { -+ PACKET_RAW, -+ PACKET_ETH, -+ PACKET_IP, -+ PACKET_ICMP, -+ PACKET_TCP, -+ PACKET_TCP_OPTIONS, -+ PACKET_UDP, -+ PACKET_TFTP, -+ PACKET_DYNAMIC, -+ PACKET_SENTINEL -+}; -+ -+/* the luaopen-function of the prot_bufs... make sure it is called -+ * inside luaopen_controller */ -+void luaopen_protbuf_raw(lua_State *L); -+void luaopen_protbuf_eth(lua_State *L); -+void luaopen_protbuf_ip(lua_State *L); -+void luaopen_protbuf_icmp(lua_State *L); -+void luaopen_protbuf_tcp(lua_State *L); -+void luaopen_protbuf_tcp_options(lua_State *L); -+void luaopen_protbuf_udp(lua_State *L); -+void luaopen_protbuf_tftp(lua_State *L); -+void luaopen_protbuf_dynamic(lua_State *L); -+ -+/**********************************************************************/ -+/* field changes */ -+/**********************************************************************/ -+struct field_changes { -+ int ref_count; -+ int *field_length_changes; -+ int *field_offset_changes; -+}; -+ -+/**********************************************************************/ -+/* lua packet segment */ -+/* ------------------ */ -+/* The struct lua_packet_segment is the integral part of a Lua packet.*/ -+/* At the very beginning, when a new packet arrives in `lua_tg`_ such */ -+/* a struct is initialized. The field start then points to the lowest */ -+/* available header inside the sk_buff structure. During packet */ -+/* processing the start pointer remains the same, only the offset and */ -+/* length value change. */ -+/**********************************************************************/ -+#define checkpacketseg(L, i, seg_type) \ -+ (lua_packet_segment *)luaL_checkudata(L, i, seg_type) -+ -+typedef struct lua_packet_segment { -+ unsigned int offset; -+ unsigned int length; -+ struct field_changes * changes; -+ unsigned char * start; /* need to be at the end because of the memory alignment */ -+} lua_packet_segment; -+ -+/**********************************************************************/ -+/* protocol field */ -+/* -------------- */ -+/* This structure is a container for the field definitions used by the*/ -+/* protocol buffer. Each protocol field is expressed using this struct*/ -+/* Have a look at the protocol buffers to see how the struct gets */ -+/* initialized. */ -+/* */ -+/* name: */ -+/* This member expresses the name of the field, ending */ -+/* in its own Lua function to access the field. */ -+/* offset / length: */ -+/* These members do specify the position inside the protocol header */ -+/* in bits (not bytes!). */ -+/* get / set: */ -+/* The get and set functions take a function pointer pointing to the*/ -+/* specific getter and setter function for this field. */ -+/**********************************************************************/ -+struct protocol_field { -+ const char * name; -+ uint32_t offset; -+ uint32_t length; -+ lua_CFunction get; -+ lua_CFunction set; -+}; -+#define PROT_FIELD_SENTINEL { NULL, 0, 0, NULL, NULL } -+ -+ -+/**********************************************************************/ -+/* protocol_buf */ -+/**********************************************************************/ -+/* This structure is a container for all the information needed for a -+ * protocol buffer. It gets initialized in each protocol buffer header -+ * file or for the dynamic protocol buffers on runtime using the -+ * 'register_dynamic_protocol_buffer' function. -+ * -+ * name: -+ * This member is used throughout the system. It is also exported -+ * to Lua as a variable name holding the index of the 'supported_protocols' -+ * array. The name is also used as the name of the generated Lua -+ * metatable, that is why inside the macro checkpacketseg_ it -+ * is always the name of a protocol buffer that is passed as the -+ * second parameter. -+ * payload_field: -+ * This member holds the string of the field responsible for payload -+ * data. The payload field of a protocol has an extra property, since -+ * it can be used to invoke another protocol buffer that is applied to -+ * the payload content. -+ * has_protocol: -+ * This member is used together with the payload_field. Since we must -+ * be sure that the payload content does really contain a protocol -+ * of type X. The function pointed to by has_protocol checks if the -+ * protocol buffer X can be applied on the payload_data. -+ * protocol_fields: -+ * This member points to the array of 'protocol_field' structures -+ * get_field_changes: -+ * This member is optional. It is used to return a pointer to an initialized -+ * field_changes struct. The function is called, whenever the payload field -+ * is requested with a given protocol type. Usually this function will -+ * initialize the field_changes struct depending on the content of the -+ * payload data. e.g. -+ * tcp = ip:data(packet_tcp) -+ * such a request will call the 'get_field_changes' function of the tcp -+ * protocol buffer. This enables, that the tcp options field have the proper -+ * length as well as the tcp data start at the right offset. -+ */ -+struct protocol_buf { -+ int is_dynamic; -+ const char * name; -+ char * payload_field; -+ int (*has_protocol)(lua_State *L, struct protocol_buf *prot_buf, lua_packet_segment * seg, int type); -+ struct protocol_field * protocol_fields; -+ struct field_changes * (*get_field_changes)(lua_State *L, lua_packet_segment * seg); -+}; -+ -+/**********************************************************************/ -+/* lua byte array library */ -+/**********************************************************************/ -+#define LUA_BYTE_ARRAY "byte_array" -+#define checkbytearray(L, i) \ -+ (lua_packet_segment *)luaL_checkudata(L, i, LUA_BYTE_ARRAY) -+lua_packet_segment * init_byte_array(lua_State *L, unsigned char * start, int length, int do_copy); -+void luaopen_bytearraylib(lua_State *L); -+ -+ -+/**********************************************************************/ -+/* lua netfilter environment library */ -+/**********************************************************************/ -+#define NETFILTER_LIB "nf" -+#if defined(__KERNEL__) -+ struct lua_env { -+ lua_State *L; -+ /* perhaps more to come here (e.g. a state per CPU) */ -+ }; -+ #define LUA_ENV "lua_env" -+ #define checkluaenv(L, i) \ -+ (struct lua_env *)luaL_checkudata(L, i, LUA_ENV) -+ -+ void luaopen_nflib(lua_State *L); -+#endif -+ -+void cleanup_dynamic_prot_bufs(void); /* freeing all dynamic prot bufs */ -+/**********************************************************************/ -+/* lua protbuf helpers */ -+/**********************************************************************/ -+int get_1_bit_generic(lua_State *L); -+int set_1_bit_generic(lua_State *L); -+int get_lower_4_bit_generic(lua_State *L); -+int set_lower_4_bit_generic(lua_State *L); -+int get_upper_4_bit_generic(lua_State *L); -+int set_upper_4_bit_generic(lua_State *L); -+int get_8_bit_generic(lua_State *L); -+int set_8_bit_generic(lua_State *L); -+int get_16_bit_generic(lua_State *L); -+int set_16_bit_generic(lua_State *L); -+int get_32_bit_generic(lua_State *L); -+int set_32_bit_generic(lua_State *L); -+int set_data_generic(lua_State *L); -+int get_string_generic(lua_State *L); -+int get_byte_generic_str(lua_State *L); -+struct field_changes * get_allocated_field_changes(lua_State *L, int nr_of_fields); -+ -+/* only used by the dynamic prot buf subsystem */ -+#define MAX_NR_OF_DYN_PROT_BUFS 16 -+int field_dynamic_setter(lua_State *L); -+int field_dynamic_getter(lua_State *L); -+int has_protocol_dynamic(lua_State *L, struct protocol_buf * prot_buf, lua_packet_segment * seg, int type); -+struct field_changes * get_field_changes_dynamic(lua_State *L, struct protocol_buf *prot_buf, lua_packet_segment * seg); -+ -+/**********************************************************************/ -+/* lua controller API */ -+/**********************************************************************/ -+void luaopen_controller(lua_State *L); -+struct protocol_buf * get_protocol_buf(unsigned int protocol_id); -+void get_metatable_from_protocol_type(lua_State *L, int type); -+void register_protbuf(lua_State *L, struct protocol_buf * prot_buf, unsigned int protocol_index); -+ -+ -+#endif /* CONTROLLER_H_ */ ---- /dev/null -+++ b/extensions/LUA/Kbuild -@@ -0,0 +1,49 @@ -+# -*- Makefile -*- -+ -+# Adding debug options -+EXTRA_CFLAGS += -DDEBUG -+ -+obj-m += xt_LUA.o -+ -+EXTRA_CFLAGS += -I$(src)/prot_buf_new -+xt_LUA-y += xt_LUA_target.o \ -+ -+xt_LUA-y += nf_lua.o \ -+ prot_buf_helpers.o \ -+ byte_array.o \ -+ controller.o \ -+ prot_buf_ethernet.o \ -+ prot_buf_icmp.o \ -+ prot_buf_ip.o \ -+ prot_buf_raw.o \ -+ prot_buf_tcp.o \ -+ prot_buf_udp.o \ -+ prot_buf_tftp.o \ -+ prot_buf_dynamic.o \ -+ -+ -+# Adding Lua Support -+EXTRA_CFLAGS += -I$(src)/lua -I$(src)/lua/include -+xt_LUA-y += lua/lapi.o \ -+ lua/lbaselib.o \ -+ lua/lcode.o \ -+ lua/ldebug.o \ -+ lua/ldo.o \ -+ lua/ldump.o \ -+ lua/lfunc.o \ -+ lua/lgc.o \ -+ lua/llex.o \ -+ lua/lmem.o \ -+ lua/lobject.o \ -+ lua/lopcodes.o \ -+ lua/lparser.o \ -+ lua/lstate.o \ -+ lua/lstring.o \ -+ lua/lstrlib.o \ -+ lua/ltable.o \ -+ lua/ltablib.o \ -+ lua/ltm.o \ -+ lua/lundump.o \ -+ lua/lvm.o \ -+ lua/lzio.o \ -+ lua/lauxlib.o \ ---- /dev/null -+++ b/extensions/LUA/libxt_LUA.c -@@ -0,0 +1,191 @@ -+/* -+ * Copyright (C) 2010 University of Basel -+ * by Andre Graf -+ * -+ * This program 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. -+ * -+ * 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. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, see . -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "xt_LUA.h" -+ -+enum { -+ FLAG_SCRIPT = 1 << 0, -+ FLAG_STATE = 1 << 1, -+ FLAG_FUNCTION = 1 << 2, -+}; -+ -+static const struct option lua_tg_opts[] = { -+ { .name = "script", .has_arg = true, .val = 's' }, -+ { .name = "state", .has_arg = true, .val = 'l' }, -+ { .name = "function", .has_arg = true, .val = 'f' }, -+ { NULL }, -+}; -+ -+ -+static void lua_tg_help(void) -+{ -+ printf( -+ "LUA target options:\n" -+ " --script SCRIPT Process packet with the Lua script given by SCRIPT\n" -+ " \n" -+ " --state ID Process packet within the Lua state given by ID.\n" -+ " Omitting --state infers the ID 0, which can be\n" -+ " refered to the 'global' state.\n" -+ " \n" -+ " --function FUNCTION Name of the function that processes the Lua packet\n" -+ "\n"); -+} -+ -+static void -+lua_tg_init(struct xt_entry_target *target) -+{ -+ struct xt_lua_tginfo *info = (void *)target->data; -+ -+ info->state_id = 0; -+ strncpy(info->function, "process_packet\0", sizeof("process_packet\0")); -+} -+ -+static int -+lua_tg_parse(int32_t c, char **argv, int32_t invert, uint32_t *flags, -+ const void *entry, struct xt_entry_target **target) -+{ -+ struct xt_lua_tginfo *info = (void *)(*target)->data; -+ char buf[MAX_SCRIPT_SIZE]; -+ long script_size; -+ uint32_t state_id; -+ FILE *file; -+ -+ switch (c) { -+ case 's': -+ if (*flags & FLAG_SCRIPT) -+ xtables_error(PARAMETER_PROBLEM, -+ "LUA: Cannot specify --script more than once"); -+ -+ if (strlen(optarg) > sizeof(info->filename)) -+ xtables_error(PARAMETER_PROBLEM, -+ "LUA: Maximum script length is %zu", -+ sizeof(info->filename)); -+ -+ if (strchr(optarg, '\n')) -+ xtables_error(PARAMETER_PROBLEM, -+ "LUA: Newlines not allowed in script name"); -+ file = fopen(optarg, "rb"); -+ if (file != NULL) { -+ fseek(file, 0, SEEK_END); -+ script_size = ftell(file); -+ if (script_size > MAX_SCRIPT_SIZE) -+ xtables_error(PARAMETER_PROBLEM, -+ "LUA: The size of the script is too big"); -+ -+ fseek(file, 0, SEEK_SET); -+ fread(buf, script_size, 1, file); -+ fclose(file); -+ } else -+ xtables_error(PARAMETER_PROBLEM, -+ "LUA: Cannot open script %s", optarg); -+ -+ strncpy(info->filename, optarg, sizeof(info->filename)); -+ strncpy(info->buf, buf, sizeof(info->buf)); -+ info->script_size = script_size; -+ -+ *flags |= FLAG_SCRIPT; -+ return true; -+ -+ case 'l': -+ if (*flags & FLAG_STATE) -+ xtables_error(PARAMETER_PROBLEM, -+ "LUA: Cannot specify --state more than once"); -+ -+ if (!xtables_strtoui(optarg, NULL, &state_id, 0, 8)) -+ xtables_error(PARAMETER_PROBLEM, -+ "LUA: Invalid --state %s", optarg); -+ -+ info->state_id = state_id; -+ *flags |= FLAG_STATE; -+ return true; -+ -+ case 'f': -+ if (*flags & FLAG_FUNCTION) -+ xtables_error(PARAMETER_PROBLEM, -+ "LUA: Cannot specify --function more than once"); -+ if (strlen(optarg) > sizeof(info->function)) -+ xtables_error(PARAMETER_PROBLEM, -+ "LUA: Maximum function length is %zu", -+ sizeof(info->function)); -+ -+ if (strchr(optarg, '\n')) -+ xtables_error(PARAMETER_PROBLEM, -+ "LUA: Newlines not allowed in function name"); -+ -+ strncpy(info->function, optarg, sizeof(info->function)); -+ -+ *flags |= FLAG_FUNCTION; -+ return true; -+ } -+ -+ return false; -+} -+ -+static void -+lua_tg_check(uint32_t flags) -+{ -+ if (flags == 0) -+ xtables_error(PARAMETER_PROBLEM, "LUA: --script parameter required"); -+} -+ -+static void -+lua_tg_print(const void *entry, const struct xt_entry_target *target, -+ int32_t numeric) -+{ -+ const struct xt_lua_tginfo *info = (const void *)target->data; -+ -+ printf("LUA script: %s ", info->filename); -+} -+ -+static void -+lua_tg_save(const void *entry, const struct xt_entry_target *target) -+{ -+ const struct xt_lua_tginfo *info = (const void *)target->data; -+ -+ printf("--script %s ", info->filename); -+} -+ -+static struct xtables_target lua_tg_reg = { -+ .name = "LUA", -+ .version = XTABLES_VERSION, -+ .revision = 0, -+ .family = NFPROTO_UNSPEC, -+ .size = XT_ALIGN(sizeof(struct xt_lua_tginfo)), -+ .userspacesize = XT_ALIGN(sizeof(struct xt_lua_tginfo)), -+ .help = lua_tg_help, -+ .init = lua_tg_init, -+ .parse = lua_tg_parse, -+ .final_check = lua_tg_check, -+ .print = lua_tg_print, -+ .save = lua_tg_save, -+ .extra_opts = lua_tg_opts, -+}; -+ -+static __attribute__((constructor)) void lua_tg_ldr(void) -+{ -+ xtables_register_target(&lua_tg_reg); -+} -+ ---- /dev/null -+++ b/extensions/LUA/libxt_LUA.man -@@ -0,0 +1 @@ -+Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. ---- /dev/null -+++ b/extensions/LUA/lua/include/ctype.h -@@ -0,0 +1,11 @@ -+#include -+#undef isalnum -+#define isalnum(c) (((__ismask(c)&(_U|_L|_D)) != 0) && (c > 0)) -+#undef isalpha -+#define isalpha(c) (((__ismask(c)&(_U|_L)) != 0) && (c > 0)) -+#undef iscntrl -+#define iscntrl(c) (((__ismask(c)&(_C)) != 0) && (c > 0)) -+#undef isdigit -+#define isdigit(c) (((__ismask(c)&(_D)) != 0) && (c > 0)) -+#undef isspace -+#define isspace(c) (((__ismask(c)&(_S)) != 0) && (c > 0)) ---- /dev/null -+++ b/extensions/LUA/lua/include/errno.h -@@ -0,0 +1 @@ -+#include ---- /dev/null -+++ b/extensions/LUA/lua/include/locale.h -@@ -0,0 +1,5 @@ -+struct lconv { -+ char * decimal_point ; -+} ; -+ -+#define localeconv() NULL ---- /dev/null -+++ b/extensions/LUA/lua/include/setjmp.h -@@ -0,0 +1,26 @@ -+/* -+ * arch/um/include/sysdep-i386/archsetjmp.h -+ */ -+ -+#ifndef _KLIBC_ARCHSETJMP_H -+#define _KLIBC_ARCHSETJMP_H -+ -+struct __jmp_buf { -+ unsigned int __ebx; -+ unsigned int __esp; -+ unsigned int __ebp; -+ unsigned int __esi; -+ unsigned int __edi; -+ unsigned int __eip; -+}; -+ -+typedef struct __jmp_buf jmp_buf[1]; -+ -+#define JB_IP __eip -+#define JB_SP __esp -+ -+int setjmp(jmp_buf); -+void longjmp(jmp_buf, int); -+ -+#endif /* _SETJMP_H */ -+ ---- /dev/null -+++ b/extensions/LUA/lua/include/stdio.h -@@ -0,0 +1 @@ -+#include ---- /dev/null -+++ b/extensions/LUA/lua/include/stdlib.h -@@ -0,0 +1,7 @@ -+#include -+ -+#define exit(E) return -+#define strtoul simple_strtoul -+#define strcoll strcmp -+ -+#define CHAR_BIT 8 ---- /dev/null -+++ b/extensions/LUA/lua/include/string.h -@@ -0,0 +1 @@ -+#include ---- /dev/null -+++ b/extensions/LUA/lua/lapi.c -@@ -0,0 +1,1086 @@ -+/* -+** $Id: lapi.c,v 2.55.1.5 2008/07/04 18:41:18 roberto Exp $ -+** Lua API -+** See Copyright Notice in lua.h -+*/ -+ -+#include -+#include -+#include -+#include -+ -+#define lapi_c -+#define LUA_CORE -+ -+#include "lua.h" -+ -+#include "lapi.h" -+#include "ldebug.h" -+#include "ldo.h" -+#include "lfunc.h" -+#include "lgc.h" -+#include "lmem.h" -+#include "lobject.h" -+#include "lstate.h" -+#include "lstring.h" -+#include "ltable.h" -+#include "ltm.h" -+#include "lundump.h" -+#include "lvm.h" -+ -+ -+ -+const char lua_ident[] = -+ "$Lua: " LUA_RELEASE " " LUA_COPYRIGHT " $\n" -+ "$Authors: " LUA_AUTHORS " $\n" -+ "$URL: www.lua.org $\n"; -+ -+ -+ -+#define api_checknelems(L, n) api_check(L, (n) <= (L->top - L->base)) -+ -+#define api_checkvalidindex(L, i) api_check(L, (i) != luaO_nilobject) -+ -+#define api_incr_top(L) {api_check(L, L->top < L->ci->top); L->top++;} -+ -+ -+ -+static TValue *index2adr (lua_State *L, int idx) { -+ if (idx > 0) { -+ TValue *o = L->base + (idx - 1); -+ api_check(L, idx <= L->ci->top - L->base); -+ if (o >= L->top) return cast(TValue *, luaO_nilobject); -+ else return o; -+ } -+ else if (idx > LUA_REGISTRYINDEX) { -+ api_check(L, idx != 0 && -idx <= L->top - L->base); -+ return L->top + idx; -+ } -+ else switch (idx) { /* pseudo-indices */ -+ case LUA_REGISTRYINDEX: return registry(L); -+ case LUA_ENVIRONINDEX: { -+ Closure *func = curr_func(L); -+ sethvalue(L, &L->env, func->c.env); -+ return &L->env; -+ } -+ case LUA_GLOBALSINDEX: return gt(L); -+ default: { -+ Closure *func = curr_func(L); -+ idx = LUA_GLOBALSINDEX - idx; -+ return (idx <= func->c.nupvalues) -+ ? &func->c.upvalue[idx-1] -+ : cast(TValue *, luaO_nilobject); -+ } -+ } -+} -+ -+ -+static Table *getcurrenv (lua_State *L) { -+ if (L->ci == L->base_ci) /* no enclosing function? */ -+ return hvalue(gt(L)); /* use global table as environment */ -+ else { -+ Closure *func = curr_func(L); -+ return func->c.env; -+ } -+} -+ -+ -+void luaA_pushobject (lua_State *L, const TValue *o) { -+ setobj2s(L, L->top, o); -+ api_incr_top(L); -+} -+ -+ -+LUA_API int lua_checkstack (lua_State *L, int size) { -+ int res = 1; -+ lua_lock(L); -+ if (size > LUAI_MAXCSTACK || (L->top - L->base + size) > LUAI_MAXCSTACK) -+ res = 0; /* stack overflow */ -+ else if (size > 0) { -+ luaD_checkstack(L, size); -+ if (L->ci->top < L->top + size) -+ L->ci->top = L->top + size; -+ } -+ lua_unlock(L); -+ return res; -+} -+ -+ -+LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) { -+ int i; -+ if (from == to) return; -+ lua_lock(to); -+ api_checknelems(from, n); -+ api_check(from, G(from) == G(to)); -+ api_check(from, to->ci->top - to->top >= n); -+ from->top -= n; -+ for (i = 0; i < n; i++) { -+ setobj2s(to, to->top++, from->top + i); -+ } -+ lua_unlock(to); -+} -+ -+ -+LUA_API void lua_setlevel (lua_State *from, lua_State *to) { -+ to->nCcalls = from->nCcalls; -+} -+ -+ -+LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) { -+ lua_CFunction old; -+ lua_lock(L); -+ old = G(L)->panic; -+ G(L)->panic = panicf; -+ lua_unlock(L); -+ return old; -+} -+ -+ -+LUA_API lua_State *lua_newthread (lua_State *L) { -+ lua_State *L1; -+ lua_lock(L); -+ luaC_checkGC(L); -+ L1 = luaE_newthread(L); -+ setthvalue(L, L->top, L1); -+ api_incr_top(L); -+ lua_unlock(L); -+ luai_userstatethread(L, L1); -+ return L1; -+} -+ -+ -+ -+/* -+** basic stack manipulation -+*/ -+ -+ -+LUA_API int lua_gettop (lua_State *L) { -+ return cast_int(L->top - L->base); -+} -+ -+ -+LUA_API void lua_settop (lua_State *L, int idx) { -+ lua_lock(L); -+ if (idx >= 0) { -+ api_check(L, idx <= L->stack_last - L->base); -+ while (L->top < L->base + idx) -+ setnilvalue(L->top++); -+ L->top = L->base + idx; -+ } -+ else { -+ api_check(L, -(idx+1) <= (L->top - L->base)); -+ L->top += idx+1; /* `subtract' index (index is negative) */ -+ } -+ lua_unlock(L); -+} -+ -+ -+LUA_API void lua_remove (lua_State *L, int idx) { -+ StkId p; -+ lua_lock(L); -+ p = index2adr(L, idx); -+ api_checkvalidindex(L, p); -+ while (++p < L->top) setobjs2s(L, p-1, p); -+ L->top--; -+ lua_unlock(L); -+} -+ -+ -+LUA_API void lua_insert (lua_State *L, int idx) { -+ StkId p; -+ StkId q; -+ lua_lock(L); -+ p = index2adr(L, idx); -+ api_checkvalidindex(L, p); -+ for (q = L->top; q>p; q--) setobjs2s(L, q, q-1); -+ setobjs2s(L, p, L->top); -+ lua_unlock(L); -+} -+ -+ -+LUA_API void lua_replace (lua_State *L, int idx) { -+ StkId o; -+ lua_lock(L); -+ /* explicit test for incompatible code */ -+ if (idx == LUA_ENVIRONINDEX && L->ci == L->base_ci) -+ luaG_runerror(L, "no calling environment"); -+ api_checknelems(L, 1); -+ o = index2adr(L, idx); -+ api_checkvalidindex(L, o); -+ if (idx == LUA_ENVIRONINDEX) { -+ Closure *func = curr_func(L); -+ api_check(L, ttistable(L->top - 1)); -+ func->c.env = hvalue(L->top - 1); -+ luaC_barrier(L, func, L->top - 1); -+ } -+ else { -+ setobj(L, o, L->top - 1); -+ if (idx < LUA_GLOBALSINDEX) /* function upvalue? */ -+ luaC_barrier(L, curr_func(L), L->top - 1); -+ } -+ L->top--; -+ lua_unlock(L); -+} -+ -+ -+LUA_API void lua_pushvalue (lua_State *L, int idx) { -+ lua_lock(L); -+ setobj2s(L, L->top, index2adr(L, idx)); -+ api_incr_top(L); -+ lua_unlock(L); -+} -+ -+ -+ -+/* -+** access functions (stack -> C) -+*/ -+ -+ -+LUA_API int lua_type (lua_State *L, int idx) { -+ StkId o = index2adr(L, idx); -+ return (o == luaO_nilobject) ? LUA_TNONE : ttype(o); -+} -+ -+ -+LUA_API const char *lua_typename (lua_State *L, int t) { -+ UNUSED(L); -+ return (t == LUA_TNONE) ? "no value" : luaT_typenames[t]; -+} -+ -+ -+LUA_API int lua_iscfunction (lua_State *L, int idx) { -+ StkId o = index2adr(L, idx); -+ return iscfunction(o); -+} -+ -+ -+LUA_API int lua_isnumber (lua_State *L, int idx) { -+ TValue n; -+ const TValue *o = index2adr(L, idx); -+ return tonumber(o, &n); -+} -+ -+ -+LUA_API int lua_isstring (lua_State *L, int idx) { -+ int t = lua_type(L, idx); -+ return (t == LUA_TSTRING || t == LUA_TNUMBER); -+} -+ -+ -+LUA_API int lua_isuserdata (lua_State *L, int idx) { -+ const TValue *o = index2adr(L, idx); -+ return (ttisuserdata(o) || ttislightuserdata(o)); -+} -+ -+ -+LUA_API int lua_rawequal (lua_State *L, int index1, int index2) { -+ StkId o1 = index2adr(L, index1); -+ StkId o2 = index2adr(L, index2); -+ return (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 -+ : luaO_rawequalObj(o1, o2); -+} -+ -+ -+LUA_API int lua_equal (lua_State *L, int index1, int index2) { -+ StkId o1, o2; -+ int i; -+ lua_lock(L); /* may call tag method */ -+ o1 = index2adr(L, index1); -+ o2 = index2adr(L, index2); -+ i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 : equalobj(L, o1, o2); -+ lua_unlock(L); -+ return i; -+} -+ -+ -+LUA_API int lua_lessthan (lua_State *L, int index1, int index2) { -+ StkId o1, o2; -+ int i; -+ lua_lock(L); /* may call tag method */ -+ o1 = index2adr(L, index1); -+ o2 = index2adr(L, index2); -+ i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 -+ : luaV_lessthan(L, o1, o2); -+ lua_unlock(L); -+ return i; -+} -+ -+ -+ -+LUA_API lua_Number lua_tonumber (lua_State *L, int idx) { -+ TValue n; -+ const TValue *o = index2adr(L, idx); -+ if (tonumber(o, &n)) -+ return nvalue(o); -+ else -+ return 0; -+} -+ -+ -+LUA_API lua_Integer lua_tointeger (lua_State *L, int idx) { -+ TValue n; -+ const TValue *o = index2adr(L, idx); -+ if (tonumber(o, &n)) { -+ lua_Integer res; -+ lua_Number num = nvalue(o); -+ lua_number2integer(res, num); -+ return res; -+ } -+ else -+ return 0; -+} -+ -+ -+LUA_API int lua_toboolean (lua_State *L, int idx) { -+ const TValue *o = index2adr(L, idx); -+ return !l_isfalse(o); -+} -+ -+ -+LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { -+ StkId o = index2adr(L, idx); -+ if (!ttisstring(o)) { -+ lua_lock(L); /* `luaV_tostring' may create a new string */ -+ if (!luaV_tostring(L, o)) { /* conversion failed? */ -+ if (len != NULL) *len = 0; -+ lua_unlock(L); -+ return NULL; -+ } -+ luaC_checkGC(L); -+ o = index2adr(L, idx); /* previous call may reallocate the stack */ -+ lua_unlock(L); -+ } -+ if (len != NULL) *len = tsvalue(o)->len; -+ return svalue(o); -+} -+ -+ -+LUA_API size_t lua_objlen (lua_State *L, int idx) { -+ StkId o = index2adr(L, idx); -+ switch (ttype(o)) { -+ case LUA_TSTRING: return tsvalue(o)->len; -+ case LUA_TUSERDATA: return uvalue(o)->len; -+ case LUA_TTABLE: return luaH_getn(hvalue(o)); -+ case LUA_TNUMBER: { -+ size_t l; -+ lua_lock(L); /* `luaV_tostring' may create a new string */ -+ l = (luaV_tostring(L, o) ? tsvalue(o)->len : 0); -+ lua_unlock(L); -+ return l; -+ } -+ default: return 0; -+ } -+} -+ -+ -+LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) { -+ StkId o = index2adr(L, idx); -+ return (!iscfunction(o)) ? NULL : clvalue(o)->c.f; -+} -+ -+ -+LUA_API void *lua_touserdata (lua_State *L, int idx) { -+ StkId o = index2adr(L, idx); -+ switch (ttype(o)) { -+ case LUA_TUSERDATA: return (rawuvalue(o) + 1); -+ case LUA_TLIGHTUSERDATA: return pvalue(o); -+ default: return NULL; -+ } -+} -+ -+ -+LUA_API lua_State *lua_tothread (lua_State *L, int idx) { -+ StkId o = index2adr(L, idx); -+ return (!ttisthread(o)) ? NULL : thvalue(o); -+} -+ -+ -+LUA_API const void *lua_topointer (lua_State *L, int idx) { -+ StkId o = index2adr(L, idx); -+ switch (ttype(o)) { -+ case LUA_TTABLE: return hvalue(o); -+ case LUA_TFUNCTION: return clvalue(o); -+ case LUA_TTHREAD: return thvalue(o); -+ case LUA_TUSERDATA: -+ case LUA_TLIGHTUSERDATA: -+ return lua_touserdata(L, idx); -+ default: return NULL; -+ } -+} -+ -+ -+ -+/* -+** push functions (C -> stack) -+*/ -+ -+ -+LUA_API void lua_pushnil (lua_State *L) { -+ lua_lock(L); -+ setnilvalue(L->top); -+ api_incr_top(L); -+ lua_unlock(L); -+} -+ -+ -+LUA_API void lua_pushnumber (lua_State *L, lua_Number n) { -+ lua_lock(L); -+ setnvalue(L->top, n); -+ api_incr_top(L); -+ lua_unlock(L); -+} -+ -+ -+LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) { -+ lua_lock(L); -+ setnvalue(L->top, cast_num(n)); -+ api_incr_top(L); -+ lua_unlock(L); -+} -+ -+ -+LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) { -+ lua_lock(L); -+ luaC_checkGC(L); -+ setsvalue2s(L, L->top, luaS_newlstr(L, s, len)); -+ api_incr_top(L); -+ lua_unlock(L); -+} -+ -+ -+LUA_API void lua_pushstring (lua_State *L, const char *s) { -+ if (s == NULL) -+ lua_pushnil(L); -+ else -+ lua_pushlstring(L, s, strlen(s)); -+} -+ -+ -+LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt, -+ va_list argp) { -+ const char *ret; -+ lua_lock(L); -+ luaC_checkGC(L); -+ ret = luaO_pushvfstring(L, fmt, argp); -+ lua_unlock(L); -+ return ret; -+} -+ -+ -+LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) { -+ const char *ret; -+ va_list argp; -+ lua_lock(L); -+ luaC_checkGC(L); -+ va_start(argp, fmt); -+ ret = luaO_pushvfstring(L, fmt, argp); -+ va_end(argp); -+ lua_unlock(L); -+ return ret; -+} -+ -+ -+LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { -+ Closure *cl; -+ lua_lock(L); -+ luaC_checkGC(L); -+ api_checknelems(L, n); -+ cl = luaF_newCclosure(L, n, getcurrenv(L)); -+ cl->c.f = fn; -+ L->top -= n; -+ while (n--) -+ setobj2n(L, &cl->c.upvalue[n], L->top+n); -+ setclvalue(L, L->top, cl); -+ lua_assert(iswhite(obj2gco(cl))); -+ api_incr_top(L); -+ lua_unlock(L); -+} -+ -+ -+LUA_API void lua_pushboolean (lua_State *L, int b) { -+ lua_lock(L); -+ setbvalue(L->top, (b != 0)); /* ensure that true is 1 */ -+ api_incr_top(L); -+ lua_unlock(L); -+} -+ -+ -+LUA_API void lua_pushlightuserdata (lua_State *L, void *p) { -+ lua_lock(L); -+ setpvalue(L->top, p); -+ api_incr_top(L); -+ lua_unlock(L); -+} -+ -+ -+LUA_API int lua_pushthread (lua_State *L) { -+ lua_lock(L); -+ setthvalue(L, L->top, L); -+ api_incr_top(L); -+ lua_unlock(L); -+ return (G(L)->mainthread == L); -+} -+ -+ -+ -+/* -+** get functions (Lua -> stack) -+*/ -+ -+ -+LUA_API void lua_gettable (lua_State *L, int idx) { -+ StkId t; -+ lua_lock(L); -+ t = index2adr(L, idx); -+ api_checkvalidindex(L, t); -+ luaV_gettable(L, t, L->top - 1, L->top - 1); -+ lua_unlock(L); -+} -+ -+ -+LUA_API void lua_getfield (lua_State *L, int idx, const char *k) { -+ StkId t; -+ TValue key; -+ lua_lock(L); -+ t = index2adr(L, idx); -+ api_checkvalidindex(L, t); -+ setsvalue(L, &key, luaS_new(L, k)); -+ luaV_gettable(L, t, &key, L->top); -+ api_incr_top(L); -+ lua_unlock(L); -+} -+ -+ -+LUA_API void lua_rawget (lua_State *L, int idx) { -+ StkId t; -+ lua_lock(L); -+ t = index2adr(L, idx); -+ api_check(L, ttistable(t)); -+ setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1)); -+ lua_unlock(L); -+} -+ -+ -+LUA_API void lua_rawgeti (lua_State *L, int idx, int n) { -+ StkId o; -+ lua_lock(L); -+ o = index2adr(L, idx); -+ api_check(L, ttistable(o)); -+ setobj2s(L, L->top, luaH_getnum(hvalue(o), n)); -+ api_incr_top(L); -+ lua_unlock(L); -+} -+ -+ -+LUA_API void lua_createtable (lua_State *L, int narray, int nrec) { -+ lua_lock(L); -+ luaC_checkGC(L); -+ sethvalue(L, L->top, luaH_new(L, narray, nrec)); -+ api_incr_top(L); -+ lua_unlock(L); -+} -+ -+ -+LUA_API int lua_getmetatable (lua_State *L, int objindex) { -+ const TValue *obj; -+ Table *mt = NULL; -+ int res; -+ lua_lock(L); -+ obj = index2adr(L, objindex); -+ switch (ttype(obj)) { -+ case LUA_TTABLE: -+ mt = hvalue(obj)->metatable; -+ break; -+ case LUA_TUSERDATA: -+ mt = uvalue(obj)->metatable; -+ break; -+ default: -+ mt = G(L)->mt[ttype(obj)]; -+ break; -+ } -+ if (mt == NULL) -+ res = 0; -+ else { -+ sethvalue(L, L->top, mt); -+ api_incr_top(L); -+ res = 1; -+ } -+ lua_unlock(L); -+ return res; -+} -+ -+ -+LUA_API void lua_getfenv (lua_State *L, int idx) { -+ StkId o; -+ lua_lock(L); -+ o = index2adr(L, idx); -+ api_checkvalidindex(L, o); -+ switch (ttype(o)) { -+ case LUA_TFUNCTION: -+ sethvalue(L, L->top, clvalue(o)->c.env); -+ break; -+ case LUA_TUSERDATA: -+ sethvalue(L, L->top, uvalue(o)->env); -+ break; -+ case LUA_TTHREAD: -+ setobj2s(L, L->top, gt(thvalue(o))); -+ break; -+ default: -+ setnilvalue(L->top); -+ break; -+ } -+ api_incr_top(L); -+ lua_unlock(L); -+} -+ -+ -+/* -+** set functions (stack -> Lua) -+*/ -+ -+ -+LUA_API void lua_settable (lua_State *L, int idx) { -+ StkId t; -+ lua_lock(L); -+ api_checknelems(L, 2); -+ t = index2adr(L, idx); -+ api_checkvalidindex(L, t); -+ luaV_settable(L, t, L->top - 2, L->top - 1); -+ L->top -= 2; /* pop index and value */ -+ lua_unlock(L); -+} -+ -+ -+LUA_API void lua_setfield (lua_State *L, int idx, const char *k) { -+ StkId t; -+ TValue key; -+ lua_lock(L); -+ api_checknelems(L, 1); -+ t = index2adr(L, idx); -+ api_checkvalidindex(L, t); -+ setsvalue(L, &key, luaS_new(L, k)); -+ luaV_settable(L, t, &key, L->top - 1); -+ L->top--; /* pop value */ -+ lua_unlock(L); -+} -+ -+ -+LUA_API void lua_rawset (lua_State *L, int idx) { -+ StkId t; -+ lua_lock(L); -+ api_checknelems(L, 2); -+ t = index2adr(L, idx); -+ api_check(L, ttistable(t)); -+ setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1); -+ luaC_barriert(L, hvalue(t), L->top-1); -+ L->top -= 2; -+ lua_unlock(L); -+} -+ -+ -+LUA_API void lua_rawseti (lua_State *L, int idx, int n) { -+ StkId o; -+ lua_lock(L); -+ api_checknelems(L, 1); -+ o = index2adr(L, idx); -+ api_check(L, ttistable(o)); -+ setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top-1); -+ luaC_barriert(L, hvalue(o), L->top-1); -+ L->top--; -+ lua_unlock(L); -+} -+ -+ -+LUA_API int lua_setmetatable (lua_State *L, int objindex) { -+ TValue *obj; -+ Table *mt; -+ lua_lock(L); -+ api_checknelems(L, 1); -+ obj = index2adr(L, objindex); -+ api_checkvalidindex(L, obj); -+ if (ttisnil(L->top - 1)) -+ mt = NULL; -+ else { -+ api_check(L, ttistable(L->top - 1)); -+ mt = hvalue(L->top - 1); -+ } -+ switch (ttype(obj)) { -+ case LUA_TTABLE: { -+ hvalue(obj)->metatable = mt; -+ if (mt) -+ luaC_objbarriert(L, hvalue(obj), mt); -+ break; -+ } -+ case LUA_TUSERDATA: { -+ uvalue(obj)->metatable = mt; -+ if (mt) -+ luaC_objbarrier(L, rawuvalue(obj), mt); -+ break; -+ } -+ default: { -+ G(L)->mt[ttype(obj)] = mt; -+ break; -+ } -+ } -+ L->top--; -+ lua_unlock(L); -+ return 1; -+} -+ -+ -+LUA_API int lua_setfenv (lua_State *L, int idx) { -+ StkId o; -+ int res = 1; -+ lua_lock(L); -+ api_checknelems(L, 1); -+ o = index2adr(L, idx); -+ api_checkvalidindex(L, o); -+ api_check(L, ttistable(L->top - 1)); -+ switch (ttype(o)) { -+ case LUA_TFUNCTION: -+ clvalue(o)->c.env = hvalue(L->top - 1); -+ break; -+ case LUA_TUSERDATA: -+ uvalue(o)->env = hvalue(L->top - 1); -+ break; -+ case LUA_TTHREAD: -+ sethvalue(L, gt(thvalue(o)), hvalue(L->top - 1)); -+ break; -+ default: -+ res = 0; -+ break; -+ } -+ if (res) luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1)); -+ L->top--; -+ lua_unlock(L); -+ return res; -+} -+ -+ -+/* -+** `load' and `call' functions (run Lua code) -+*/ -+ -+ -+#define adjustresults(L,nres) \ -+ { if (nres == LUA_MULTRET && L->top >= L->ci->top) L->ci->top = L->top; } -+ -+ -+#define checkresults(L,na,nr) \ -+ api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na))) -+ -+ -+LUA_API void lua_call (lua_State *L, int nargs, int nresults) { -+ StkId func; -+ lua_lock(L); -+ api_checknelems(L, nargs+1); -+ checkresults(L, nargs, nresults); -+ func = L->top - (nargs+1); -+ luaD_call(L, func, nresults); -+ adjustresults(L, nresults); -+ lua_unlock(L); -+} -+ -+ -+ -+/* -+** Execute a protected call. -+*/ -+struct CallS { /* data to `f_call' */ -+ StkId func; -+ int nresults; -+}; -+ -+ -+static void f_call (lua_State *L, void *ud) { -+ struct CallS *c = cast(struct CallS *, ud); -+ luaD_call(L, c->func, c->nresults); -+} -+ -+ -+ -+LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc) { -+ struct CallS c; -+ int status; -+ ptrdiff_t func; -+ lua_lock(L); -+ api_checknelems(L, nargs+1); -+ checkresults(L, nargs, nresults); -+ if (errfunc == 0) -+ func = 0; -+ else { -+ StkId o = index2adr(L, errfunc); -+ api_checkvalidindex(L, o); -+ func = savestack(L, o); -+ } -+ c.func = L->top - (nargs+1); /* function to be called */ -+ c.nresults = nresults; -+ status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func); -+ adjustresults(L, nresults); -+ lua_unlock(L); -+ return status; -+} -+ -+ -+/* -+** Execute a protected C call. -+*/ -+struct CCallS { /* data to `f_Ccall' */ -+ lua_CFunction func; -+ void *ud; -+}; -+ -+ -+static void f_Ccall (lua_State *L, void *ud) { -+ struct CCallS *c = cast(struct CCallS *, ud); -+ Closure *cl; -+ cl = luaF_newCclosure(L, 0, getcurrenv(L)); -+ cl->c.f = c->func; -+ setclvalue(L, L->top, cl); /* push function */ -+ api_incr_top(L); -+ setpvalue(L->top, c->ud); /* push only argument */ -+ api_incr_top(L); -+ luaD_call(L, L->top - 2, 0); -+} -+ -+ -+LUA_API int lua_cpcall (lua_State *L, lua_CFunction func, void *ud) { -+ struct CCallS c; -+ int status; -+ lua_lock(L); -+ c.func = func; -+ c.ud = ud; -+ status = luaD_pcall(L, f_Ccall, &c, savestack(L, L->top), 0); -+ lua_unlock(L); -+ return status; -+} -+ -+ -+LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data, -+ const char *chunkname) { -+ ZIO z; -+ int status; -+ lua_lock(L); -+ if (!chunkname) chunkname = "?"; -+ luaZ_init(L, &z, reader, data); -+ status = luaD_protectedparser(L, &z, chunkname); -+ lua_unlock(L); -+ return status; -+} -+ -+ -+LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data) { -+ int status; -+ TValue *o; -+ lua_lock(L); -+ api_checknelems(L, 1); -+ o = L->top - 1; -+ if (isLfunction(o)) -+ status = luaU_dump(L, clvalue(o)->l.p, writer, data, 0); -+ else -+ status = 1; -+ lua_unlock(L); -+ return status; -+} -+ -+ -+LUA_API int lua_status (lua_State *L) { -+ return L->status; -+} -+ -+ -+/* -+** Garbage-collection function -+*/ -+ -+LUA_API int lua_gc (lua_State *L, int what, int data) { -+ int res = 0; -+ global_State *g; -+ lua_lock(L); -+ g = G(L); -+ switch (what) { -+ case LUA_GCSTOP: { -+ g->GCthreshold = MAX_LUMEM; -+ break; -+ } -+ case LUA_GCRESTART: { -+ g->GCthreshold = g->totalbytes; -+ break; -+ } -+ case LUA_GCCOLLECT: { -+ luaC_fullgc(L); -+ break; -+ } -+ case LUA_GCCOUNT: { -+ /* GC values are expressed in Kbytes: #bytes/2^10 */ -+ res = cast_int(g->totalbytes >> 10); -+ break; -+ } -+ case LUA_GCCOUNTB: { -+ res = cast_int(g->totalbytes & 0x3ff); -+ break; -+ } -+ case LUA_GCSTEP: { -+ lu_mem a = (cast(lu_mem, data) << 10); -+ if (a <= g->totalbytes) -+ g->GCthreshold = g->totalbytes - a; -+ else -+ g->GCthreshold = 0; -+ while (g->GCthreshold <= g->totalbytes) { -+ luaC_step(L); -+ if (g->gcstate == GCSpause) { /* end of cycle? */ -+ res = 1; /* signal it */ -+ break; -+ } -+ } -+ break; -+ } -+ case LUA_GCSETPAUSE: { -+ res = g->gcpause; -+ g->gcpause = data; -+ break; -+ } -+ case LUA_GCSETSTEPMUL: { -+ res = g->gcstepmul; -+ g->gcstepmul = data; -+ break; -+ } -+ default: res = -1; /* invalid option */ -+ } -+ lua_unlock(L); -+ return res; -+} -+ -+ -+ -+/* -+** miscellaneous functions -+*/ -+ -+ -+LUA_API int lua_error (lua_State *L) { -+ lua_lock(L); -+ api_checknelems(L, 1); -+ luaG_errormsg(L); -+ lua_unlock(L); -+ return 0; /* to avoid warnings */ -+} -+ -+ -+LUA_API int lua_next (lua_State *L, int idx) { -+ StkId t; -+ int more; -+ lua_lock(L); -+ t = index2adr(L, idx); -+ api_check(L, ttistable(t)); -+ more = luaH_next(L, hvalue(t), L->top - 1); -+ if (more) { -+ api_incr_top(L); -+ } -+ else /* no more elements */ -+ L->top -= 1; /* remove key */ -+ lua_unlock(L); -+ return more; -+} -+ -+ -+LUA_API void lua_concat (lua_State *L, int n) { -+ lua_lock(L); -+ api_checknelems(L, n); -+ if (n >= 2) { -+ luaC_checkGC(L); -+ luaV_concat(L, n, cast_int(L->top - L->base) - 1); -+ L->top -= (n-1); -+ } -+ else if (n == 0) { /* push empty string */ -+ setsvalue2s(L, L->top, luaS_newlstr(L, "", 0)); -+ api_incr_top(L); -+ } -+ /* else n == 1; nothing to do */ -+ lua_unlock(L); -+} -+ -+ -+LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) { -+ lua_Alloc f; -+ lua_lock(L); -+ if (ud) *ud = G(L)->ud; -+ f = G(L)->frealloc; -+ lua_unlock(L); -+ return f; -+} -+ -+ -+LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud) { -+ lua_lock(L); -+ G(L)->ud = ud; -+ G(L)->frealloc = f; -+ lua_unlock(L); -+} -+ -+ -+LUA_API void *lua_newuserdata (lua_State *L, size_t size) { -+ Udata *u; -+ lua_lock(L); -+ luaC_checkGC(L); -+ u = luaS_newudata(L, size, getcurrenv(L)); -+ setuvalue(L, L->top, u); -+ api_incr_top(L); -+ lua_unlock(L); -+ return u + 1; -+} -+ -+ -+ -+ -+static const char *aux_upvalue (StkId fi, int n, TValue **val) { -+ Closure *f; -+ if (!ttisfunction(fi)) return NULL; -+ f = clvalue(fi); -+ if (f->c.isC) { -+ if (!(1 <= n && n <= f->c.nupvalues)) return NULL; -+ *val = &f->c.upvalue[n-1]; -+ return ""; -+ } -+ else { -+ Proto *p = f->l.p; -+ if (!(1 <= n && n <= p->sizeupvalues)) return NULL; -+ *val = f->l.upvals[n-1]->v; -+ return getstr(p->upvalues[n-1]); -+ } -+} -+ -+ -+LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { -+ const char *name; -+ TValue *val; -+ lua_lock(L); -+ name = aux_upvalue(index2adr(L, funcindex), n, &val); -+ if (name) { -+ setobj2s(L, L->top, val); -+ api_incr_top(L); -+ } -+ lua_unlock(L); -+ return name; -+} -+ -+ -+LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { -+ const char *name; -+ TValue *val; -+ StkId fi; -+ lua_lock(L); -+ fi = index2adr(L, funcindex); -+ api_checknelems(L, 1); -+ name = aux_upvalue(fi, n, &val); -+ if (name) { -+ L->top--; -+ setobj(L, val, L->top); -+ luaC_barrier(L, clvalue(fi), L->top); -+ } -+ lua_unlock(L); -+ return name; -+} -+ ---- /dev/null -+++ b/extensions/LUA/lua/lapi.h -@@ -0,0 +1,16 @@ -+/* -+** $Id: lapi.h,v 2.2.1.1 2007/12/27 13:02:25 roberto Exp $ -+** Auxiliary functions from Lua API -+** See Copyright Notice in lua.h -+*/ -+ -+#ifndef lapi_h -+#define lapi_h -+ -+ -+#include "lobject.h" -+ -+ -+LUAI_FUNC void luaA_pushobject (lua_State *L, const TValue *o); -+ -+#endif ---- /dev/null -+++ b/extensions/LUA/lua/lauxlib.c -@@ -0,0 +1,674 @@ -+/* -+** $Id: lauxlib.c,v 1.159.1.3 2008/01/21 13:20:51 roberto Exp $ -+** Auxiliary functions for building Lua libraries -+** See Copyright Notice in lua.h -+*/ -+ -+#include -+ -+#if !defined(__KERNEL__) -+#include -+#include -+#include -+#include -+#include -+#else -+#include -+#include -+#include -+#include -+#include -+#endif -+ -+/* This file uses only the official API of Lua. -+** Any function declared here could be written as an application function. -+*/ -+ -+#define lauxlib_c -+#define LUA_LIB -+ -+#include "lua.h" -+ -+#include "lauxlib.h" -+ -+ -+#define FREELIST_REF 0 /* free list of references */ -+ -+ -+/* convert a stack index to positive */ -+#define abs_index(L, i) ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \ -+ lua_gettop(L) + (i) + 1) -+ -+ -+/* -+** {====================================================== -+** Error-report functions -+** ======================================================= -+*/ -+ -+ -+LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) { -+ lua_Debug ar; -+ if (!lua_getstack(L, 0, &ar)) /* no stack frame? */ -+ return luaL_error(L, "bad argument #%d (%s)", narg, extramsg); -+ lua_getinfo(L, "n", &ar); -+ if (strcmp(ar.namewhat, "method") == 0) { -+ narg--; /* do not count `self' */ -+ if (narg == 0) /* error is in the self argument itself? */ -+ return luaL_error(L, "calling " LUA_QS " on bad self (%s)", -+ ar.name, extramsg); -+ } -+ if (ar.name == NULL) -+ ar.name = "?"; -+ return luaL_error(L, "bad argument #%d to " LUA_QS " (%s)", -+ narg, ar.name, extramsg); -+} -+ -+ -+LUALIB_API int luaL_typerror (lua_State *L, int narg, const char *tname) { -+ const char *msg = lua_pushfstring(L, "%s expected, got %s", -+ tname, luaL_typename(L, narg)); -+ return luaL_argerror(L, narg, msg); -+} -+ -+ -+static void tag_error (lua_State *L, int narg, int tag) { -+ luaL_typerror(L, narg, lua_typename(L, tag)); -+} -+ -+ -+LUALIB_API void luaL_where (lua_State *L, int level) { -+ lua_Debug ar; -+ if (lua_getstack(L, level, &ar)) { /* check function at level */ -+ lua_getinfo(L, "Sl", &ar); /* get info about it */ -+ if (ar.currentline > 0) { /* is there info? */ -+ lua_pushfstring(L, "%s:%d: ", ar.short_src, ar.currentline); -+ return; -+ } -+ } -+ lua_pushliteral(L, ""); /* else, no information available... */ -+} -+ -+ -+LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) { -+ va_list argp; -+ va_start(argp, fmt); -+ luaL_where(L, 1); -+ lua_pushvfstring(L, fmt, argp); -+ va_end(argp); -+ lua_concat(L, 2); -+ return lua_error(L); -+} -+ -+/* }====================================================== */ -+ -+ -+LUALIB_API int luaL_checkoption (lua_State *L, int narg, const char *def, -+ const char *const lst[]) { -+ const char *name = (def) ? luaL_optstring(L, narg, def) : -+ luaL_checkstring(L, narg); -+ int i; -+ for (i=0; lst[i]; i++) -+ if (strcmp(lst[i], name) == 0) -+ return i; -+ return luaL_argerror(L, narg, -+ lua_pushfstring(L, "invalid option " LUA_QS, name)); -+} -+ -+ -+LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) { -+ lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get registry.name */ -+ if (!lua_isnil(L, -1)) /* name already in use? */ -+ return 0; /* leave previous value on top, but return 0 */ -+ lua_pop(L, 1); -+ lua_newtable(L); /* create metatable */ -+ lua_pushvalue(L, -1); -+ lua_setfield(L, LUA_REGISTRYINDEX, tname); /* registry.name = metatable */ -+ return 1; -+} -+ -+ -+LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) { -+ void *p = lua_touserdata(L, ud); -+ if (p != NULL) { /* value is a userdata? */ -+ if (lua_getmetatable(L, ud)) { /* does it have a metatable? */ -+ lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */ -+ if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */ -+ lua_pop(L, 2); /* remove both metatables */ -+ return p; -+ } -+ } -+ } -+ luaL_typerror(L, ud, tname); /* else error */ -+ return NULL; /* to avoid warnings */ -+} -+ -+ -+LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) { -+ if (!lua_checkstack(L, space)) -+ luaL_error(L, "stack overflow (%s)", mes); -+} -+ -+ -+LUALIB_API void luaL_checktype (lua_State *L, int narg, int t) { -+ if (lua_type(L, narg) != t) -+ tag_error(L, narg, t); -+} -+ -+ -+LUALIB_API void luaL_checkany (lua_State *L, int narg) { -+ if (lua_type(L, narg) == LUA_TNONE) -+ luaL_argerror(L, narg, "value expected"); -+} -+ -+ -+LUALIB_API const char *luaL_checklstring (lua_State *L, int narg, size_t *len) { -+ const char *s = lua_tolstring(L, narg, len); -+ if (!s) tag_error(L, narg, LUA_TSTRING); -+ return s; -+} -+ -+ -+LUALIB_API const char *luaL_optlstring (lua_State *L, int narg, -+ const char *def, size_t *len) { -+ if (lua_isnoneornil(L, narg)) { -+ if (len) -+ *len = (def ? strlen(def) : 0); -+ return def; -+ } -+ else return luaL_checklstring(L, narg, len); -+} -+ -+ -+LUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) { -+ lua_Number d = lua_tonumber(L, narg); -+ if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */ -+ tag_error(L, narg, LUA_TNUMBER); -+ return d; -+} -+ -+ -+LUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number def) { -+ return luaL_opt(L, luaL_checknumber, narg, def); -+} -+ -+ -+LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) { -+ lua_Integer d = lua_tointeger(L, narg); -+ if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */ -+ tag_error(L, narg, LUA_TNUMBER); -+ return d; -+} -+ -+ -+LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int narg, -+ lua_Integer def) { -+ return luaL_opt(L, luaL_checkinteger, narg, def); -+} -+ -+ -+LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) { -+ if (!lua_getmetatable(L, obj)) /* no metatable? */ -+ return 0; -+ lua_pushstring(L, event); -+ lua_rawget(L, -2); -+ if (lua_isnil(L, -1)) { -+ lua_pop(L, 2); /* remove metatable and metafield */ -+ return 0; -+ } -+ else { -+ lua_remove(L, -2); /* remove only metatable */ -+ return 1; -+ } -+} -+ -+ -+LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) { -+ obj = abs_index(L, obj); -+ if (!luaL_getmetafield(L, obj, event)) /* no metafield? */ -+ return 0; -+ lua_pushvalue(L, obj); -+ lua_call(L, 1, 1); -+ return 1; -+} -+ -+ -+LUALIB_API void (luaL_register) (lua_State *L, const char *libname, -+ const luaL_Reg *l) { -+ luaI_openlib(L, libname, l, 0); -+} -+ -+ -+static int libsize (const luaL_Reg *l) { -+ int size = 0; -+ for (; l->name; l++) size++; -+ return size; -+} -+ -+ -+LUALIB_API void luaI_openlib (lua_State *L, const char *libname, -+ const luaL_Reg *l, int nup) { -+ if (libname) { -+ int size = libsize(l); -+ /* check whether lib already exists */ -+ luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 1); -+ lua_getfield(L, -1, libname); /* get _LOADED[libname] */ -+ if (!lua_istable(L, -1)) { /* not found? */ -+ lua_pop(L, 1); /* remove previous result */ -+ /* try global variable (and create one if it does not exist) */ -+ if (luaL_findtable(L, LUA_GLOBALSINDEX, libname, size) != NULL) -+ luaL_error(L, "name conflict for module " LUA_QS, libname); -+ lua_pushvalue(L, -1); -+ lua_setfield(L, -3, libname); /* _LOADED[libname] = new table */ -+ } -+ lua_remove(L, -2); /* remove _LOADED table */ -+ lua_insert(L, -(nup+1)); /* move library table to below upvalues */ -+ } -+ for (; l->name; l++) { -+ int i; -+ for (i=0; ifunc, nup); -+ lua_setfield(L, -(nup+2), l->name); -+ } -+ lua_pop(L, nup); /* remove upvalues */ -+} -+ -+ -+ -+/* -+** {====================================================== -+** getn-setn: size for arrays -+** ======================================================= -+*/ -+ -+#if defined(LUA_COMPAT_GETN) -+ -+static int checkint (lua_State *L, int topop) { -+ int n = (lua_type(L, -1) == LUA_TNUMBER) ? lua_tointeger(L, -1) : -1; -+ lua_pop(L, topop); -+ return n; -+} -+ -+ -+static void getsizes (lua_State *L) { -+ lua_getfield(L, LUA_REGISTRYINDEX, "LUA_SIZES"); -+ if (lua_isnil(L, -1)) { /* no `size' table? */ -+ lua_pop(L, 1); /* remove nil */ -+ lua_newtable(L); /* create it */ -+ lua_pushvalue(L, -1); /* `size' will be its own metatable */ -+ lua_setmetatable(L, -2); -+ lua_pushliteral(L, "kv"); -+ lua_setfield(L, -2, "__mode"); /* metatable(N).__mode = "kv" */ -+ lua_pushvalue(L, -1); -+ lua_setfield(L, LUA_REGISTRYINDEX, "LUA_SIZES"); /* store in register */ -+ } -+} -+ -+ -+LUALIB_API void luaL_setn (lua_State *L, int t, int n) { -+ t = abs_index(L, t); -+ lua_pushliteral(L, "n"); -+ lua_rawget(L, t); -+ if (checkint(L, 1) >= 0) { /* is there a numeric field `n'? */ -+ lua_pushliteral(L, "n"); /* use it */ -+ lua_pushinteger(L, n); -+ lua_rawset(L, t); -+ } -+ else { /* use `sizes' */ -+ getsizes(L); -+ lua_pushvalue(L, t); -+ lua_pushinteger(L, n); -+ lua_rawset(L, -3); /* sizes[t] = n */ -+ lua_pop(L, 1); /* remove `sizes' */ -+ } -+} -+ -+ -+LUALIB_API int luaL_getn (lua_State *L, int t) { -+ int n; -+ t = abs_index(L, t); -+ lua_pushliteral(L, "n"); /* try t.n */ -+ lua_rawget(L, t); -+ if ((n = checkint(L, 1)) >= 0) return n; -+ getsizes(L); /* else try sizes[t] */ -+ lua_pushvalue(L, t); -+ lua_rawget(L, -2); -+ if ((n = checkint(L, 2)) >= 0) return n; -+ return (int)lua_objlen(L, t); -+} -+ -+#endif -+ -+/* }====================================================== */ -+ -+ -+ -+LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p, -+ const char *r) { -+ const char *wild; -+ size_t l = strlen(p); -+ luaL_Buffer *b = (luaL_Buffer *)kmalloc(sizeof(luaL_Buffer) + BUFSIZ, GFP_ATOMIC); -+ if(!b) luaL_error(L, "luaL_gsub: cannot allocate memory"); -+ luaL_buffinit(L, b); -+ while ((wild = strstr(s, p)) != NULL) { -+ luaL_addlstring(b, s, wild - s); /* push prefix */ -+ luaL_addstring(b, r); /* push replacement in place of pattern */ -+ s = wild + l; /* continue after `p' */ -+ } -+ luaL_addstring(b, s); /* push last suffix */ -+ luaL_pushresult(b); -+ kfree(b); -+ return lua_tostring(L, -1); -+} -+ -+ -+LUALIB_API const char *luaL_findtable (lua_State *L, int idx, -+ const char *fname, int szhint) { -+ const char *e; -+ lua_pushvalue(L, idx); -+ do { -+ e = strchr(fname, '.'); -+ if (e == NULL) e = fname + strlen(fname); -+ lua_pushlstring(L, fname, e - fname); -+ lua_rawget(L, -2); -+ if (lua_isnil(L, -1)) { /* no such field? */ -+ lua_pop(L, 1); /* remove this nil */ -+ lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */ -+ lua_pushlstring(L, fname, e - fname); -+ lua_pushvalue(L, -2); -+ lua_settable(L, -4); /* set new table into field */ -+ } -+ else if (!lua_istable(L, -1)) { /* field has a non-table value? */ -+ lua_pop(L, 2); /* remove table and value */ -+ return fname; /* return problematic part of the name */ -+ } -+ lua_remove(L, -2); /* remove previous table */ -+ fname = e + 1; -+ } while (*e == '.'); -+ return NULL; -+} -+ -+ -+ -+/* -+** {====================================================== -+** Generic Buffer manipulation -+** ======================================================= -+*/ -+ -+ -+#define bufflen(B) ((B)->p - (B)->buffer) -+#define bufffree(B) ((size_t)(LUAL_BUFFERSIZE - bufflen(B))) -+ -+#define LIMIT (LUA_MINSTACK/2) -+ -+ -+static int emptybuffer (luaL_Buffer *B) { -+ size_t l = bufflen(B); -+ if (l == 0) return 0; /* put nothing on stack */ -+ else { -+ lua_pushlstring(B->L, B->buffer, l); -+ B->p = B->buffer; -+ B->lvl++; -+ return 1; -+ } -+} -+ -+ -+static void adjuststack (luaL_Buffer *B) { -+ if (B->lvl > 1) { -+ lua_State *L = B->L; -+ int toget = 1; /* number of levels to concat */ -+ size_t toplen = lua_strlen(L, -1); -+ do { -+ size_t l = lua_strlen(L, -(toget+1)); -+ if (B->lvl - toget + 1 >= LIMIT || toplen > l) { -+ toplen += l; -+ toget++; -+ } -+ else break; -+ } while (toget < B->lvl); -+ lua_concat(L, toget); -+ B->lvl = B->lvl - toget + 1; -+ } -+} -+ -+ -+LUALIB_API char *luaL_prepbuffer (luaL_Buffer *B) { -+ if (emptybuffer(B)) -+ adjuststack(B); -+ return B->buffer; -+} -+ -+ -+LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) { -+ while (l--) -+ luaL_addchar(B, *s++); -+} -+ -+ -+LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) { -+ luaL_addlstring(B, s, strlen(s)); -+} -+ -+ -+LUALIB_API void luaL_pushresult (luaL_Buffer *B) { -+ emptybuffer(B); -+ lua_concat(B->L, B->lvl); -+ B->lvl = 1; -+} -+ -+ -+LUALIB_API void luaL_addvalue (luaL_Buffer *B) { -+ lua_State *L = B->L; -+ size_t vl; -+ const char *s = lua_tolstring(L, -1, &vl); -+ if (vl <= bufffree(B)) { /* fit into buffer? */ -+ memcpy(B->p, s, vl); /* put it there */ -+ B->p += vl; -+ lua_pop(L, 1); /* remove from stack */ -+ } -+ else { -+ if (emptybuffer(B)) -+ lua_insert(L, -2); /* put buffer before new value */ -+ B->lvl++; /* add new value into B stack */ -+ adjuststack(B); -+ } -+} -+ -+ -+LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) { -+ B->L = L; -+ B->p = B->buffer; -+ B->lvl = 0; -+} -+ -+/* }====================================================== */ -+ -+ -+LUALIB_API int luaL_ref (lua_State *L, int t) { -+ int ref; -+ t = abs_index(L, t); -+ if (lua_isnil(L, -1)) { -+ lua_pop(L, 1); /* remove from stack */ -+ return LUA_REFNIL; /* `nil' has a unique fixed reference */ -+ } -+ lua_rawgeti(L, t, FREELIST_REF); /* get first free element */ -+ ref = (int)lua_tointeger(L, -1); /* ref = t[FREELIST_REF] */ -+ lua_pop(L, 1); /* remove it from stack */ -+ if (ref != 0) { /* any free element? */ -+ lua_rawgeti(L, t, ref); /* remove it from list */ -+ lua_rawseti(L, t, FREELIST_REF); /* (t[FREELIST_REF] = t[ref]) */ -+ } -+ else { /* no free elements */ -+ ref = (int)lua_objlen(L, t); -+ ref++; /* create new reference */ -+ } -+ lua_rawseti(L, t, ref); -+ return ref; -+} -+ -+ -+LUALIB_API void luaL_unref (lua_State *L, int t, int ref) { -+ if (ref >= 0) { -+ t = abs_index(L, t); -+ lua_rawgeti(L, t, FREELIST_REF); -+ lua_rawseti(L, t, ref); /* t[ref] = t[FREELIST_REF] */ -+ lua_pushinteger(L, ref); -+ lua_rawseti(L, t, FREELIST_REF); /* t[FREELIST_REF] = ref */ -+ } -+} -+ -+ -+ -+/* -+** {====================================================== -+** Load functions -+** ======================================================= -+*/ -+ -+#if !defined(__KERNEL__) -+typedef struct LoadF { -+ int extraline; -+ FILE *f; -+ char buff[LUAL_BUFFERSIZE]; -+} LoadF; -+ -+ -+static const char *getF (lua_State *L, void *ud, size_t *size) { -+ LoadF *lf = (LoadF *)ud; -+ (void)L; -+ if (lf->extraline) { -+ lf->extraline = 0; -+ *size = 1; -+ return "\n"; -+ } -+ if (feof(lf->f)) return NULL; -+ *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f); -+ return (*size > 0) ? lf->buff : NULL; -+} -+ -+ -+static int errfile (lua_State *L, const char *what, int fnameindex) { -+ const char *serr = strerror(errno); -+ const char *filename = lua_tostring(L, fnameindex) + 1; -+ lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr); -+ lua_remove(L, fnameindex); -+ return LUA_ERRFILE; -+} -+ -+ -+LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) { -+ LoadF lf; -+ int status, readstatus; -+ int c; -+ int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */ -+ lf.extraline = 0; -+ if (filename == NULL) { -+ lua_pushliteral(L, "=stdin"); -+ lf.f = stdin; -+ } -+ else { -+ lua_pushfstring(L, "@%s", filename); -+ lf.f = fopen(filename, "r"); -+ if (lf.f == NULL) return errfile(L, "open", fnameindex); -+ } -+ c = getc(lf.f); -+ if (c == '#') { /* Unix exec. file? */ -+ lf.extraline = 1; -+ while ((c = getc(lf.f)) != EOF && c != '\n') ; /* skip first line */ -+ if (c == '\n') c = getc(lf.f); -+ } -+ if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */ -+ lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */ -+ if (lf.f == NULL) return errfile(L, "reopen", fnameindex); -+ /* skip eventual `#!...' */ -+ while ((c = getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) ; -+ lf.extraline = 0; -+ } -+ ungetc(c, lf.f); -+ status = lua_load(L, getF, &lf, lua_tostring(L, -1)); -+ readstatus = ferror(lf.f); -+ if (filename) fclose(lf.f); /* close file (even in case of errors) */ -+ if (readstatus) { -+ lua_settop(L, fnameindex); /* ignore results from `lua_load' */ -+ return errfile(L, "read", fnameindex); -+ } -+ lua_remove(L, fnameindex); -+ return status; -+} -+#endif -+ -+typedef struct LoadS { -+ const char *s; -+ size_t size; -+} LoadS; -+ -+ -+static const char *getS (lua_State *L, void *ud, size_t *size) { -+ LoadS *ls = (LoadS *)ud; -+ (void)L; -+ if (ls->size == 0) return NULL; -+ *size = ls->size; -+ ls->size = 0; -+ return ls->s; -+} -+ -+ -+LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size, -+ const char *name) { -+ LoadS ls; -+ ls.s = buff; -+ ls.size = size; -+ return lua_load(L, getS, &ls, name); -+} -+ -+ -+LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s) { -+ return luaL_loadbuffer(L, s, strlen(s), s); -+} -+ -+ -+ -+/* }====================================================== */ -+ -+ -+static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { -+ (void)ud; -+ (void)osize; -+ if (nsize == 0) { -+#if !defined(__KERNEL__) -+ free(ptr); -+#else -+ kfree(ptr); -+#endif -+ return NULL; -+ } -+ else -+#if !defined(__KERNEL__) -+ return realloc(ptr, nsize); -+#else -+ return krealloc(ptr, nsize, GFP_ATOMIC); -+#endif -+} -+ -+ -+static int lpanic (lua_State *L) { -+ (void)L; /* to avoid warnings */ -+#if !defined(__KERNEL__) -+ fprintf(stderr, "PANIC: unprotected error in call to Lua API (%s)\n", -+#else -+ printk( "PANIC: unprotected error in call to Lua API (%s)\n", -+#endif -+ lua_tostring(L, -1)); -+ return 0; -+} -+ -+ -+LUALIB_API lua_State *luaL_newstate (void) { -+ lua_State *L = lua_newstate(l_alloc, NULL); -+ if (L) lua_atpanic(L, &lpanic); -+ return L; -+} -+ ---- /dev/null -+++ b/extensions/LUA/lua/lauxlib.h -@@ -0,0 +1,184 @@ -+/* -+** $Id: lauxlib.h,v 1.88.1.1 2007/12/27 13:02:25 roberto Exp $ -+** Auxiliary functions for building Lua libraries -+** See Copyright Notice in lua.h -+*/ -+ -+ -+#ifndef lauxlib_h -+#define lauxlib_h -+ -+ -+#include -+#include /* for kmalloc and kfree when allocating luaL_Buffer */ -+ -+#if !defined(__KERNEL__) -+#include -+#endif -+ -+#include "lua.h" -+ -+ -+#if defined(LUA_COMPAT_GETN) -+LUALIB_API int (luaL_getn) (lua_State *L, int t); -+LUALIB_API void (luaL_setn) (lua_State *L, int t, int n); -+#else -+#define luaL_getn(L,i) ((int)lua_objlen(L, i)) -+#define luaL_setn(L,i,j) ((void)0) /* no op! */ -+#endif -+ -+#if defined(LUA_COMPAT_OPENLIB) -+#define luaI_openlib luaL_openlib -+#endif -+ -+ -+/* extra error code for `luaL_load' */ -+#define LUA_ERRFILE (LUA_ERRERR+1) -+ -+ -+typedef struct luaL_Reg { -+ const char *name; -+ lua_CFunction func; -+} luaL_Reg; -+ -+ -+ -+LUALIB_API void (luaI_openlib) (lua_State *L, const char *libname, -+ const luaL_Reg *l, int nup); -+LUALIB_API void (luaL_register) (lua_State *L, const char *libname, -+ const luaL_Reg *l); -+LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e); -+LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e); -+LUALIB_API int (luaL_typerror) (lua_State *L, int narg, const char *tname); -+LUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg); -+LUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg, -+ size_t *l); -+LUALIB_API const char *(luaL_optlstring) (lua_State *L, int numArg, -+ const char *def, size_t *l); -+LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int numArg); -+LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int nArg, lua_Number def); -+ -+LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg); -+LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg, -+ lua_Integer def); -+ -+LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg); -+LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t); -+LUALIB_API void (luaL_checkany) (lua_State *L, int narg); -+ -+LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname); -+LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname); -+ -+LUALIB_API void (luaL_where) (lua_State *L, int lvl); -+LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...); -+ -+LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def, -+ const char *const lst[]); -+ -+LUALIB_API int (luaL_ref) (lua_State *L, int t); -+LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref); -+ -+#if !defined(__KERNEL__) -+LUALIB_API int (luaL_loadfile) (lua_State *L, const char *filename); -+#endif -+ -+LUALIB_API int (luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz, -+ const char *name); -+LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s); -+ -+LUALIB_API lua_State *(luaL_newstate) (void); -+ -+ -+LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p, -+ const char *r); -+ -+LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx, -+ const char *fname, int szhint); -+ -+ -+ -+ -+/* -+** =============================================================== -+** some useful macros -+** =============================================================== -+*/ -+ -+#define luaL_argcheck(L, cond,numarg,extramsg) \ -+ ((void)((cond) || luaL_argerror(L, (numarg), (extramsg)))) -+#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) -+#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL)) -+#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n))) -+#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d))) -+#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n))) -+#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d))) -+ -+#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i))) -+ -+#if !defined(__KERNEL__) -+#define luaL_dofile(L, fn) \ -+ (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0)) -+#endif -+ -+#define luaL_dostring(L, s) \ -+ (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0)) -+ -+#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n))) -+ -+#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n))) -+ -+/* -+** {====================================================== -+** Generic Buffer manipulation -+** ======================================================= -+*/ -+ -+ -+ -+typedef struct luaL_Buffer { -+ char *p; /* current position in buffer */ -+ int lvl; /* number of strings in the stack (level) */ -+ lua_State *L; -+ char buffer[LUAL_BUFFERSIZE]; -+} luaL_Buffer; -+ -+#define luaL_addchar(B,c) \ -+ ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \ -+ (*(B)->p++ = (char)(c))) -+ -+/* compatibility only */ -+#define luaL_putchar(B,c) luaL_addchar(B,c) -+ -+#define luaL_addsize(B,n) ((B)->p += (n)) -+ -+ -+LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B); -+LUALIB_API char *(luaL_prepbuffer) (luaL_Buffer *B); -+LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); -+LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s); -+LUALIB_API void (luaL_addvalue) (luaL_Buffer *B); -+LUALIB_API void (luaL_pushresult) (luaL_Buffer *B); -+ -+ -+/* }====================================================== */ -+ -+ -+/* compatibility with ref system */ -+ -+/* pre-defined references */ -+#define LUA_NOREF (-2) -+#define LUA_REFNIL (-1) -+ -+#define lua_ref(L,lock) ((lock) ? luaL_ref(L, LUA_REGISTRYINDEX) : \ -+ (lua_pushstring(L, "unlocked references are obsolete"), lua_error(L), 0)) -+ -+#define lua_unref(L,ref) luaL_unref(L, LUA_REGISTRYINDEX, (ref)) -+ -+#define lua_getref(L,ref) lua_rawgeti(L, LUA_REGISTRYINDEX, (ref)) -+ -+ -+#define luaL_reg luaL_Reg -+ -+#endif -+ -+ ---- /dev/null -+++ b/extensions/LUA/lua/lbaselib.c -@@ -0,0 +1,647 @@ -+/* -+** $Id: lbaselib.c,v 1.191.1.6 2008/02/14 16:46:22 roberto Exp $ -+** Basic library -+** See Copyright Notice in lua.h -+*/ -+ -+ -+#include -+#include -+#include -+ -+#define lbaselib_c -+#define LUA_LIB -+ -+#include "lua.h" -+ -+#include "lauxlib.h" -+#include "lualib.h" -+ -+ -+ -+ -+/* -+** If your system does not support `stdout', you can just remove this function. -+** If you need, you can define your own `print' function, following this -+** model but changing `fputs' to put the strings at a proper place -+** (a console window or a log file, for instance). -+*/ -+static int luaB_print (lua_State *L) { -+ int n = lua_gettop(L); /* number of arguments */ -+ int i; -+ lua_getglobal(L, "tostring"); -+ for (i=1; i<=n; i++) { -+ const char *s; -+ lua_pushvalue(L, -1); /* function to be called */ -+ lua_pushvalue(L, i); /* value to print */ -+ lua_call(L, 1, 1); -+ s = lua_tostring(L, -1); /* get result */ -+ if (s == NULL) -+ return luaL_error(L, LUA_QL("tostring") " must return a string to " -+ LUA_QL("print")); -+ printk(KERN_INFO "LUA[print]: %s", s); -+ lua_pop(L, 1); /* pop result */ -+ } -+ return 0; -+} -+ -+ -+static int luaB_tonumber (lua_State *L) { -+ int base = luaL_optint(L, 2, 10); -+ if (base == 10) { /* standard conversion */ -+ luaL_checkany(L, 1); -+ if (lua_isnumber(L, 1)) { -+ lua_pushnumber(L, lua_tonumber(L, 1)); -+ return 1; -+ } -+ } -+ else { -+ const char *s1 = luaL_checkstring(L, 1); -+ char *s2; -+ unsigned long n; -+ luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); -+ n = simple_strtoul(s1, &s2, base); -+ if (s1 != s2) { /* at least one valid digit? */ -+ while (isspace((unsigned char)(*s2))) s2++; /* skip trailing spaces */ -+ if (*s2 == '\0') { /* no invalid trailing characters? */ -+ lua_pushnumber(L, (lua_Number)n); -+ return 1; -+ } -+ } -+ } -+ lua_pushnil(L); /* else not a number */ -+ return 1; -+} -+ -+ -+static int luaB_error (lua_State *L) { -+ int level = luaL_optint(L, 2, 1); -+ lua_settop(L, 1); -+ if (lua_isstring(L, 1) && level > 0) { /* add extra information? */ -+ luaL_where(L, level); -+ lua_pushvalue(L, 1); -+ lua_concat(L, 2); -+ } -+ return lua_error(L); -+} -+ -+ -+static int luaB_getmetatable (lua_State *L) { -+ luaL_checkany(L, 1); -+ if (!lua_getmetatable(L, 1)) { -+ lua_pushnil(L); -+ return 1; /* no metatable */ -+ } -+ luaL_getmetafield(L, 1, "__metatable"); -+ return 1; /* returns either __metatable field (if present) or metatable */ -+} -+ -+ -+static int luaB_setmetatable (lua_State *L) { -+ int t = lua_type(L, 2); -+ luaL_checktype(L, 1, LUA_TTABLE); -+ luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, -+ "nil or table expected"); -+ if (luaL_getmetafield(L, 1, "__metatable")) -+ luaL_error(L, "cannot change a protected metatable"); -+ lua_settop(L, 2); -+ lua_setmetatable(L, 1); -+ return 1; -+} -+ -+ -+static void getfunc (lua_State *L, int opt) { -+ if (lua_isfunction(L, 1)) lua_pushvalue(L, 1); -+ else { -+ lua_Debug ar; -+ int level = opt ? luaL_optint(L, 1, 1) : luaL_checkint(L, 1); -+ luaL_argcheck(L, level >= 0, 1, "level must be non-negative"); -+ if (lua_getstack(L, level, &ar) == 0) -+ luaL_argerror(L, 1, "invalid level"); -+ lua_getinfo(L, "f", &ar); -+ if (lua_isnil(L, -1)) -+ luaL_error(L, "no function environment for tail call at level %d", -+ level); -+ } -+} -+ -+ -+static int luaB_getfenv (lua_State *L) { -+ getfunc(L, 1); -+ if (lua_iscfunction(L, -1)) /* is a C function? */ -+ lua_pushvalue(L, LUA_GLOBALSINDEX); /* return the thread's global env. */ -+ else -+ lua_getfenv(L, -1); -+ return 1; -+} -+ -+ -+static int luaB_setfenv (lua_State *L) { -+ luaL_checktype(L, 2, LUA_TTABLE); -+ getfunc(L, 0); -+ lua_pushvalue(L, 2); -+ if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) { -+ /* change environment of current thread */ -+ lua_pushthread(L); -+ lua_insert(L, -2); -+ lua_setfenv(L, -2); -+ return 0; -+ } -+ else if (lua_iscfunction(L, -2) || lua_setfenv(L, -2) == 0) -+ luaL_error(L, -+ LUA_QL("setfenv") " cannot change environment of given object"); -+ return 1; -+} -+ -+ -+static int luaB_rawequal (lua_State *L) { -+ luaL_checkany(L, 1); -+ luaL_checkany(L, 2); -+ lua_pushboolean(L, lua_rawequal(L, 1, 2)); -+ return 1; -+} -+ -+ -+static int luaB_rawget (lua_State *L) { -+ luaL_checktype(L, 1, LUA_TTABLE); -+ luaL_checkany(L, 2); -+ lua_settop(L, 2); -+ lua_rawget(L, 1); -+ return 1; -+} -+ -+static int luaB_rawset (lua_State *L) { -+ luaL_checktype(L, 1, LUA_TTABLE); -+ luaL_checkany(L, 2); -+ luaL_checkany(L, 3); -+ lua_settop(L, 3); -+ lua_rawset(L, 1); -+ return 1; -+} -+ -+ -+static int luaB_gcinfo (lua_State *L) { -+ lua_pushinteger(L, lua_getgccount(L)); -+ return 1; -+} -+ -+static int luaB_collectgarbage (lua_State *L) { -+ static const char *const opts[] = {"stop", "restart", "collect", -+ "count", "step", "setpause", "setstepmul", NULL}; -+ static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, -+ LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL}; -+ int o = luaL_checkoption(L, 1, "collect", opts); -+ int ex = luaL_optint(L, 2, 0); -+ int res = lua_gc(L, optsnum[o], ex); -+ switch (optsnum[o]) { -+ case LUA_GCCOUNT: { -+ int b = lua_gc(L, LUA_GCCOUNTB, 0); -+ lua_pushnumber(L, res + ((lua_Number)b/1024)); -+ return 1; -+ } -+ case LUA_GCSTEP: { -+ lua_pushboolean(L, res); -+ return 1; -+ } -+ default: { -+ lua_pushnumber(L, res); -+ return 1; -+ } -+ } -+} -+ -+ -+static int luaB_type (lua_State *L) { -+ luaL_checkany(L, 1); -+ lua_pushstring(L, luaL_typename(L, 1)); -+ return 1; -+} -+ -+ -+static int luaB_next (lua_State *L) { -+ luaL_checktype(L, 1, LUA_TTABLE); -+ lua_settop(L, 2); /* create a 2nd argument if there isn't one */ -+ if (lua_next(L, 1)) -+ return 2; -+ else { -+ lua_pushnil(L); -+ return 1; -+ } -+} -+ -+ -+static int luaB_pairs (lua_State *L) { -+ luaL_checktype(L, 1, LUA_TTABLE); -+ lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */ -+ lua_pushvalue(L, 1); /* state, */ -+ lua_pushnil(L); /* and initial value */ -+ return 3; -+} -+ -+ -+static int ipairsaux (lua_State *L) { -+ int i = luaL_checkint(L, 2); -+ luaL_checktype(L, 1, LUA_TTABLE); -+ i++; /* next value */ -+ lua_pushinteger(L, i); -+ lua_rawgeti(L, 1, i); -+ return (lua_isnil(L, -1)) ? 0 : 2; -+} -+ -+ -+static int luaB_ipairs (lua_State *L) { -+ luaL_checktype(L, 1, LUA_TTABLE); -+ lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */ -+ lua_pushvalue(L, 1); /* state, */ -+ lua_pushinteger(L, 0); /* and initial value */ -+ return 3; -+} -+ -+ -+static int load_aux (lua_State *L, int status) { -+ if (status == 0) /* OK? */ -+ return 1; -+ else { -+ lua_pushnil(L); -+ lua_insert(L, -2); /* put before error message */ -+ return 2; /* return nil plus error message */ -+ } -+} -+ -+ -+static int luaB_loadstring (lua_State *L) { -+ size_t l; -+ const char *s = luaL_checklstring(L, 1, &l); -+ const char *chunkname = luaL_optstring(L, 2, s); -+ return load_aux(L, luaL_loadbuffer(L, s, l, chunkname)); -+} -+ -+/* -+static int luaB_loadfile (lua_State *L) { -+ const char *fname = luaL_optstring(L, 1, NULL); -+ return load_aux(L, luaL_loadfile(L, fname)); -+} -+*/ -+ -+/* -+** Reader for generic `load' function: `lua_load' uses the -+** stack for internal stuff, so the reader cannot change the -+** stack top. Instead, it keeps its resulting string in a -+** reserved slot inside the stack. -+*/ -+static const char *generic_reader (lua_State *L, void *ud, size_t *size) { -+ (void)ud; /* to avoid warnings */ -+ luaL_checkstack(L, 2, "too many nested functions"); -+ lua_pushvalue(L, 1); /* get function */ -+ lua_call(L, 0, 1); /* call it */ -+ if (lua_isnil(L, -1)) { -+ *size = 0; -+ return NULL; -+ } -+ else if (lua_isstring(L, -1)) { -+ lua_replace(L, 3); /* save string in a reserved stack slot */ -+ return lua_tolstring(L, 3, size); -+ } -+ else luaL_error(L, "reader function must return a string"); -+ return NULL; /* to avoid warnings */ -+} -+ -+ -+static int luaB_load (lua_State *L) { -+ int status; -+ const char *cname = luaL_optstring(L, 2, "=(load)"); -+ luaL_checktype(L, 1, LUA_TFUNCTION); -+ lua_settop(L, 3); /* function, eventual name, plus one reserved slot */ -+ status = lua_load(L, generic_reader, NULL, cname); -+ return load_aux(L, status); -+} -+ -+/* -+static int luaB_dofile (lua_State *L) { -+ const char *fname = luaL_optstring(L, 1, NULL); -+ int n = lua_gettop(L); -+ if (luaL_loadfile(L, fname) != 0) lua_error(L); -+ lua_call(L, 0, LUA_MULTRET); -+ return lua_gettop(L) - n; -+} -+*/ -+ -+static int luaB_assert (lua_State *L) { -+ luaL_checkany(L, 1); -+ if (!lua_toboolean(L, 1)) -+ return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!")); -+ return lua_gettop(L); -+} -+ -+ -+static int luaB_unpack (lua_State *L) { -+ int i, e, n; -+ luaL_checktype(L, 1, LUA_TTABLE); -+ i = luaL_optint(L, 2, 1); -+ e = luaL_opt(L, luaL_checkint, 3, luaL_getn(L, 1)); -+ if (i > e) return 0; /* empty range */ -+ n = e - i + 1; /* number of elements */ -+ if (n <= 0 || !lua_checkstack(L, n)) /* n <= 0 means arith. overflow */ -+ return luaL_error(L, "too many results to unpack"); -+ lua_rawgeti(L, 1, i); /* push arg[i] (avoiding overflow problems) */ -+ while (i++ < e) /* push arg[i + 1...e] */ -+ lua_rawgeti(L, 1, i); -+ return n; -+} -+ -+ -+static int luaB_select (lua_State *L) { -+ int n = lua_gettop(L); -+ if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') { -+ lua_pushinteger(L, n-1); -+ return 1; -+ } -+ else { -+ int i = luaL_checkint(L, 1); -+ if (i < 0) i = n + i; -+ else if (i > n) i = n; -+ luaL_argcheck(L, 1 <= i, 1, "index out of range"); -+ return n - i; -+ } -+} -+ -+ -+static int luaB_pcall (lua_State *L) { -+ int status; -+ luaL_checkany(L, 1); -+ status = lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0); -+ lua_pushboolean(L, (status == 0)); -+ lua_insert(L, 1); -+ return lua_gettop(L); /* return status + all results */ -+} -+ -+ -+static int luaB_xpcall (lua_State *L) { -+ int status; -+ luaL_checkany(L, 2); -+ lua_settop(L, 2); -+ lua_insert(L, 1); /* put error function under function to be called */ -+ status = lua_pcall(L, 0, LUA_MULTRET, 1); -+ lua_pushboolean(L, (status == 0)); -+ lua_replace(L, 1); -+ return lua_gettop(L); /* return status + all results */ -+} -+ -+ -+static int luaB_tostring (lua_State *L) { -+ luaL_checkany(L, 1); -+ if (luaL_callmeta(L, 1, "__tostring")) /* is there a metafield? */ -+ return 1; /* use its value */ -+ switch (lua_type(L, 1)) { -+ case LUA_TNUMBER: -+ lua_pushstring(L, lua_tostring(L, 1)); -+ break; -+ case LUA_TSTRING: -+ lua_pushvalue(L, 1); -+ break; -+ case LUA_TBOOLEAN: -+ lua_pushstring(L, (lua_toboolean(L, 1) ? "true" : "false")); -+ break; -+ case LUA_TNIL: -+ lua_pushliteral(L, "nil"); -+ break; -+ default: -+ lua_pushfstring(L, "%s: %p", luaL_typename(L, 1), lua_topointer(L, 1)); -+ break; -+ } -+ return 1; -+} -+ -+ -+static int luaB_newproxy (lua_State *L) { -+ lua_settop(L, 1); -+ lua_newuserdata(L, 0); /* create proxy */ -+ if (lua_toboolean(L, 1) == 0) -+ return 1; /* no metatable */ -+ else if (lua_isboolean(L, 1)) { -+ lua_newtable(L); /* create a new metatable `m' ... */ -+ lua_pushvalue(L, -1); /* ... and mark `m' as a valid metatable */ -+ lua_pushboolean(L, 1); -+ lua_rawset(L, lua_upvalueindex(1)); /* weaktable[m] = true */ -+ } -+ else { -+ int validproxy = 0; /* to check if weaktable[metatable(u)] == true */ -+ if (lua_getmetatable(L, 1)) { -+ lua_rawget(L, lua_upvalueindex(1)); -+ validproxy = lua_toboolean(L, -1); -+ lua_pop(L, 1); /* remove value */ -+ } -+ luaL_argcheck(L, validproxy, 1, "boolean or proxy expected"); -+ lua_getmetatable(L, 1); /* metatable is valid; get it */ -+ } -+ lua_setmetatable(L, 2); -+ return 1; -+} -+ -+ -+static const luaL_Reg base_funcs[] = { -+ {"assert", luaB_assert}, -+ {"collectgarbage", luaB_collectgarbage}, -+// {"dofile", luaB_dofile}, -+ {"error", luaB_error}, -+ {"gcinfo", luaB_gcinfo}, -+ {"getfenv", luaB_getfenv}, -+ {"getmetatable", luaB_getmetatable}, -+// {"loadfile", luaB_loadfile}, -+ {"load", luaB_load}, -+ {"loadstring", luaB_loadstring}, -+ {"next", luaB_next}, -+ {"pcall", luaB_pcall}, -+ {"print", luaB_print}, -+ {"rawequal", luaB_rawequal}, -+ {"rawget", luaB_rawget}, -+ {"rawset", luaB_rawset}, -+ {"select", luaB_select}, -+ {"setfenv", luaB_setfenv}, -+ {"setmetatable", luaB_setmetatable}, -+ {"tonumber", luaB_tonumber}, -+ {"tostring", luaB_tostring}, -+ {"type", luaB_type}, -+ {"unpack", luaB_unpack}, -+ {"xpcall", luaB_xpcall}, -+ {NULL, NULL} -+}; -+ -+ -+/* -+** {====================================================== -+** Coroutine library -+** ======================================================= -+*/ -+ -+#define CO_RUN 0 /* running */ -+#define CO_SUS 1 /* suspended */ -+#define CO_NOR 2 /* 'normal' (it resumed another coroutine) */ -+#define CO_DEAD 3 -+ -+static const char *const statnames[] = -+ {"running", "suspended", "normal", "dead"}; -+ -+static int costatus (lua_State *L, lua_State *co) { -+ if (L == co) return CO_RUN; -+ switch (lua_status(co)) { -+ case LUA_YIELD: -+ return CO_SUS; -+ case 0: { -+ lua_Debug ar; -+ if (lua_getstack(co, 0, &ar) > 0) /* does it have frames? */ -+ return CO_NOR; /* it is running */ -+ else if (lua_gettop(co) == 0) -+ return CO_DEAD; -+ else -+ return CO_SUS; /* initial state */ -+ } -+ default: /* some error occured */ -+ return CO_DEAD; -+ } -+} -+ -+ -+static int luaB_costatus (lua_State *L) { -+ lua_State *co = lua_tothread(L, 1); -+ luaL_argcheck(L, co, 1, "coroutine expected"); -+ lua_pushstring(L, statnames[costatus(L, co)]); -+ return 1; -+} -+ -+ -+static int auxresume (lua_State *L, lua_State *co, int narg) { -+ int status = costatus(L, co); -+ if (!lua_checkstack(co, narg)) -+ luaL_error(L, "too many arguments to resume"); -+ if (status != CO_SUS) { -+ lua_pushfstring(L, "cannot resume %s coroutine", statnames[status]); -+ return -1; /* error flag */ -+ } -+ lua_xmove(L, co, narg); -+ lua_setlevel(L, co); -+ status = lua_resume(co, narg); -+ if (status == 0 || status == LUA_YIELD) { -+ int nres = lua_gettop(co); -+ if (!lua_checkstack(L, nres + 1)) -+ luaL_error(L, "too many results to resume"); -+ lua_xmove(co, L, nres); /* move yielded values */ -+ return nres; -+ } -+ else { -+ lua_xmove(co, L, 1); /* move error message */ -+ return -1; /* error flag */ -+ } -+} -+ -+ -+static int luaB_coresume (lua_State *L) { -+ lua_State *co = lua_tothread(L, 1); -+ int r; -+ luaL_argcheck(L, co, 1, "coroutine expected"); -+ r = auxresume(L, co, lua_gettop(L) - 1); -+ if (r < 0) { -+ lua_pushboolean(L, 0); -+ lua_insert(L, -2); -+ return 2; /* return false + error message */ -+ } -+ else { -+ lua_pushboolean(L, 1); -+ lua_insert(L, -(r + 1)); -+ return r + 1; /* return true + `resume' returns */ -+ } -+} -+ -+ -+static int luaB_auxwrap (lua_State *L) { -+ lua_State *co = lua_tothread(L, lua_upvalueindex(1)); -+ int r = auxresume(L, co, lua_gettop(L)); -+ if (r < 0) { -+ if (lua_isstring(L, -1)) { /* error object is a string? */ -+ luaL_where(L, 1); /* add extra info */ -+ lua_insert(L, -2); -+ lua_concat(L, 2); -+ } -+ lua_error(L); /* propagate error */ -+ } -+ return r; -+} -+ -+ -+static int luaB_cocreate (lua_State *L) { -+ lua_State *NL = lua_newthread(L); -+ luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1, -+ "Lua function expected"); -+ lua_pushvalue(L, 1); /* move function to top */ -+ lua_xmove(L, NL, 1); /* move function from L to NL */ -+ return 1; -+} -+ -+ -+static int luaB_cowrap (lua_State *L) { -+ luaB_cocreate(L); -+ lua_pushcclosure(L, luaB_auxwrap, 1); -+ return 1; -+} -+ -+ -+static int luaB_yield (lua_State *L) { -+ return lua_yield(L, lua_gettop(L)); -+} -+ -+ -+static int luaB_corunning (lua_State *L) { -+ if (lua_pushthread(L)) -+ lua_pushnil(L); /* main thread is not a coroutine */ -+ return 1; -+} -+ -+ -+static const luaL_Reg co_funcs[] = { -+ {"create", luaB_cocreate}, -+ {"resume", luaB_coresume}, -+ {"running", luaB_corunning}, -+ {"status", luaB_costatus}, -+ {"wrap", luaB_cowrap}, -+ {"yield", luaB_yield}, -+ {NULL, NULL} -+}; -+ -+/* }====================================================== */ -+ -+ -+static void auxopen (lua_State *L, const char *name, -+ lua_CFunction f, lua_CFunction u) { -+ lua_pushcfunction(L, u); -+ lua_pushcclosure(L, f, 1); -+ lua_setfield(L, -2, name); -+} -+ -+ -+static void base_open (lua_State *L) { -+ /* set global _G */ -+ lua_pushvalue(L, LUA_GLOBALSINDEX); -+ lua_setglobal(L, "_G"); -+ /* open lib into global table */ -+ luaL_register(L, "_G", base_funcs); -+ lua_pushliteral(L, LUA_VERSION); -+ lua_setglobal(L, "_VERSION"); /* set global _VERSION */ -+ /* `ipairs' and `pairs' need auxliliary functions as upvalues */ -+ auxopen(L, "ipairs", luaB_ipairs, ipairsaux); -+ auxopen(L, "pairs", luaB_pairs, luaB_next); -+ /* `newproxy' needs a weaktable as upvalue */ -+ lua_createtable(L, 0, 1); /* new table `w' */ -+ lua_pushvalue(L, -1); /* `w' will be its own metatable */ -+ lua_setmetatable(L, -2); -+ lua_pushliteral(L, "kv"); -+ lua_setfield(L, -2, "__mode"); /* metatable(w).__mode = "kv" */ -+ lua_pushcclosure(L, luaB_newproxy, 1); -+ lua_setglobal(L, "newproxy"); /* set global `newproxy' */ -+} -+ -+ -+LUALIB_API int luaopen_base (lua_State *L) { -+ base_open(L); -+ luaL_register(L, LUA_COLIBNAME, co_funcs); -+ return 2; -+} ---- /dev/null -+++ b/extensions/LUA/lua/lcode.c -@@ -0,0 +1,838 @@ -+/* -+** $Id: lcode.c,v 2.25.1.3 2007/12/28 15:32:23 roberto Exp $ -+** Code generator for Lua -+** See Copyright Notice in lua.h -+*/ -+ -+#include -+ -+#define lcode_c -+#define LUA_CORE -+ -+#include "lua.h" -+ -+#include "lcode.h" -+#include "ldebug.h" -+#include "ldo.h" -+#include "lgc.h" -+#include "llex.h" -+#include "lmem.h" -+#include "lobject.h" -+#include "lopcodes.h" -+#include "lparser.h" -+#include "ltable.h" -+ -+ -+#define hasjumps(e) ((e)->t != (e)->f) -+ -+ -+static int isnumeral(expdesc *e) { -+ return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP); -+} -+ -+ -+void luaK_nil (FuncState *fs, int from, int n) { -+ Instruction *previous; -+ if (fs->pc > fs->lasttarget) { /* no jumps to current position? */ -+ if (fs->pc == 0) { /* function start? */ -+ if (from >= fs->nactvar) -+ return; /* positions are already clean */ -+ } -+ else { -+ previous = &fs->f->code[fs->pc-1]; -+ if (GET_OPCODE(*previous) == OP_LOADNIL) { -+ int pfrom = GETARG_A(*previous); -+ int pto = GETARG_B(*previous); -+ if (pfrom <= from && from <= pto+1) { /* can connect both? */ -+ if (from+n-1 > pto) -+ SETARG_B(*previous, from+n-1); -+ return; -+ } -+ } -+ } -+ } -+ luaK_codeABC(fs, OP_LOADNIL, from, from+n-1, 0); /* else no optimization */ -+} -+ -+ -+int luaK_jump (FuncState *fs) { -+ int jpc = fs->jpc; /* save list of jumps to here */ -+ int j; -+ fs->jpc = NO_JUMP; -+ j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP); -+ luaK_concat(fs, &j, jpc); /* keep them on hold */ -+ return j; -+} -+ -+ -+void luaK_ret (FuncState *fs, int first, int nret) { -+ luaK_codeABC(fs, OP_RETURN, first, nret+1, 0); -+} -+ -+ -+static int condjump (FuncState *fs, OpCode op, int A, int B, int C) { -+ luaK_codeABC(fs, op, A, B, C); -+ return luaK_jump(fs); -+} -+ -+ -+static void fixjump (FuncState *fs, int pc, int dest) { -+ Instruction *jmp = &fs->f->code[pc]; -+ int offset = dest-(pc+1); -+ lua_assert(dest != NO_JUMP); -+ if (abs(offset) > MAXARG_sBx) -+ luaX_syntaxerror(fs->ls, "control structure too long"); -+ SETARG_sBx(*jmp, offset); -+} -+ -+ -+/* -+** returns current `pc' and marks it as a jump target (to avoid wrong -+** optimizations with consecutive instructions not in the same basic block). -+*/ -+int luaK_getlabel (FuncState *fs) { -+ fs->lasttarget = fs->pc; -+ return fs->pc; -+} -+ -+ -+static int getjump (FuncState *fs, int pc) { -+ int offset = GETARG_sBx(fs->f->code[pc]); -+ if (offset == NO_JUMP) /* point to itself represents end of list */ -+ return NO_JUMP; /* end of list */ -+ else -+ return (pc+1)+offset; /* turn offset into absolute position */ -+} -+ -+ -+static Instruction *getjumpcontrol (FuncState *fs, int pc) { -+ Instruction *pi = &fs->f->code[pc]; -+ if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1)))) -+ return pi-1; -+ else -+ return pi; -+} -+ -+ -+/* -+** check whether list has any jump that do not produce a value -+** (or produce an inverted value) -+*/ -+static int need_value (FuncState *fs, int list) { -+ for (; list != NO_JUMP; list = getjump(fs, list)) { -+ Instruction i = *getjumpcontrol(fs, list); -+ if (GET_OPCODE(i) != OP_TESTSET) return 1; -+ } -+ return 0; /* not found */ -+} -+ -+ -+static int patchtestreg (FuncState *fs, int node, int reg) { -+ Instruction *i = getjumpcontrol(fs, node); -+ if (GET_OPCODE(*i) != OP_TESTSET) -+ return 0; /* cannot patch other instructions */ -+ if (reg != NO_REG && reg != GETARG_B(*i)) -+ SETARG_A(*i, reg); -+ else /* no register to put value or register already has the value */ -+ *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i)); -+ -+ return 1; -+} -+ -+ -+static void removevalues (FuncState *fs, int list) { -+ for (; list != NO_JUMP; list = getjump(fs, list)) -+ patchtestreg(fs, list, NO_REG); -+} -+ -+ -+static void patchlistaux (FuncState *fs, int list, int vtarget, int reg, -+ int dtarget) { -+ while (list != NO_JUMP) { -+ int next = getjump(fs, list); -+ if (patchtestreg(fs, list, reg)) -+ fixjump(fs, list, vtarget); -+ else -+ fixjump(fs, list, dtarget); /* jump to default target */ -+ list = next; -+ } -+} -+ -+ -+static void dischargejpc (FuncState *fs) { -+ patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc); -+ fs->jpc = NO_JUMP; -+} -+ -+ -+void luaK_patchlist (FuncState *fs, int list, int target) { -+ if (target == fs->pc) -+ luaK_patchtohere(fs, list); -+ else { -+ lua_assert(target < fs->pc); -+ patchlistaux(fs, list, target, NO_REG, target); -+ } -+} -+ -+ -+void luaK_patchtohere (FuncState *fs, int list) { -+ luaK_getlabel(fs); -+ luaK_concat(fs, &fs->jpc, list); -+} -+ -+ -+void luaK_concat (FuncState *fs, int *l1, int l2) { -+ if (l2 == NO_JUMP) return; -+ else if (*l1 == NO_JUMP) -+ *l1 = l2; -+ else { -+ int list = *l1; -+ int next; -+ while ((next = getjump(fs, list)) != NO_JUMP) /* find last element */ -+ list = next; -+ fixjump(fs, list, l2); -+ } -+} -+ -+ -+void luaK_checkstack (FuncState *fs, int n) { -+ int newstack = fs->freereg + n; -+ if (newstack > fs->f->maxstacksize) { -+ if (newstack >= MAXSTACK) -+ luaX_syntaxerror(fs->ls, "function or expression too complex"); -+ fs->f->maxstacksize = cast_byte(newstack); -+ } -+} -+ -+ -+void luaK_reserveregs (FuncState *fs, int n) { -+ luaK_checkstack(fs, n); -+ fs->freereg += n; -+} -+ -+ -+static void freereg (FuncState *fs, int reg) { -+ if (!ISK(reg) && reg >= fs->nactvar) { -+ fs->freereg--; -+ lua_assert(reg == fs->freereg); -+ } -+} -+ -+ -+static void freeexp (FuncState *fs, expdesc *e) { -+ if (e->k == VNONRELOC) -+ freereg(fs, e->u.s.info); -+} -+ -+ -+static int addk (FuncState *fs, TValue *k, TValue *v) { -+ lua_State *L = fs->L; -+ TValue *idx = luaH_set(L, fs->h, k); -+ Proto *f = fs->f; -+ int oldsize = f->sizek; -+ if (ttisnumber(idx)) { -+ lua_assert(luaO_rawequalObj(&fs->f->k[cast_int(nvalue(idx))], v)); -+ return cast_int(nvalue(idx)); -+ } -+ else { /* constant not found; create a new entry */ -+ setnvalue(idx, cast_num(fs->nk)); -+ luaM_growvector(L, f->k, fs->nk, f->sizek, TValue, -+ MAXARG_Bx, "constant table overflow"); -+ while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); -+ setobj(L, &f->k[fs->nk], v); -+ luaC_barrier(L, f, v); -+ return fs->nk++; -+ } -+} -+ -+ -+int luaK_stringK (FuncState *fs, TString *s) { -+ TValue o; -+ setsvalue(fs->L, &o, s); -+ return addk(fs, &o, &o); -+} -+ -+ -+int luaK_numberK (FuncState *fs, lua_Number r) { -+ TValue o; -+ setnvalue(&o, r); -+ return addk(fs, &o, &o); -+} -+ -+ -+static int boolK (FuncState *fs, int b) { -+ TValue o; -+ setbvalue(&o, b); -+ return addk(fs, &o, &o); -+} -+ -+ -+static int nilK (FuncState *fs) { -+ TValue k, v; -+ setnilvalue(&v); -+ /* cannot use nil as key; instead use table itself to represent nil */ -+ sethvalue(fs->L, &k, fs->h); -+ return addk(fs, &k, &v); -+} -+ -+ -+void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) { -+ if (e->k == VCALL) { /* expression is an open function call? */ -+ SETARG_C(getcode(fs, e), nresults+1); -+ } -+ else if (e->k == VVARARG) { -+ SETARG_B(getcode(fs, e), nresults+1); -+ SETARG_A(getcode(fs, e), fs->freereg); -+ luaK_reserveregs(fs, 1); -+ } -+} -+ -+ -+void luaK_setoneret (FuncState *fs, expdesc *e) { -+ if (e->k == VCALL) { /* expression is an open function call? */ -+ e->k = VNONRELOC; -+ e->u.s.info = GETARG_A(getcode(fs, e)); -+ } -+ else if (e->k == VVARARG) { -+ SETARG_B(getcode(fs, e), 2); -+ e->k = VRELOCABLE; /* can relocate its simple result */ -+ } -+} -+ -+ -+void luaK_dischargevars (FuncState *fs, expdesc *e) { -+ switch (e->k) { -+ case VLOCAL: { -+ e->k = VNONRELOC; -+ break; -+ } -+ case VUPVAL: { -+ e->u.s.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.s.info, 0); -+ e->k = VRELOCABLE; -+ break; -+ } -+ case VGLOBAL: { -+ e->u.s.info = luaK_codeABx(fs, OP_GETGLOBAL, 0, e->u.s.info); -+ e->k = VRELOCABLE; -+ break; -+ } -+ case VINDEXED: { -+ freereg(fs, e->u.s.aux); -+ freereg(fs, e->u.s.info); -+ e->u.s.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.s.info, e->u.s.aux); -+ e->k = VRELOCABLE; -+ break; -+ } -+ case VVARARG: -+ case VCALL: { -+ luaK_setoneret(fs, e); -+ break; -+ } -+ default: break; /* there is one value available (somewhere) */ -+ } -+} -+ -+ -+static int code_label (FuncState *fs, int A, int b, int jump) { -+ luaK_getlabel(fs); /* those instructions may be jump targets */ -+ return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump); -+} -+ -+ -+static void discharge2reg (FuncState *fs, expdesc *e, int reg) { -+ luaK_dischargevars(fs, e); -+ switch (e->k) { -+ case VNIL: { -+ luaK_nil(fs, reg, 1); -+ break; -+ } -+ case VFALSE: case VTRUE: { -+ luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0); -+ break; -+ } -+ case VK: { -+ luaK_codeABx(fs, OP_LOADK, reg, e->u.s.info); -+ break; -+ } -+ case VKNUM: { -+ luaK_codeABx(fs, OP_LOADK, reg, luaK_numberK(fs, e->u.nval)); -+ break; -+ } -+ case VRELOCABLE: { -+ Instruction *pc = &getcode(fs, e); -+ SETARG_A(*pc, reg); -+ break; -+ } -+ case VNONRELOC: { -+ if (reg != e->u.s.info) -+ luaK_codeABC(fs, OP_MOVE, reg, e->u.s.info, 0); -+ break; -+ } -+ default: { -+ lua_assert(e->k == VVOID || e->k == VJMP); -+ return; /* nothing to do... */ -+ } -+ } -+ e->u.s.info = reg; -+ e->k = VNONRELOC; -+} -+ -+ -+static void discharge2anyreg (FuncState *fs, expdesc *e) { -+ if (e->k != VNONRELOC) { -+ luaK_reserveregs(fs, 1); -+ discharge2reg(fs, e, fs->freereg-1); -+ } -+} -+ -+ -+static void exp2reg (FuncState *fs, expdesc *e, int reg) { -+ discharge2reg(fs, e, reg); -+ if (e->k == VJMP) -+ luaK_concat(fs, &e->t, e->u.s.info); /* put this jump in `t' list */ -+ if (hasjumps(e)) { -+ int final; /* position after whole expression */ -+ int p_f = NO_JUMP; /* position of an eventual LOAD false */ -+ int p_t = NO_JUMP; /* position of an eventual LOAD true */ -+ if (need_value(fs, e->t) || need_value(fs, e->f)) { -+ int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs); -+ p_f = code_label(fs, reg, 0, 1); -+ p_t = code_label(fs, reg, 1, 0); -+ luaK_patchtohere(fs, fj); -+ } -+ final = luaK_getlabel(fs); -+ patchlistaux(fs, e->f, final, reg, p_f); -+ patchlistaux(fs, e->t, final, reg, p_t); -+ } -+ e->f = e->t = NO_JUMP; -+ e->u.s.info = reg; -+ e->k = VNONRELOC; -+} -+ -+ -+void luaK_exp2nextreg (FuncState *fs, expdesc *e) { -+ luaK_dischargevars(fs, e); -+ freeexp(fs, e); -+ luaK_reserveregs(fs, 1); -+ exp2reg(fs, e, fs->freereg - 1); -+} -+ -+ -+int luaK_exp2anyreg (FuncState *fs, expdesc *e) { -+ luaK_dischargevars(fs, e); -+ if (e->k == VNONRELOC) { -+ if (!hasjumps(e)) return e->u.s.info; /* exp is already in a register */ -+ if (e->u.s.info >= fs->nactvar) { /* reg. is not a local? */ -+ exp2reg(fs, e, e->u.s.info); /* put value on it */ -+ return e->u.s.info; -+ } -+ } -+ luaK_exp2nextreg(fs, e); /* default */ -+ return e->u.s.info; -+} -+ -+ -+void luaK_exp2val (FuncState *fs, expdesc *e) { -+ if (hasjumps(e)) -+ luaK_exp2anyreg(fs, e); -+ else -+ luaK_dischargevars(fs, e); -+} -+ -+ -+int luaK_exp2RK (FuncState *fs, expdesc *e) { -+ luaK_exp2val(fs, e); -+ switch (e->k) { -+ case VKNUM: -+ case VTRUE: -+ case VFALSE: -+ case VNIL: { -+ if (fs->nk <= MAXINDEXRK) { /* constant fit in RK operand? */ -+ e->u.s.info = (e->k == VNIL) ? nilK(fs) : -+ (e->k == VKNUM) ? luaK_numberK(fs, e->u.nval) : -+ boolK(fs, (e->k == VTRUE)); -+ e->k = VK; -+ return RKASK(e->u.s.info); -+ } -+ else break; -+ } -+ case VK: { -+ if (e->u.s.info <= MAXINDEXRK) /* constant fit in argC? */ -+ return RKASK(e->u.s.info); -+ else break; -+ } -+ default: break; -+ } -+ /* not a constant in the right range: put it in a register */ -+ return luaK_exp2anyreg(fs, e); -+} -+ -+ -+void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) { -+ switch (var->k) { -+ case VLOCAL: { -+ freeexp(fs, ex); -+ exp2reg(fs, ex, var->u.s.info); -+ return; -+ } -+ case VUPVAL: { -+ int e = luaK_exp2anyreg(fs, ex); -+ luaK_codeABC(fs, OP_SETUPVAL, e, var->u.s.info, 0); -+ break; -+ } -+ case VGLOBAL: { -+ int e = luaK_exp2anyreg(fs, ex); -+ luaK_codeABx(fs, OP_SETGLOBAL, e, var->u.s.info); -+ break; -+ } -+ case VINDEXED: { -+ int e = luaK_exp2RK(fs, ex); -+ luaK_codeABC(fs, OP_SETTABLE, var->u.s.info, var->u.s.aux, e); -+ break; -+ } -+ default: { -+ lua_assert(0); /* invalid var kind to store */ -+ break; -+ } -+ } -+ freeexp(fs, ex); -+} -+ -+ -+void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { -+ int func; -+ luaK_exp2anyreg(fs, e); -+ freeexp(fs, e); -+ func = fs->freereg; -+ luaK_reserveregs(fs, 2); -+ luaK_codeABC(fs, OP_SELF, func, e->u.s.info, luaK_exp2RK(fs, key)); -+ freeexp(fs, key); -+ e->u.s.info = func; -+ e->k = VNONRELOC; -+} -+ -+ -+static void invertjump (FuncState *fs, expdesc *e) { -+ Instruction *pc = getjumpcontrol(fs, e->u.s.info); -+ lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET && -+ GET_OPCODE(*pc) != OP_TEST); -+ SETARG_A(*pc, !(GETARG_A(*pc))); -+} -+ -+ -+static int jumponcond (FuncState *fs, expdesc *e, int cond) { -+ if (e->k == VRELOCABLE) { -+ Instruction ie = getcode(fs, e); -+ if (GET_OPCODE(ie) == OP_NOT) { -+ fs->pc--; /* remove previous OP_NOT */ -+ return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond); -+ } -+ /* else go through */ -+ } -+ discharge2anyreg(fs, e); -+ freeexp(fs, e); -+ return condjump(fs, OP_TESTSET, NO_REG, e->u.s.info, cond); -+} -+ -+ -+void luaK_goiftrue (FuncState *fs, expdesc *e) { -+ int pc; /* pc of last jump */ -+ luaK_dischargevars(fs, e); -+ switch (e->k) { -+ case VK: case VKNUM: case VTRUE: { -+ pc = NO_JUMP; /* always true; do nothing */ -+ break; -+ } -+ case VFALSE: { -+ pc = luaK_jump(fs); /* always jump */ -+ break; -+ } -+ case VJMP: { -+ invertjump(fs, e); -+ pc = e->u.s.info; -+ break; -+ } -+ default: { -+ pc = jumponcond(fs, e, 0); -+ break; -+ } -+ } -+ luaK_concat(fs, &e->f, pc); /* insert last jump in `f' list */ -+ luaK_patchtohere(fs, e->t); -+ e->t = NO_JUMP; -+} -+ -+ -+static void luaK_goiffalse (FuncState *fs, expdesc *e) { -+ int pc; /* pc of last jump */ -+ luaK_dischargevars(fs, e); -+ switch (e->k) { -+ case VNIL: case VFALSE: { -+ pc = NO_JUMP; /* always false; do nothing */ -+ break; -+ } -+ case VTRUE: { -+ pc = luaK_jump(fs); /* always jump */ -+ break; -+ } -+ case VJMP: { -+ pc = e->u.s.info; -+ break; -+ } -+ default: { -+ pc = jumponcond(fs, e, 1); -+ break; -+ } -+ } -+ luaK_concat(fs, &e->t, pc); /* insert last jump in `t' list */ -+ luaK_patchtohere(fs, e->f); -+ e->f = NO_JUMP; -+} -+ -+ -+static void codenot (FuncState *fs, expdesc *e) { -+ luaK_dischargevars(fs, e); -+ switch (e->k) { -+ case VNIL: case VFALSE: { -+ e->k = VTRUE; -+ break; -+ } -+ case VK: case VKNUM: case VTRUE: { -+ e->k = VFALSE; -+ break; -+ } -+ case VJMP: { -+ invertjump(fs, e); -+ break; -+ } -+ case VRELOCABLE: -+ case VNONRELOC: { -+ discharge2anyreg(fs, e); -+ freeexp(fs, e); -+ e->u.s.info = luaK_codeABC(fs, OP_NOT, 0, e->u.s.info, 0); -+ e->k = VRELOCABLE; -+ break; -+ } -+ default: { -+ lua_assert(0); /* cannot happen */ -+ break; -+ } -+ } -+ /* interchange true and false lists */ -+ { int temp = e->f; e->f = e->t; e->t = temp; } -+ removevalues(fs, e->f); -+ removevalues(fs, e->t); -+} -+ -+ -+void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { -+ t->u.s.aux = luaK_exp2RK(fs, k); -+ t->k = VINDEXED; -+} -+ -+ -+static int constfolding (OpCode op, expdesc *e1, expdesc *e2) { -+ lua_Number v1, v2, r; -+ if (!isnumeral(e1) || !isnumeral(e2)) return 0; -+ v1 = e1->u.nval; -+ v2 = e2->u.nval; -+ switch (op) { -+ case OP_ADD: r = luai_numadd(v1, v2); break; -+ case OP_SUB: r = luai_numsub(v1, v2); break; -+ case OP_MUL: r = luai_nummul(v1, v2); break; -+ case OP_DIV: -+ if (v2 == 0) return 0; /* do not attempt to divide by 0 */ -+ r = luai_numdiv(v1, v2); break; -+ case OP_MOD: -+ if (v2 == 0) return 0; /* do not attempt to divide by 0 */ -+ r = luai_nummod(v1, v2); break; -+ case OP_POW: r = luai_numpow(v1, v2); break; -+ case OP_UNM: r = luai_numunm(v1); break; -+ case OP_LEN: return 0; /* no constant folding for 'len' */ -+ default: lua_assert(0); r = 0; break; -+ } -+ if (luai_numisnan(r)) return 0; /* do not attempt to produce NaN */ -+ e1->u.nval = r; -+ return 1; -+} -+ -+ -+static void codearith (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) { -+ if (constfolding(op, e1, e2)) -+ return; -+ else { -+ int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0; -+ int o1 = luaK_exp2RK(fs, e1); -+ if (o1 > o2) { -+ freeexp(fs, e1); -+ freeexp(fs, e2); -+ } -+ else { -+ freeexp(fs, e2); -+ freeexp(fs, e1); -+ } -+ e1->u.s.info = luaK_codeABC(fs, op, 0, o1, o2); -+ e1->k = VRELOCABLE; -+ } -+} -+ -+ -+static void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1, -+ expdesc *e2) { -+ int o1 = luaK_exp2RK(fs, e1); -+ int o2 = luaK_exp2RK(fs, e2); -+ freeexp(fs, e2); -+ freeexp(fs, e1); -+ if (cond == 0 && op != OP_EQ) { -+ int temp; /* exchange args to replace by `<' or `<=' */ -+ temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */ -+ cond = 1; -+ } -+ e1->u.s.info = condjump(fs, op, cond, o1, o2); -+ e1->k = VJMP; -+} -+ -+ -+void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) { -+ expdesc e2; -+ e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0; -+ switch (op) { -+ case OPR_MINUS: { -+ if (!isnumeral(e)) -+ luaK_exp2anyreg(fs, e); /* cannot operate on non-numeric constants */ -+ codearith(fs, OP_UNM, e, &e2); -+ break; -+ } -+ case OPR_NOT: codenot(fs, e); break; -+ case OPR_LEN: { -+ luaK_exp2anyreg(fs, e); /* cannot operate on constants */ -+ codearith(fs, OP_LEN, e, &e2); -+ break; -+ } -+ default: lua_assert(0); -+ } -+} -+ -+ -+void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { -+ switch (op) { -+ case OPR_AND: { -+ luaK_goiftrue(fs, v); -+ break; -+ } -+ case OPR_OR: { -+ luaK_goiffalse(fs, v); -+ break; -+ } -+ case OPR_CONCAT: { -+ luaK_exp2nextreg(fs, v); /* operand must be on the `stack' */ -+ break; -+ } -+ case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV: -+ case OPR_MOD: case OPR_POW: { -+ if (!isnumeral(v)) luaK_exp2RK(fs, v); -+ break; -+ } -+ default: { -+ luaK_exp2RK(fs, v); -+ break; -+ } -+ } -+} -+ -+ -+void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) { -+ switch (op) { -+ case OPR_AND: { -+ lua_assert(e1->t == NO_JUMP); /* list must be closed */ -+ luaK_dischargevars(fs, e2); -+ luaK_concat(fs, &e2->f, e1->f); -+ *e1 = *e2; -+ break; -+ } -+ case OPR_OR: { -+ lua_assert(e1->f == NO_JUMP); /* list must be closed */ -+ luaK_dischargevars(fs, e2); -+ luaK_concat(fs, &e2->t, e1->t); -+ *e1 = *e2; -+ break; -+ } -+ case OPR_CONCAT: { -+ luaK_exp2val(fs, e2); -+ if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) { -+ lua_assert(e1->u.s.info == GETARG_B(getcode(fs, e2))-1); -+ freeexp(fs, e1); -+ SETARG_B(getcode(fs, e2), e1->u.s.info); -+ e1->k = VRELOCABLE; e1->u.s.info = e2->u.s.info; -+ } -+ else { -+ luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */ -+ codearith(fs, OP_CONCAT, e1, e2); -+ } -+ break; -+ } -+ case OPR_ADD: codearith(fs, OP_ADD, e1, e2); break; -+ case OPR_SUB: codearith(fs, OP_SUB, e1, e2); break; -+ case OPR_MUL: codearith(fs, OP_MUL, e1, e2); break; -+ case OPR_DIV: codearith(fs, OP_DIV, e1, e2); break; -+ case OPR_MOD: codearith(fs, OP_MOD, e1, e2); break; -+ case OPR_POW: codearith(fs, OP_POW, e1, e2); break; -+ case OPR_EQ: codecomp(fs, OP_EQ, 1, e1, e2); break; -+ case OPR_NE: codecomp(fs, OP_EQ, 0, e1, e2); break; -+ case OPR_LT: codecomp(fs, OP_LT, 1, e1, e2); break; -+ case OPR_LE: codecomp(fs, OP_LE, 1, e1, e2); break; -+ case OPR_GT: codecomp(fs, OP_LT, 0, e1, e2); break; -+ case OPR_GE: codecomp(fs, OP_LE, 0, e1, e2); break; -+ default: lua_assert(0); -+ } -+} -+ -+ -+void luaK_fixline (FuncState *fs, int line) { -+ fs->f->lineinfo[fs->pc - 1] = line; -+} -+ -+ -+static int luaK_code (FuncState *fs, Instruction i, int line) { -+ Proto *f = fs->f; -+ dischargejpc(fs); /* `pc' will change */ -+ /* put new instruction in code array */ -+ luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction, -+ MAX_INT, "code size overflow"); -+ f->code[fs->pc] = i; -+ /* save corresponding line information */ -+ luaM_growvector(fs->L, f->lineinfo, fs->pc, f->sizelineinfo, int, -+ MAX_INT, "code size overflow"); -+ f->lineinfo[fs->pc] = line; -+ return fs->pc++; -+} -+ -+ -+int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) { -+ lua_assert(getOpMode(o) == iABC); -+ lua_assert(getBMode(o) != OpArgN || b == 0); -+ lua_assert(getCMode(o) != OpArgN || c == 0); -+ return luaK_code(fs, CREATE_ABC(o, a, b, c), fs->ls->lastline); -+} -+ -+ -+int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) { -+ lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx); -+ lua_assert(getCMode(o) == OpArgN); -+ return luaK_code(fs, CREATE_ABx(o, a, bc), fs->ls->lastline); -+} -+ -+ -+void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) { -+ int c = (nelems - 1)/LFIELDS_PER_FLUSH + 1; -+ int b = (tostore == LUA_MULTRET) ? 0 : tostore; -+ lua_assert(tostore != 0); -+ if (c <= MAXARG_C) -+ luaK_codeABC(fs, OP_SETLIST, base, b, c); -+ else { -+ luaK_codeABC(fs, OP_SETLIST, base, b, 0); -+ luaK_code(fs, cast(Instruction, c), fs->ls->lastline); -+ } -+ fs->freereg = base + 1; /* free registers with list values */ -+} -+ ---- /dev/null -+++ b/extensions/LUA/lua/lcode.h -@@ -0,0 +1,76 @@ -+/* -+** $Id: lcode.h,v 1.48.1.1 2007/12/27 13:02:25 roberto Exp $ -+** Code generator for Lua -+** See Copyright Notice in lua.h -+*/ -+ -+#ifndef lcode_h -+#define lcode_h -+ -+#include "llex.h" -+#include "lobject.h" -+#include "lopcodes.h" -+#include "lparser.h" -+ -+ -+/* -+** Marks the end of a patch list. It is an invalid value both as an absolute -+** address, and as a list link (would link an element to itself). -+*/ -+#define NO_JUMP (-1) -+ -+ -+/* -+** grep "ORDER OPR" if you change these enums -+*/ -+typedef enum BinOpr { -+ OPR_ADD, OPR_SUB, OPR_MUL, OPR_DIV, OPR_MOD, OPR_POW, -+ OPR_CONCAT, -+ OPR_NE, OPR_EQ, -+ OPR_LT, OPR_LE, OPR_GT, OPR_GE, -+ OPR_AND, OPR_OR, -+ OPR_NOBINOPR -+} BinOpr; -+ -+ -+typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr; -+ -+ -+#define getcode(fs,e) ((fs)->f->code[(e)->u.s.info]) -+ -+#define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx) -+ -+#define luaK_setmultret(fs,e) luaK_setreturns(fs, e, LUA_MULTRET) -+ -+LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx); -+LUAI_FUNC int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C); -+LUAI_FUNC void luaK_fixline (FuncState *fs, int line); -+LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n); -+LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n); -+LUAI_FUNC void luaK_checkstack (FuncState *fs, int n); -+LUAI_FUNC int luaK_stringK (FuncState *fs, TString *s); -+LUAI_FUNC int luaK_numberK (FuncState *fs, lua_Number r); -+LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e); -+LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e); -+LUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e); -+LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e); -+LUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e); -+LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key); -+LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k); -+LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e); -+LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e); -+LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults); -+LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e); -+LUAI_FUNC int luaK_jump (FuncState *fs); -+LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret); -+LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target); -+LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list); -+LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2); -+LUAI_FUNC int luaK_getlabel (FuncState *fs); -+LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v); -+LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v); -+LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, expdesc *v2); -+LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore); -+ -+ -+#endif ---- /dev/null -+++ b/extensions/LUA/lua/ldebug.c -@@ -0,0 +1,637 @@ -+/* -+** $Id: ldebug.c,v 2.29.1.6 2008/05/08 16:56:26 roberto Exp $ -+** Debug Interface -+** See Copyright Notice in lua.h -+*/ -+ -+ -+#include -+#include -+#include -+ -+#define ldebug_c -+#define LUA_CORE -+ -+#include "lua.h" -+ -+#include "lapi.h" -+#include "lcode.h" -+#include "ldebug.h" -+#include "ldo.h" -+#include "lfunc.h" -+#include "lobject.h" -+#include "lopcodes.h" -+#include "lstate.h" -+#include "lstring.h" -+#include "ltable.h" -+#include "ltm.h" -+#include "lvm.h" -+ -+ -+ -+static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name); -+ -+ -+static int currentpc (lua_State *L, CallInfo *ci) { -+ if (!isLua(ci)) return -1; /* function is not a Lua function? */ -+ if (ci == L->ci) -+ ci->savedpc = L->savedpc; -+ return pcRel(ci->savedpc, ci_func(ci)->l.p); -+} -+ -+ -+static int currentline (lua_State *L, CallInfo *ci) { -+ int pc = currentpc(L, ci); -+ if (pc < 0) -+ return -1; /* only active lua functions have current-line information */ -+ else -+ return getline(ci_func(ci)->l.p, pc); -+} -+ -+ -+/* -+** this function can be called asynchronous (e.g. during a signal) -+*/ -+LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count) { -+ if (func == NULL || mask == 0) { /* turn off hooks? */ -+ mask = 0; -+ func = NULL; -+ } -+ L->hook = func; -+ L->basehookcount = count; -+ resethookcount(L); -+ L->hookmask = cast_byte(mask); -+ return 1; -+} -+ -+ -+LUA_API lua_Hook lua_gethook (lua_State *L) { -+ return L->hook; -+} -+ -+ -+LUA_API int lua_gethookmask (lua_State *L) { -+ return L->hookmask; -+} -+ -+ -+LUA_API int lua_gethookcount (lua_State *L) { -+ return L->basehookcount; -+} -+ -+ -+LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { -+ int status; -+ CallInfo *ci; -+ lua_lock(L); -+ for (ci = L->ci; level > 0 && ci > L->base_ci; ci--) { -+ level--; -+ if (f_isLua(ci)) /* Lua function? */ -+ level -= ci->tailcalls; /* skip lost tail calls */ -+ } -+ if (level == 0 && ci > L->base_ci) { /* level found? */ -+ status = 1; -+ ar->i_ci = cast_int(ci - L->base_ci); -+ } -+ else if (level < 0) { /* level is of a lost tail call? */ -+ status = 1; -+ ar->i_ci = 0; -+ } -+ else status = 0; /* no such level */ -+ lua_unlock(L); -+ return status; -+} -+ -+ -+static Proto *getluaproto (CallInfo *ci) { -+ return (isLua(ci) ? ci_func(ci)->l.p : NULL); -+} -+ -+ -+static const char *findlocal (lua_State *L, CallInfo *ci, int n) { -+ const char *name; -+ Proto *fp = getluaproto(ci); -+ if (fp && (name = luaF_getlocalname(fp, n, currentpc(L, ci))) != NULL) -+ return name; /* is a local variable in a Lua function */ -+ else { -+ StkId limit = (ci == L->ci) ? L->top : (ci+1)->func; -+ if (limit - ci->base >= n && n > 0) /* is 'n' inside 'ci' stack? */ -+ return "(*temporary)"; -+ else -+ return NULL; -+ } -+} -+ -+ -+LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { -+ CallInfo *ci = L->base_ci + ar->i_ci; -+ const char *name = findlocal(L, ci, n); -+ lua_lock(L); -+ if (name) -+ luaA_pushobject(L, ci->base + (n - 1)); -+ lua_unlock(L); -+ return name; -+} -+ -+ -+LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { -+ CallInfo *ci = L->base_ci + ar->i_ci; -+ const char *name = findlocal(L, ci, n); -+ lua_lock(L); -+ if (name) -+ setobjs2s(L, ci->base + (n - 1), L->top - 1); -+ L->top--; /* pop value */ -+ lua_unlock(L); -+ return name; -+} -+ -+ -+static void funcinfo (lua_Debug *ar, Closure *cl) { -+ if (cl->c.isC) { -+ ar->source = "=[C]"; -+ ar->linedefined = -1; -+ ar->lastlinedefined = -1; -+ ar->what = "C"; -+ } -+ else { -+ ar->source = getstr(cl->l.p->source); -+ ar->linedefined = cl->l.p->linedefined; -+ ar->lastlinedefined = cl->l.p->lastlinedefined; -+ ar->what = (ar->linedefined == 0) ? "main" : "Lua"; -+ } -+ luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); -+} -+ -+ -+static void info_tailcall (lua_Debug *ar) { -+ ar->name = ar->namewhat = ""; -+ ar->what = "tail"; -+ ar->lastlinedefined = ar->linedefined = ar->currentline = -1; -+ ar->source = "=(tail call)"; -+ luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); -+ ar->nups = 0; -+} -+ -+ -+static void collectvalidlines (lua_State *L, Closure *f) { -+ if (f == NULL || f->c.isC) { -+ setnilvalue(L->top); -+ } -+ else { -+ Table *t = luaH_new(L, 0, 0); -+ int *lineinfo = f->l.p->lineinfo; -+ int i; -+ for (i=0; il.p->sizelineinfo; i++) -+ setbvalue(luaH_setnum(L, t, lineinfo[i]), 1); -+ sethvalue(L, L->top, t); -+ } -+ incr_top(L); -+} -+ -+ -+static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, -+ Closure *f, CallInfo *ci) { -+ int status = 1; -+ if (f == NULL) { -+ info_tailcall(ar); -+ return status; -+ } -+ for (; *what; what++) { -+ switch (*what) { -+ case 'S': { -+ funcinfo(ar, f); -+ break; -+ } -+ case 'l': { -+ ar->currentline = (ci) ? currentline(L, ci) : -1; -+ break; -+ } -+ case 'u': { -+ ar->nups = f->c.nupvalues; -+ break; -+ } -+ case 'n': { -+ ar->namewhat = (ci) ? getfuncname(L, ci, &ar->name) : NULL; -+ if (ar->namewhat == NULL) { -+ ar->namewhat = ""; /* not found */ -+ ar->name = NULL; -+ } -+ break; -+ } -+ case 'L': -+ case 'f': /* handled by lua_getinfo */ -+ break; -+ default: status = 0; /* invalid option */ -+ } -+ } -+ return status; -+} -+ -+ -+LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { -+ int status; -+ Closure *f = NULL; -+ CallInfo *ci = NULL; -+ lua_lock(L); -+ if (*what == '>') { -+ StkId func = L->top - 1; -+ luai_apicheck(L, ttisfunction(func)); -+ what++; /* skip the '>' */ -+ f = clvalue(func); -+ L->top--; /* pop function */ -+ } -+ else if (ar->i_ci != 0) { /* no tail call? */ -+ ci = L->base_ci + ar->i_ci; -+ lua_assert(ttisfunction(ci->func)); -+ f = clvalue(ci->func); -+ } -+ status = auxgetinfo(L, what, ar, f, ci); -+ if (strchr(what, 'f')) { -+ if (f == NULL) setnilvalue(L->top); -+ else setclvalue(L, L->top, f); -+ incr_top(L); -+ } -+ if (strchr(what, 'L')) -+ collectvalidlines(L, f); -+ lua_unlock(L); -+ return status; -+} -+ -+ -+/* -+** {====================================================== -+** Symbolic Execution and code checker -+** ======================================================= -+*/ -+ -+#define check(x) if (!(x)) return 0; -+ -+#define checkjump(pt,pc) check(0 <= pc && pc < pt->sizecode) -+ -+#define checkreg(pt,reg) check((reg) < (pt)->maxstacksize) -+ -+ -+ -+static int precheck (const Proto *pt) { -+ check(pt->maxstacksize <= MAXSTACK); -+ check(pt->numparams+(pt->is_vararg & VARARG_HASARG) <= pt->maxstacksize); -+ check(!(pt->is_vararg & VARARG_NEEDSARG) || -+ (pt->is_vararg & VARARG_HASARG)); -+ check(pt->sizeupvalues <= pt->nups); -+ check(pt->sizelineinfo == pt->sizecode || pt->sizelineinfo == 0); -+ check(pt->sizecode > 0 && GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN); -+ return 1; -+} -+ -+ -+#define checkopenop(pt,pc) luaG_checkopenop((pt)->code[(pc)+1]) -+ -+int luaG_checkopenop (Instruction i) { -+ switch (GET_OPCODE(i)) { -+ case OP_CALL: -+ case OP_TAILCALL: -+ case OP_RETURN: -+ case OP_SETLIST: { -+ check(GETARG_B(i) == 0); -+ return 1; -+ } -+ default: return 0; /* invalid instruction after an open call */ -+ } -+} -+ -+ -+static int checkArgMode (const Proto *pt, int r, enum OpArgMask mode) { -+ switch (mode) { -+ case OpArgN: check(r == 0); break; -+ case OpArgU: break; -+ case OpArgR: checkreg(pt, r); break; -+ case OpArgK: -+ check(ISK(r) ? INDEXK(r) < pt->sizek : r < pt->maxstacksize); -+ break; -+ } -+ return 1; -+} -+ -+ -+static Instruction symbexec (const Proto *pt, int lastpc, int reg) { -+ int pc; -+ int last; /* stores position of last instruction that changed `reg' */ -+ last = pt->sizecode-1; /* points to final return (a `neutral' instruction) */ -+ check(precheck(pt)); -+ for (pc = 0; pc < lastpc; pc++) { -+ Instruction i = pt->code[pc]; -+ OpCode op = GET_OPCODE(i); -+ int a = GETARG_A(i); -+ int b = 0; -+ int c = 0; -+ check(op < NUM_OPCODES); -+ checkreg(pt, a); -+ switch (getOpMode(op)) { -+ case iABC: { -+ b = GETARG_B(i); -+ c = GETARG_C(i); -+ check(checkArgMode(pt, b, getBMode(op))); -+ check(checkArgMode(pt, c, getCMode(op))); -+ break; -+ } -+ case iABx: { -+ b = GETARG_Bx(i); -+ if (getBMode(op) == OpArgK) check(b < pt->sizek); -+ break; -+ } -+ case iAsBx: { -+ b = GETARG_sBx(i); -+ if (getBMode(op) == OpArgR) { -+ int dest = pc+1+b; -+ check(0 <= dest && dest < pt->sizecode); -+ if (dest > 0) { -+ int j; -+ /* check that it does not jump to a setlist count; this -+ is tricky, because the count from a previous setlist may -+ have the same value of an invalid setlist; so, we must -+ go all the way back to the first of them (if any) */ -+ for (j = 0; j < dest; j++) { -+ Instruction d = pt->code[dest-1-j]; -+ if (!(GET_OPCODE(d) == OP_SETLIST && GETARG_C(d) == 0)) break; -+ } -+ /* if 'j' is even, previous value is not a setlist (even if -+ it looks like one) */ -+ check((j&1) == 0); -+ } -+ } -+ break; -+ } -+ } -+ if (testAMode(op)) { -+ if (a == reg) last = pc; /* change register `a' */ -+ } -+ if (testTMode(op)) { -+ check(pc+2 < pt->sizecode); /* check skip */ -+ check(GET_OPCODE(pt->code[pc+1]) == OP_JMP); -+ } -+ switch (op) { -+ case OP_LOADBOOL: { -+ if (c == 1) { /* does it jump? */ -+ check(pc+2 < pt->sizecode); /* check its jump */ -+ check(GET_OPCODE(pt->code[pc+1]) != OP_SETLIST || -+ GETARG_C(pt->code[pc+1]) != 0); -+ } -+ break; -+ } -+ case OP_LOADNIL: { -+ if (a <= reg && reg <= b) -+ last = pc; /* set registers from `a' to `b' */ -+ break; -+ } -+ case OP_GETUPVAL: -+ case OP_SETUPVAL: { -+ check(b < pt->nups); -+ break; -+ } -+ case OP_GETGLOBAL: -+ case OP_SETGLOBAL: { -+ check(ttisstring(&pt->k[b])); -+ break; -+ } -+ case OP_SELF: { -+ checkreg(pt, a+1); -+ if (reg == a+1) last = pc; -+ break; -+ } -+ case OP_CONCAT: { -+ check(b < c); /* at least two operands */ -+ break; -+ } -+ case OP_TFORLOOP: { -+ check(c >= 1); /* at least one result (control variable) */ -+ checkreg(pt, a+2+c); /* space for results */ -+ if (reg >= a+2) last = pc; /* affect all regs above its base */ -+ break; -+ } -+ case OP_FORLOOP: -+ case OP_FORPREP: -+ checkreg(pt, a+3); -+ /* go through */ -+ case OP_JMP: { -+ int dest = pc+1+b; -+ /* not full check and jump is forward and do not skip `lastpc'? */ -+ if (reg != NO_REG && pc < dest && dest <= lastpc) -+ pc += b; /* do the jump */ -+ break; -+ } -+ case OP_CALL: -+ case OP_TAILCALL: { -+ if (b != 0) { -+ checkreg(pt, a+b-1); -+ } -+ c--; /* c = num. returns */ -+ if (c == LUA_MULTRET) { -+ check(checkopenop(pt, pc)); -+ } -+ else if (c != 0) -+ checkreg(pt, a+c-1); -+ if (reg >= a) last = pc; /* affect all registers above base */ -+ break; -+ } -+ case OP_RETURN: { -+ b--; /* b = num. returns */ -+ if (b > 0) checkreg(pt, a+b-1); -+ break; -+ } -+ case OP_SETLIST: { -+ if (b > 0) checkreg(pt, a + b); -+ if (c == 0) { -+ pc++; -+ check(pc < pt->sizecode - 1); -+ } -+ break; -+ } -+ case OP_CLOSURE: { -+ int nup, j; -+ check(b < pt->sizep); -+ nup = pt->p[b]->nups; -+ check(pc + nup < pt->sizecode); -+ for (j = 1; j <= nup; j++) { -+ OpCode op1 = GET_OPCODE(pt->code[pc + j]); -+ check(op1 == OP_GETUPVAL || op1 == OP_MOVE); -+ } -+ if (reg != NO_REG) /* tracing? */ -+ pc += nup; /* do not 'execute' these pseudo-instructions */ -+ break; -+ } -+ case OP_VARARG: { -+ check((pt->is_vararg & VARARG_ISVARARG) && -+ !(pt->is_vararg & VARARG_NEEDSARG)); -+ b--; -+ if (b == LUA_MULTRET) check(checkopenop(pt, pc)); -+ checkreg(pt, a+b-1); -+ break; -+ } -+ default: break; -+ } -+ } -+ return pt->code[last]; -+} -+ -+#undef check -+#undef checkjump -+#undef checkreg -+ -+/* }====================================================== */ -+ -+ -+int luaG_checkcode (const Proto *pt) { -+ return (symbexec(pt, pt->sizecode, NO_REG) != 0); -+} -+ -+ -+static const char *kname (Proto *p, int c) { -+ if (ISK(c) && ttisstring(&p->k[INDEXK(c)])) -+ return svalue(&p->k[INDEXK(c)]); -+ else -+ return "?"; -+} -+ -+ -+static const char *getobjname (lua_State *L, CallInfo *ci, int stackpos, -+ const char **name) { -+ if (isLua(ci)) { /* a Lua function? */ -+ Proto *p = ci_func(ci)->l.p; -+ int pc = currentpc(L, ci); -+ Instruction i; -+ *name = luaF_getlocalname(p, stackpos+1, pc); -+ if (*name) /* is a local? */ -+ return "local"; -+ i = symbexec(p, pc, stackpos); /* try symbolic execution */ -+ lua_assert(pc != -1); -+ switch (GET_OPCODE(i)) { -+ case OP_GETGLOBAL: { -+ int g = GETARG_Bx(i); /* global index */ -+ lua_assert(ttisstring(&p->k[g])); -+ *name = svalue(&p->k[g]); -+ return "global"; -+ } -+ case OP_MOVE: { -+ int a = GETARG_A(i); -+ int b = GETARG_B(i); /* move from `b' to `a' */ -+ if (b < a) -+ return getobjname(L, ci, b, name); /* get name for `b' */ -+ break; -+ } -+ case OP_GETTABLE: { -+ int k = GETARG_C(i); /* key index */ -+ *name = kname(p, k); -+ return "field"; -+ } -+ case OP_GETUPVAL: { -+ int u = GETARG_B(i); /* upvalue index */ -+ *name = p->upvalues ? getstr(p->upvalues[u]) : "?"; -+ return "upvalue"; -+ } -+ case OP_SELF: { -+ int k = GETARG_C(i); /* key index */ -+ *name = kname(p, k); -+ return "method"; -+ } -+ default: break; -+ } -+ } -+ return NULL; /* no useful name found */ -+} -+ -+ -+static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { -+ Instruction i; -+ if ((isLua(ci) && ci->tailcalls > 0) || !isLua(ci - 1)) -+ return NULL; /* calling function is not Lua (or is unknown) */ -+ ci--; /* calling function */ -+ i = ci_func(ci)->l.p->code[currentpc(L, ci)]; -+ if (GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL || -+ GET_OPCODE(i) == OP_TFORLOOP) -+ return getobjname(L, ci, GETARG_A(i), name); -+ else -+ return NULL; /* no useful name can be found */ -+} -+ -+ -+/* only ANSI way to check whether a pointer points to an array */ -+static int isinstack (CallInfo *ci, const TValue *o) { -+ StkId p; -+ for (p = ci->base; p < ci->top; p++) -+ if (o == p) return 1; -+ return 0; -+} -+ -+ -+void luaG_typeerror (lua_State *L, const TValue *o, const char *op) { -+ const char *name = NULL; -+ const char *t = luaT_typenames[ttype(o)]; -+ const char *kind = (isinstack(L->ci, o)) ? -+ getobjname(L, L->ci, cast_int(o - L->base), &name) : -+ NULL; -+ if (kind) -+ luaG_runerror(L, "attempt to %s %s " LUA_QS " (a %s value)", -+ op, kind, name, t); -+ else -+ luaG_runerror(L, "attempt to %s a %s value", op, t); -+} -+ -+ -+void luaG_concaterror (lua_State *L, StkId p1, StkId p2) { -+ if (ttisstring(p1) || ttisnumber(p1)) p1 = p2; -+ lua_assert(!ttisstring(p1) && !ttisnumber(p1)); -+ luaG_typeerror(L, p1, "concatenate"); -+} -+ -+ -+void luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) { -+ TValue temp; -+ if (luaV_tonumber(p1, &temp) == NULL) -+ p2 = p1; /* first operand is wrong */ -+ luaG_typeerror(L, p2, "perform arithmetic on"); -+} -+ -+ -+int luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) { -+ const char *t1 = luaT_typenames[ttype(p1)]; -+ const char *t2 = luaT_typenames[ttype(p2)]; -+ if (t1[2] == t2[2]) -+ luaG_runerror(L, "attempt to compare two %s values", t1); -+ else -+ luaG_runerror(L, "attempt to compare %s with %s", t1, t2); -+ return 0; -+} -+ -+ -+static void addinfo (lua_State *L, const char *msg) { -+ CallInfo *ci = L->ci; -+ if (isLua(ci)) { /* is Lua code? */ -+ char buff[LUA_IDSIZE]; /* add file:line information */ -+ int line = currentline(L, ci); -+ luaO_chunkid(buff, getstr(getluaproto(ci)->source), LUA_IDSIZE); -+ luaO_pushfstring(L, "%s:%d: %s", buff, line, msg); -+ } -+} -+ -+ -+void luaG_errormsg (lua_State *L) { -+ if (L->errfunc != 0) { /* is there an error handling function? */ -+ StkId errfunc = restorestack(L, L->errfunc); -+ if (!ttisfunction(errfunc)) luaD_throw(L, LUA_ERRERR); -+ setobjs2s(L, L->top, L->top - 1); /* move argument */ -+ setobjs2s(L, L->top - 1, errfunc); /* push function */ -+ incr_top(L); -+ luaD_call(L, L->top - 2, 1); /* call it */ -+ } -+ luaD_throw(L, LUA_ERRRUN); -+} -+ -+ -+void luaG_runerror (lua_State *L, const char *fmt, ...) { -+ va_list argp; -+ va_start(argp, fmt); -+ addinfo(L, luaO_pushvfstring(L, fmt, argp)); -+ va_end(argp); -+ luaG_errormsg(L); -+} -+ ---- /dev/null -+++ b/extensions/LUA/lua/ldebug.h -@@ -0,0 +1,33 @@ -+/* -+** $Id: ldebug.h,v 2.3.1.1 2007/12/27 13:02:25 roberto Exp $ -+** Auxiliary functions from Debug Interface module -+** See Copyright Notice in lua.h -+*/ -+ -+#ifndef ldebug_h -+#define ldebug_h -+ -+ -+#include "lstate.h" -+ -+ -+#define pcRel(pc, p) (cast(int, (pc) - (p)->code) - 1) -+ -+#define getline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : 0) -+ -+#define resethookcount(L) (L->hookcount = L->basehookcount) -+ -+ -+LUAI_FUNC void luaG_typeerror (lua_State *L, const TValue *o, -+ const char *opname); -+LUAI_FUNC void luaG_concaterror (lua_State *L, StkId p1, StkId p2); -+LUAI_FUNC void luaG_aritherror (lua_State *L, const TValue *p1, -+ const TValue *p2); -+LUAI_FUNC int luaG_ordererror (lua_State *L, const TValue *p1, -+ const TValue *p2); -+LUAI_FUNC void luaG_runerror (lua_State *L, const char *fmt, ...); -+LUAI_FUNC void luaG_errormsg (lua_State *L); -+LUAI_FUNC int luaG_checkcode (const Proto *pt); -+LUAI_FUNC int luaG_checkopenop (Instruction i); -+ -+#endif ---- /dev/null -+++ b/extensions/LUA/lua/ldo.c -@@ -0,0 +1,515 @@ -+/* -+** $Id: ldo.c,v 2.38.1.3 2008/01/18 22:31:22 roberto Exp $ -+** Stack and Call structure of Lua -+** See Copyright Notice in lua.h -+*/ -+ -+#include -+#include -+#include -+ -+#define ldo_c -+#define LUA_CORE -+ -+#include "lua.h" -+ -+#include "ldebug.h" -+#include "ldo.h" -+#include "lfunc.h" -+#include "lgc.h" -+#include "lmem.h" -+#include "lobject.h" -+#include "lopcodes.h" -+#include "lparser.h" -+#include "lstate.h" -+#include "lstring.h" -+#include "ltable.h" -+#include "ltm.h" -+#include "lundump.h" -+#include "lvm.h" -+#include "lzio.h" -+ -+ -+ -+/* -+** {====================================================== -+** Error-recovery functions -+** ======================================================= -+*/ -+ -+ -+/* chain list of long jump buffers */ -+struct lua_longjmp { -+ struct lua_longjmp *previous; -+ luai_jmpbuf b; -+ volatile int status; /* error code */ -+}; -+ -+ -+void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) { -+ switch (errcode) { -+ case LUA_ERRMEM: { -+ setsvalue2s(L, oldtop, luaS_newliteral(L, MEMERRMSG)); -+ break; -+ } -+ case LUA_ERRERR: { -+ setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling")); -+ break; -+ } -+ case LUA_ERRSYNTAX: -+ case LUA_ERRRUN: { -+ setobjs2s(L, oldtop, L->top - 1); /* error message on current top */ -+ break; -+ } -+ } -+ L->top = oldtop + 1; -+} -+ -+ -+static void restore_stack_limit (lua_State *L) { -+ lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1); -+ if (L->size_ci > LUAI_MAXCALLS) { /* there was an overflow? */ -+ int inuse = cast_int(L->ci - L->base_ci); -+ if (inuse + 1 < LUAI_MAXCALLS) /* can `undo' overflow? */ -+ luaD_reallocCI(L, LUAI_MAXCALLS); -+ } -+} -+ -+ -+static void resetstack (lua_State *L, int status) { -+ L->ci = L->base_ci; -+ L->base = L->ci->base; -+ luaF_close(L, L->base); /* close eventual pending closures */ -+ luaD_seterrorobj(L, status, L->base); -+ L->nCcalls = L->baseCcalls; -+ L->allowhook = 1; -+ restore_stack_limit(L); -+ L->errfunc = 0; -+ L->errorJmp = NULL; -+} -+ -+ -+void luaD_throw (lua_State *L, int errcode) { -+ if (L->errorJmp) { -+ L->errorJmp->status = errcode; -+ LUAI_THROW(L, L->errorJmp); -+ } -+ else { -+ L->status = cast_byte(errcode); -+ if (G(L)->panic) { -+ resetstack(L, errcode); -+ lua_unlock(L); -+ G(L)->panic(L); -+ } -+ exit(EXIT_FAILURE); -+ } -+} -+ -+ -+int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { -+ struct lua_longjmp lj; -+ lj.status = 0; -+ lj.previous = L->errorJmp; /* chain new error handler */ -+ L->errorJmp = &lj; -+ LUAI_TRY(L, &lj, -+ (*f)(L, ud); -+ ); -+ L->errorJmp = lj.previous; /* restore old error handler */ -+ return lj.status; -+} -+ -+/* }====================================================== */ -+ -+ -+static void correctstack (lua_State *L, TValue *oldstack) { -+ CallInfo *ci; -+ GCObject *up; -+ L->top = (L->top - oldstack) + L->stack; -+ for (up = L->openupval; up != NULL; up = up->gch.next) -+ gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack; -+ for (ci = L->base_ci; ci <= L->ci; ci++) { -+ ci->top = (ci->top - oldstack) + L->stack; -+ ci->base = (ci->base - oldstack) + L->stack; -+ ci->func = (ci->func - oldstack) + L->stack; -+ } -+ L->base = (L->base - oldstack) + L->stack; -+} -+ -+ -+void luaD_reallocstack (lua_State *L, int newsize) { -+ TValue *oldstack = L->stack; -+ int realsize = newsize + 1 + EXTRA_STACK; -+ lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1); -+ luaM_reallocvector(L, L->stack, L->stacksize, realsize, TValue); -+ L->stacksize = realsize; -+ L->stack_last = L->stack+newsize; -+ correctstack(L, oldstack); -+} -+ -+ -+void luaD_reallocCI (lua_State *L, int newsize) { -+ CallInfo *oldci = L->base_ci; -+ luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo); -+ L->size_ci = newsize; -+ L->ci = (L->ci - oldci) + L->base_ci; -+ L->end_ci = L->base_ci + L->size_ci - 1; -+} -+ -+ -+void luaD_growstack (lua_State *L, int n) { -+ if (n <= L->stacksize) /* double size is enough? */ -+ luaD_reallocstack(L, 2*L->stacksize); -+ else -+ luaD_reallocstack(L, L->stacksize + n); -+} -+ -+ -+static CallInfo *growCI (lua_State *L) { -+ if (L->size_ci > LUAI_MAXCALLS) /* overflow while handling overflow? */ -+ luaD_throw(L, LUA_ERRERR); -+ else { -+ luaD_reallocCI(L, 2*L->size_ci); -+ if (L->size_ci > LUAI_MAXCALLS) -+ luaG_runerror(L, "stack overflow"); -+ } -+ return ++L->ci; -+} -+ -+ -+void luaD_callhook (lua_State *L, int event, int line) { -+ lua_Hook hook = L->hook; -+ if (hook && L->allowhook) { -+ ptrdiff_t top = savestack(L, L->top); -+ ptrdiff_t ci_top = savestack(L, L->ci->top); -+ lua_Debug ar; -+ ar.event = event; -+ ar.currentline = line; -+ if (event == LUA_HOOKTAILRET) -+ ar.i_ci = 0; /* tail call; no debug information about it */ -+ else -+ ar.i_ci = cast_int(L->ci - L->base_ci); -+ luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ -+ L->ci->top = L->top + LUA_MINSTACK; -+ lua_assert(L->ci->top <= L->stack_last); -+ L->allowhook = 0; /* cannot call hooks inside a hook */ -+ lua_unlock(L); -+ (*hook)(L, &ar); -+ lua_lock(L); -+ lua_assert(!L->allowhook); -+ L->allowhook = 1; -+ L->ci->top = restorestack(L, ci_top); -+ L->top = restorestack(L, top); -+ } -+} -+ -+ -+static StkId adjust_varargs (lua_State *L, Proto *p, int actual) { -+ int i; -+ int nfixargs = p->numparams; -+ Table *htab = NULL; -+ StkId base, fixed; -+ for (; actual < nfixargs; ++actual) -+ setnilvalue(L->top++); -+#if defined(LUA_COMPAT_VARARG) -+ if (p->is_vararg & VARARG_NEEDSARG) { /* compat. with old-style vararg? */ -+ int nvar = actual - nfixargs; /* number of extra arguments */ -+ lua_assert(p->is_vararg & VARARG_HASARG); -+ luaC_checkGC(L); -+ htab = luaH_new(L, nvar, 1); /* create `arg' table */ -+ for (i=0; itop - nvar + i); -+ /* store counter in field `n' */ -+ setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), cast_num(nvar)); -+ } -+#endif -+ /* move fixed parameters to final position */ -+ fixed = L->top - actual; /* first fixed argument */ -+ base = L->top; /* final position of first argument */ -+ for (i=0; itop++, fixed+i); -+ setnilvalue(fixed+i); -+ } -+ /* add `arg' parameter */ -+ if (htab) { -+ sethvalue(L, L->top++, htab); -+ lua_assert(iswhite(obj2gco(htab))); -+ } -+ return base; -+} -+ -+ -+static StkId tryfuncTM (lua_State *L, StkId func) { -+ const TValue *tm = luaT_gettmbyobj(L, func, TM_CALL); -+ StkId p; -+ ptrdiff_t funcr = savestack(L, func); -+ if (!ttisfunction(tm)) -+ luaG_typeerror(L, func, "call"); -+ /* Open a hole inside the stack at `func' */ -+ for (p = L->top; p > func; p--) setobjs2s(L, p, p-1); -+ incr_top(L); -+ func = restorestack(L, funcr); /* previous call may change stack */ -+ setobj2s(L, func, tm); /* tag method is the new function to be called */ -+ return func; -+} -+ -+ -+ -+#define inc_ci(L) \ -+ ((L->ci == L->end_ci) ? growCI(L) : \ -+ (condhardstacktests(luaD_reallocCI(L, L->size_ci)), ++L->ci)) -+ -+ -+int luaD_precall (lua_State *L, StkId func, int nresults) { -+ LClosure *cl; -+ ptrdiff_t funcr; -+ if (!ttisfunction(func)) /* `func' is not a function? */ -+ func = tryfuncTM(L, func); /* check the `function' tag method */ -+ funcr = savestack(L, func); -+ cl = &clvalue(func)->l; -+ L->ci->savedpc = L->savedpc; -+ if (!cl->isC) { /* Lua function? prepare its call */ -+ CallInfo *ci; -+ StkId st, base; -+ Proto *p = cl->p; -+ luaD_checkstack(L, p->maxstacksize); -+ func = restorestack(L, funcr); -+ if (!p->is_vararg) { /* no varargs? */ -+ base = func + 1; -+ if (L->top > base + p->numparams) -+ L->top = base + p->numparams; -+ } -+ else { /* vararg function */ -+ int nargs = cast_int(L->top - func) - 1; -+ base = adjust_varargs(L, p, nargs); -+ func = restorestack(L, funcr); /* previous call may change the stack */ -+ } -+ ci = inc_ci(L); /* now `enter' new function */ -+ ci->func = func; -+ L->base = ci->base = base; -+ ci->top = L->base + p->maxstacksize; -+ lua_assert(ci->top <= L->stack_last); -+ L->savedpc = p->code; /* starting point */ -+ ci->tailcalls = 0; -+ ci->nresults = nresults; -+ for (st = L->top; st < ci->top; st++) -+ setnilvalue(st); -+ L->top = ci->top; -+ if (L->hookmask & LUA_MASKCALL) { -+ L->savedpc++; /* hooks assume 'pc' is already incremented */ -+ luaD_callhook(L, LUA_HOOKCALL, -1); -+ L->savedpc--; /* correct 'pc' */ -+ } -+ return PCRLUA; -+ } -+ else { /* if is a C function, call it */ -+ CallInfo *ci; -+ int n; -+ luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ -+ ci = inc_ci(L); /* now `enter' new function */ -+ ci->func = restorestack(L, funcr); -+ L->base = ci->base = ci->func + 1; -+ ci->top = L->top + LUA_MINSTACK; -+ lua_assert(ci->top <= L->stack_last); -+ ci->nresults = nresults; -+ if (L->hookmask & LUA_MASKCALL) -+ luaD_callhook(L, LUA_HOOKCALL, -1); -+ lua_unlock(L); -+ n = (*curr_func(L)->c.f)(L); /* do the actual call */ -+ lua_lock(L); -+ if (n < 0) /* yielding? */ -+ return PCRYIELD; -+ else { -+ luaD_poscall(L, L->top - n); -+ return PCRC; -+ } -+ } -+} -+ -+ -+static StkId callrethooks (lua_State *L, StkId firstResult) { -+ ptrdiff_t fr = savestack(L, firstResult); /* next call may change stack */ -+ luaD_callhook(L, LUA_HOOKRET, -1); -+ if (f_isLua(L->ci)) { /* Lua function? */ -+ while ((L->hookmask & LUA_MASKRET) && L->ci->tailcalls--) /* tail calls */ -+ luaD_callhook(L, LUA_HOOKTAILRET, -1); -+ } -+ return restorestack(L, fr); -+} -+ -+ -+int luaD_poscall (lua_State *L, StkId firstResult) { -+ StkId res; -+ int wanted, i; -+ CallInfo *ci; -+ if (L->hookmask & LUA_MASKRET) -+ firstResult = callrethooks(L, firstResult); -+ ci = L->ci--; -+ res = ci->func; /* res == final position of 1st result */ -+ wanted = ci->nresults; -+ L->base = (ci - 1)->base; /* restore base */ -+ L->savedpc = (ci - 1)->savedpc; /* restore savedpc */ -+ /* move results to correct place */ -+ for (i = wanted; i != 0 && firstResult < L->top; i--) -+ setobjs2s(L, res++, firstResult++); -+ while (i-- > 0) -+ setnilvalue(res++); -+ L->top = res; -+ return (wanted - LUA_MULTRET); /* 0 iff wanted == LUA_MULTRET */ -+} -+ -+ -+/* -+** Call a function (C or Lua). The function to be called is at *func. -+** The arguments are on the stack, right after the function. -+** When returns, all the results are on the stack, starting at the original -+** function position. -+*/ -+void luaD_call (lua_State *L, StkId func, int nResults) { -+ if (++L->nCcalls >= LUAI_MAXCCALLS) { -+ if (L->nCcalls == LUAI_MAXCCALLS) -+ luaG_runerror(L, "C stack overflow"); -+ else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3))) -+ luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ -+ } -+ if (luaD_precall(L, func, nResults) == PCRLUA) /* is a Lua function? */ -+ luaV_execute(L, 1); /* call it */ -+ L->nCcalls--; -+ luaC_checkGC(L); -+} -+ -+ -+static void resume (lua_State *L, void *ud) { -+ StkId firstArg = cast(StkId, ud); -+ CallInfo *ci = L->ci; -+ if (L->status == 0) { /* start coroutine? */ -+ lua_assert(ci == L->base_ci && firstArg > L->base); -+ if (luaD_precall(L, firstArg - 1, LUA_MULTRET) != PCRLUA) -+ return; -+ } -+ else { /* resuming from previous yield */ -+ lua_assert(L->status == LUA_YIELD); -+ L->status = 0; -+ if (!f_isLua(ci)) { /* `common' yield? */ -+ /* finish interrupted execution of `OP_CALL' */ -+ lua_assert(GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_CALL || -+ GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_TAILCALL); -+ if (luaD_poscall(L, firstArg)) /* complete it... */ -+ L->top = L->ci->top; /* and correct top if not multiple results */ -+ } -+ else /* yielded inside a hook: just continue its execution */ -+ L->base = L->ci->base; -+ } -+ luaV_execute(L, cast_int(L->ci - L->base_ci)); -+} -+ -+ -+static int resume_error (lua_State *L, const char *msg) { -+ L->top = L->ci->base; -+ setsvalue2s(L, L->top, luaS_new(L, msg)); -+ incr_top(L); -+ lua_unlock(L); -+ return LUA_ERRRUN; -+} -+ -+ -+LUA_API int lua_resume (lua_State *L, int nargs) { -+ int status; -+ lua_lock(L); -+ if (L->status != LUA_YIELD && (L->status != 0 || L->ci != L->base_ci)) -+ return resume_error(L, "cannot resume non-suspended coroutine"); -+ if (L->nCcalls >= LUAI_MAXCCALLS) -+ return resume_error(L, "C stack overflow"); -+ luai_userstateresume(L, nargs); -+ lua_assert(L->errfunc == 0); -+ L->baseCcalls = ++L->nCcalls; -+ status = luaD_rawrunprotected(L, resume, L->top - nargs); -+ if (status != 0) { /* error? */ -+ L->status = cast_byte(status); /* mark thread as `dead' */ -+ luaD_seterrorobj(L, status, L->top); -+ L->ci->top = L->top; -+ } -+ else { -+ lua_assert(L->nCcalls == L->baseCcalls); -+ status = L->status; -+ } -+ --L->nCcalls; -+ lua_unlock(L); -+ return status; -+} -+ -+ -+LUA_API int lua_yield (lua_State *L, int nresults) { -+ luai_userstateyield(L, nresults); -+ lua_lock(L); -+ if (L->nCcalls > L->baseCcalls) -+ luaG_runerror(L, "attempt to yield across metamethod/C-call boundary"); -+ L->base = L->top - nresults; /* protect stack slots below */ -+ L->status = LUA_YIELD; -+ lua_unlock(L); -+ return -1; -+} -+ -+ -+int luaD_pcall (lua_State *L, Pfunc func, void *u, -+ ptrdiff_t old_top, ptrdiff_t ef) { -+ int status; -+ unsigned short oldnCcalls = L->nCcalls; -+ ptrdiff_t old_ci = saveci(L, L->ci); -+ lu_byte old_allowhooks = L->allowhook; -+ ptrdiff_t old_errfunc = L->errfunc; -+ L->errfunc = ef; -+ status = luaD_rawrunprotected(L, func, u); -+ if (status != 0) { /* an error occurred? */ -+ StkId oldtop = restorestack(L, old_top); -+ luaF_close(L, oldtop); /* close eventual pending closures */ -+ luaD_seterrorobj(L, status, oldtop); -+ L->nCcalls = oldnCcalls; -+ L->ci = restoreci(L, old_ci); -+ L->base = L->ci->base; -+ L->savedpc = L->ci->savedpc; -+ L->allowhook = old_allowhooks; -+ restore_stack_limit(L); -+ } -+ L->errfunc = old_errfunc; -+ return status; -+} -+ -+ -+ -+/* -+** Execute a protected parser. -+*/ -+struct SParser { /* data to `f_parser' */ -+ ZIO *z; -+ Mbuffer buff; /* buffer to be used by the scanner */ -+ const char *name; -+}; -+ -+static void f_parser (lua_State *L, void *ud) { -+ int i; -+ Proto *tf; -+ Closure *cl; -+ struct SParser *p = cast(struct SParser *, ud); -+ int c = luaZ_lookahead(p->z); -+ luaC_checkGC(L); -+ tf = ((c == LUA_SIGNATURE[0]) ? luaU_undump : luaY_parser)(L, p->z, -+ &p->buff, p->name); -+ cl = luaF_newLclosure(L, tf->nups, hvalue(gt(L))); -+ cl->l.p = tf; -+ for (i = 0; i < tf->nups; i++) /* initialize eventual upvalues */ -+ cl->l.upvals[i] = luaF_newupval(L); -+ setclvalue(L, L->top, cl); -+ incr_top(L); -+} -+ -+ -+int luaD_protectedparser (lua_State *L, ZIO *z, const char *name) { -+ struct SParser p; -+ int status; -+ p.z = z; p.name = name; -+ luaZ_initbuffer(L, &p.buff); -+ status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc); -+ luaZ_freebuffer(L, &p.buff); -+ return status; -+} -+ ---- /dev/null -+++ b/extensions/LUA/lua/ldo.h -@@ -0,0 +1,57 @@ -+/* -+** $Id: ldo.h,v 2.7.1.1 2007/12/27 13:02:25 roberto Exp $ -+** Stack and Call structure of Lua -+** See Copyright Notice in lua.h -+*/ -+ -+#ifndef ldo_h -+#define ldo_h -+ -+ -+#include "lobject.h" -+#include "lstate.h" -+#include "lzio.h" -+ -+ -+#define luaD_checkstack(L,n) \ -+ if ((char *)L->stack_last - (char *)L->top <= (n)*(int)sizeof(TValue)) \ -+ luaD_growstack(L, n); \ -+ else condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); -+ -+ -+#define incr_top(L) {luaD_checkstack(L,1); L->top++;} -+ -+#define savestack(L,p) ((char *)(p) - (char *)L->stack) -+#define restorestack(L,n) ((TValue *)((char *)L->stack + (n))) -+ -+#define saveci(L,p) ((char *)(p) - (char *)L->base_ci) -+#define restoreci(L,n) ((CallInfo *)((char *)L->base_ci + (n))) -+ -+ -+/* results from luaD_precall */ -+#define PCRLUA 0 /* initiated a call to a Lua function */ -+#define PCRC 1 /* did a call to a C function */ -+#define PCRYIELD 2 /* C funtion yielded */ -+ -+ -+/* type of protected functions, to be ran by `runprotected' */ -+typedef void (*Pfunc) (lua_State *L, void *ud); -+ -+LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name); -+LUAI_FUNC void luaD_callhook (lua_State *L, int event, int line); -+LUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults); -+LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults); -+LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u, -+ ptrdiff_t oldtop, ptrdiff_t ef); -+LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult); -+LUAI_FUNC void luaD_reallocCI (lua_State *L, int newsize); -+LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize); -+LUAI_FUNC void luaD_growstack (lua_State *L, int n); -+ -+LUAI_FUNC void luaD_throw (lua_State *L, int errcode); -+LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud); -+ -+LUAI_FUNC void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop); -+ -+#endif -+ ---- /dev/null -+++ b/extensions/LUA/lua/ldump.c -@@ -0,0 +1,164 @@ -+/* -+** $Id: ldump.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $ -+** save precompiled Lua chunks -+** See Copyright Notice in lua.h -+*/ -+ -+#include -+ -+#define ldump_c -+#define LUA_CORE -+ -+#include "lua.h" -+ -+#include "lobject.h" -+#include "lstate.h" -+#include "lundump.h" -+ -+typedef struct { -+ lua_State* L; -+ lua_Writer writer; -+ void* data; -+ int strip; -+ int status; -+} DumpState; -+ -+#define DumpMem(b,n,size,D) DumpBlock(b,(n)*(size),D) -+#define DumpVar(x,D) DumpMem(&x,1,sizeof(x),D) -+ -+static void DumpBlock(const void* b, size_t size, DumpState* D) -+{ -+ if (D->status==0) -+ { -+ lua_unlock(D->L); -+ D->status=(*D->writer)(D->L,b,size,D->data); -+ lua_lock(D->L); -+ } -+} -+ -+static void DumpChar(int y, DumpState* D) -+{ -+ char x=(char)y; -+ DumpVar(x,D); -+} -+ -+static void DumpInt(int x, DumpState* D) -+{ -+ DumpVar(x,D); -+} -+ -+static void DumpNumber(lua_Number x, DumpState* D) -+{ -+ DumpVar(x,D); -+} -+ -+static void DumpVector(const void* b, int n, size_t size, DumpState* D) -+{ -+ DumpInt(n,D); -+ DumpMem(b,n,size,D); -+} -+ -+static void DumpString(const TString* s, DumpState* D) -+{ -+ if (s==NULL || getstr(s)==NULL) -+ { -+ size_t size=0; -+ DumpVar(size,D); -+ } -+ else -+ { -+ size_t size=s->tsv.len+1; /* include trailing '\0' */ -+ DumpVar(size,D); -+ DumpBlock(getstr(s),size,D); -+ } -+} -+ -+#define DumpCode(f,D) DumpVector(f->code,f->sizecode,sizeof(Instruction),D) -+ -+static void DumpFunction(const Proto* f, const TString* p, DumpState* D); -+ -+static void DumpConstants(const Proto* f, DumpState* D) -+{ -+ int i,n=f->sizek; -+ DumpInt(n,D); -+ for (i=0; ik[i]; -+ DumpChar(ttype(o),D); -+ switch (ttype(o)) -+ { -+ case LUA_TNIL: -+ break; -+ case LUA_TBOOLEAN: -+ DumpChar(bvalue(o),D); -+ break; -+ case LUA_TNUMBER: -+ DumpNumber(nvalue(o),D); -+ break; -+ case LUA_TSTRING: -+ DumpString(rawtsvalue(o),D); -+ break; -+ default: -+ lua_assert(0); /* cannot happen */ -+ break; -+ } -+ } -+ n=f->sizep; -+ DumpInt(n,D); -+ for (i=0; ip[i],f->source,D); -+} -+ -+static void DumpDebug(const Proto* f, DumpState* D) -+{ -+ int i,n; -+ n= (D->strip) ? 0 : f->sizelineinfo; -+ DumpVector(f->lineinfo,n,sizeof(int),D); -+ n= (D->strip) ? 0 : f->sizelocvars; -+ DumpInt(n,D); -+ for (i=0; ilocvars[i].varname,D); -+ DumpInt(f->locvars[i].startpc,D); -+ DumpInt(f->locvars[i].endpc,D); -+ } -+ n= (D->strip) ? 0 : f->sizeupvalues; -+ DumpInt(n,D); -+ for (i=0; iupvalues[i],D); -+} -+ -+static void DumpFunction(const Proto* f, const TString* p, DumpState* D) -+{ -+ DumpString((f->source==p || D->strip) ? NULL : f->source,D); -+ DumpInt(f->linedefined,D); -+ DumpInt(f->lastlinedefined,D); -+ DumpChar(f->nups,D); -+ DumpChar(f->numparams,D); -+ DumpChar(f->is_vararg,D); -+ DumpChar(f->maxstacksize,D); -+ DumpCode(f,D); -+ DumpConstants(f,D); -+ DumpDebug(f,D); -+} -+ -+static void DumpHeader(DumpState* D) -+{ -+ char h[LUAC_HEADERSIZE]; -+ luaU_header(h); -+ DumpBlock(h,LUAC_HEADERSIZE,D); -+} -+ -+/* -+** dump Lua function as precompiled chunk -+*/ -+int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip) -+{ -+ DumpState D; -+ D.L=L; -+ D.writer=w; -+ D.data=data; -+ D.strip=strip; -+ D.status=0; -+ DumpHeader(&D); -+ DumpFunction(f,NULL,&D); -+ return D.status; -+} ---- /dev/null -+++ b/extensions/LUA/lua/lfunc.c -@@ -0,0 +1,174 @@ -+/* -+** $Id: lfunc.c,v 2.12.1.2 2007/12/28 14:58:43 roberto Exp $ -+** Auxiliary functions to manipulate prototypes and closures -+** See Copyright Notice in lua.h -+*/ -+ -+ -+#include -+ -+#define lfunc_c -+#define LUA_CORE -+ -+#include "lua.h" -+ -+#include "lfunc.h" -+#include "lgc.h" -+#include "lmem.h" -+#include "lobject.h" -+#include "lstate.h" -+ -+ -+ -+Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e) { -+ Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems))); -+ luaC_link(L, obj2gco(c), LUA_TFUNCTION); -+ c->c.isC = 1; -+ c->c.env = e; -+ c->c.nupvalues = cast_byte(nelems); -+ return c; -+} -+ -+ -+Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e) { -+ Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems))); -+ luaC_link(L, obj2gco(c), LUA_TFUNCTION); -+ c->l.isC = 0; -+ c->l.env = e; -+ c->l.nupvalues = cast_byte(nelems); -+ while (nelems--) c->l.upvals[nelems] = NULL; -+ return c; -+} -+ -+ -+UpVal *luaF_newupval (lua_State *L) { -+ UpVal *uv = luaM_new(L, UpVal); -+ luaC_link(L, obj2gco(uv), LUA_TUPVAL); -+ uv->v = &uv->u.value; -+ setnilvalue(uv->v); -+ return uv; -+} -+ -+ -+UpVal *luaF_findupval (lua_State *L, StkId level) { -+ global_State *g = G(L); -+ GCObject **pp = &L->openupval; -+ UpVal *p; -+ UpVal *uv; -+ while (*pp != NULL && (p = ngcotouv(*pp))->v >= level) { -+ lua_assert(p->v != &p->u.value); -+ if (p->v == level) { /* found a corresponding upvalue? */ -+ if (isdead(g, obj2gco(p))) /* is it dead? */ -+ changewhite(obj2gco(p)); /* ressurect it */ -+ return p; -+ } -+ pp = &p->next; -+ } -+ uv = luaM_new(L, UpVal); /* not found: create a new one */ -+ uv->tt = LUA_TUPVAL; -+ uv->marked = luaC_white(g); -+ uv->v = level; /* current value lives in the stack */ -+ uv->next = *pp; /* chain it in the proper position */ -+ *pp = obj2gco(uv); -+ uv->u.l.prev = &g->uvhead; /* double link it in `uvhead' list */ -+ uv->u.l.next = g->uvhead.u.l.next; -+ uv->u.l.next->u.l.prev = uv; -+ g->uvhead.u.l.next = uv; -+ lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); -+ return uv; -+} -+ -+ -+static void unlinkupval (UpVal *uv) { -+ lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); -+ uv->u.l.next->u.l.prev = uv->u.l.prev; /* remove from `uvhead' list */ -+ uv->u.l.prev->u.l.next = uv->u.l.next; -+} -+ -+ -+void luaF_freeupval (lua_State *L, UpVal *uv) { -+ if (uv->v != &uv->u.value) /* is it open? */ -+ unlinkupval(uv); /* remove from open list */ -+ luaM_free(L, uv); /* free upvalue */ -+} -+ -+ -+void luaF_close (lua_State *L, StkId level) { -+ UpVal *uv; -+ global_State *g = G(L); -+ while (L->openupval != NULL && (uv = ngcotouv(L->openupval))->v >= level) { -+ GCObject *o = obj2gco(uv); -+ lua_assert(!isblack(o) && uv->v != &uv->u.value); -+ L->openupval = uv->next; /* remove from `open' list */ -+ if (isdead(g, o)) -+ luaF_freeupval(L, uv); /* free upvalue */ -+ else { -+ unlinkupval(uv); -+ setobj(L, &uv->u.value, uv->v); -+ uv->v = &uv->u.value; /* now current value lives here */ -+ luaC_linkupval(L, uv); /* link upvalue into `gcroot' list */ -+ } -+ } -+} -+ -+ -+Proto *luaF_newproto (lua_State *L) { -+ Proto *f = luaM_new(L, Proto); -+ luaC_link(L, obj2gco(f), LUA_TPROTO); -+ f->k = NULL; -+ f->sizek = 0; -+ f->p = NULL; -+ f->sizep = 0; -+ f->code = NULL; -+ f->sizecode = 0; -+ f->sizelineinfo = 0; -+ f->sizeupvalues = 0; -+ f->nups = 0; -+ f->upvalues = NULL; -+ f->numparams = 0; -+ f->is_vararg = 0; -+ f->maxstacksize = 0; -+ f->lineinfo = NULL; -+ f->sizelocvars = 0; -+ f->locvars = NULL; -+ f->linedefined = 0; -+ f->lastlinedefined = 0; -+ f->source = NULL; -+ return f; -+} -+ -+ -+void luaF_freeproto (lua_State *L, Proto *f) { -+ luaM_freearray(L, f->code, f->sizecode, Instruction); -+ luaM_freearray(L, f->p, f->sizep, Proto *); -+ luaM_freearray(L, f->k, f->sizek, TValue); -+ luaM_freearray(L, f->lineinfo, f->sizelineinfo, int); -+ luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar); -+ luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *); -+ luaM_free(L, f); -+} -+ -+ -+void luaF_freeclosure (lua_State *L, Closure *c) { -+ int size = (c->c.isC) ? sizeCclosure(c->c.nupvalues) : -+ sizeLclosure(c->l.nupvalues); -+ luaM_freemem(L, c, size); -+} -+ -+ -+/* -+** Look for n-th local variable at line `line' in function `func'. -+** Returns NULL if not found. -+*/ -+const char *luaF_getlocalname (const Proto *f, int local_number, int pc) { -+ int i; -+ for (i = 0; isizelocvars && f->locvars[i].startpc <= pc; i++) { -+ if (pc < f->locvars[i].endpc) { /* is variable active? */ -+ local_number--; -+ if (local_number == 0) -+ return getstr(f->locvars[i].varname); -+ } -+ } -+ return NULL; /* not found */ -+} -+ ---- /dev/null -+++ b/extensions/LUA/lua/lfunc.h -@@ -0,0 +1,34 @@ -+/* -+** $Id: lfunc.h,v 2.4.1.1 2007/12/27 13:02:25 roberto Exp $ -+** Auxiliary functions to manipulate prototypes and closures -+** See Copyright Notice in lua.h -+*/ -+ -+#ifndef lfunc_h -+#define lfunc_h -+ -+ -+#include "lobject.h" -+ -+ -+#define sizeCclosure(n) (cast(int, sizeof(CClosure)) + \ -+ cast(int, sizeof(TValue)*((n)-1))) -+ -+#define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \ -+ cast(int, sizeof(TValue *)*((n)-1))) -+ -+ -+LUAI_FUNC Proto *luaF_newproto (lua_State *L); -+LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e); -+LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e); -+LUAI_FUNC UpVal *luaF_newupval (lua_State *L); -+LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level); -+LUAI_FUNC void luaF_close (lua_State *L, StkId level); -+LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f); -+LUAI_FUNC void luaF_freeclosure (lua_State *L, Closure *c); -+LUAI_FUNC void luaF_freeupval (lua_State *L, UpVal *uv); -+LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number, -+ int pc); -+ -+ -+#endif ---- /dev/null -+++ b/extensions/LUA/lua/lgc.c -@@ -0,0 +1,711 @@ -+/* -+** $Id: lgc.c,v 2.38.1.1 2007/12/27 13:02:25 roberto Exp $ -+** Garbage Collector -+** See Copyright Notice in lua.h -+*/ -+ -+#include -+ -+#define lgc_c -+#define LUA_CORE -+ -+#include "lua.h" -+ -+#include "ldebug.h" -+#include "ldo.h" -+#include "lfunc.h" -+#include "lgc.h" -+#include "lmem.h" -+#include "lobject.h" -+#include "lstate.h" -+#include "lstring.h" -+#include "ltable.h" -+#include "ltm.h" -+ -+ -+#define GCSTEPSIZE 1024u -+#define GCSWEEPMAX 40 -+#define GCSWEEPCOST 10 -+#define GCFINALIZECOST 100 -+ -+ -+#define maskmarks cast_byte(~(bitmask(BLACKBIT)|WHITEBITS)) -+ -+#define makewhite(g,x) \ -+ ((x)->gch.marked = cast_byte(((x)->gch.marked & maskmarks) | luaC_white(g))) -+ -+#define white2gray(x) reset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) -+#define black2gray(x) resetbit((x)->gch.marked, BLACKBIT) -+ -+#define stringmark(s) reset2bits((s)->tsv.marked, WHITE0BIT, WHITE1BIT) -+ -+ -+#define isfinalized(u) testbit((u)->marked, FINALIZEDBIT) -+#define markfinalized(u) l_setbit((u)->marked, FINALIZEDBIT) -+ -+ -+#define KEYWEAK bitmask(KEYWEAKBIT) -+#define VALUEWEAK bitmask(VALUEWEAKBIT) -+ -+ -+ -+#define markvalue(g,o) { checkconsistency(o); \ -+ if (iscollectable(o) && iswhite(gcvalue(o))) reallymarkobject(g,gcvalue(o)); } -+ -+#define markobject(g,t) { if (iswhite(obj2gco(t))) \ -+ reallymarkobject(g, obj2gco(t)); } -+ -+ -+#define setthreshold(g) (g->GCthreshold = (g->estimate/100) * g->gcpause) -+ -+ -+static void removeentry (Node *n) { -+ lua_assert(ttisnil(gval(n))); -+ if (iscollectable(gkey(n))) -+ setttype(gkey(n), LUA_TDEADKEY); /* dead key; remove it */ -+} -+ -+ -+static void reallymarkobject (global_State *g, GCObject *o) { -+ lua_assert(iswhite(o) && !isdead(g, o)); -+ white2gray(o); -+ switch (o->gch.tt) { -+ case LUA_TSTRING: { -+ return; -+ } -+ case LUA_TUSERDATA: { -+ Table *mt = gco2u(o)->metatable; -+ gray2black(o); /* udata are never gray */ -+ if (mt) markobject(g, mt); -+ markobject(g, gco2u(o)->env); -+ return; -+ } -+ case LUA_TUPVAL: { -+ UpVal *uv = gco2uv(o); -+ markvalue(g, uv->v); -+ if (uv->v == &uv->u.value) /* closed? */ -+ gray2black(o); /* open upvalues are never black */ -+ return; -+ } -+ case LUA_TFUNCTION: { -+ gco2cl(o)->c.gclist = g->gray; -+ g->gray = o; -+ break; -+ } -+ case LUA_TTABLE: { -+ gco2h(o)->gclist = g->gray; -+ g->gray = o; -+ break; -+ } -+ case LUA_TTHREAD: { -+ gco2th(o)->gclist = g->gray; -+ g->gray = o; -+ break; -+ } -+ case LUA_TPROTO: { -+ gco2p(o)->gclist = g->gray; -+ g->gray = o; -+ break; -+ } -+ default: lua_assert(0); -+ } -+} -+ -+ -+static void marktmu (global_State *g) { -+ GCObject *u = g->tmudata; -+ if (u) { -+ do { -+ u = u->gch.next; -+ makewhite(g, u); /* may be marked, if left from previous GC */ -+ reallymarkobject(g, u); -+ } while (u != g->tmudata); -+ } -+} -+ -+ -+/* move `dead' udata that need finalization to list `tmudata' */ -+size_t luaC_separateudata (lua_State *L, int all) { -+ global_State *g = G(L); -+ size_t deadmem = 0; -+ GCObject **p = &g->mainthread->next; -+ GCObject *curr; -+ while ((curr = *p) != NULL) { -+ if (!(iswhite(curr) || all) || isfinalized(gco2u(curr))) -+ p = &curr->gch.next; /* don't bother with them */ -+ else if (fasttm(L, gco2u(curr)->metatable, TM_GC) == NULL) { -+ markfinalized(gco2u(curr)); /* don't need finalization */ -+ p = &curr->gch.next; -+ } -+ else { /* must call its gc method */ -+ deadmem += sizeudata(gco2u(curr)); -+ markfinalized(gco2u(curr)); -+ *p = curr->gch.next; -+ /* link `curr' at the end of `tmudata' list */ -+ if (g->tmudata == NULL) /* list is empty? */ -+ g->tmudata = curr->gch.next = curr; /* creates a circular list */ -+ else { -+ curr->gch.next = g->tmudata->gch.next; -+ g->tmudata->gch.next = curr; -+ g->tmudata = curr; -+ } -+ } -+ } -+ return deadmem; -+} -+ -+ -+static int traversetable (global_State *g, Table *h) { -+ int i; -+ int weakkey = 0; -+ int weakvalue = 0; -+ const TValue *mode; -+ if (h->metatable) -+ markobject(g, h->metatable); -+ mode = gfasttm(g, h->metatable, TM_MODE); -+ if (mode && ttisstring(mode)) { /* is there a weak mode? */ -+ weakkey = (strchr(svalue(mode), 'k') != NULL); -+ weakvalue = (strchr(svalue(mode), 'v') != NULL); -+ if (weakkey || weakvalue) { /* is really weak? */ -+ h->marked &= ~(KEYWEAK | VALUEWEAK); /* clear bits */ -+ h->marked |= cast_byte((weakkey << KEYWEAKBIT) | -+ (weakvalue << VALUEWEAKBIT)); -+ h->gclist = g->weak; /* must be cleared after GC, ... */ -+ g->weak = obj2gco(h); /* ... so put in the appropriate list */ -+ } -+ } -+ if (weakkey && weakvalue) return 1; -+ if (!weakvalue) { -+ i = h->sizearray; -+ while (i--) -+ markvalue(g, &h->array[i]); -+ } -+ i = sizenode(h); -+ while (i--) { -+ Node *n = gnode(h, i); -+ lua_assert(ttype(gkey(n)) != LUA_TDEADKEY || ttisnil(gval(n))); -+ if (ttisnil(gval(n))) -+ removeentry(n); /* remove empty entries */ -+ else { -+ lua_assert(!ttisnil(gkey(n))); -+ if (!weakkey) markvalue(g, gkey(n)); -+ if (!weakvalue) markvalue(g, gval(n)); -+ } -+ } -+ return weakkey || weakvalue; -+} -+ -+ -+/* -+** All marks are conditional because a GC may happen while the -+** prototype is still being created -+*/ -+static void traverseproto (global_State *g, Proto *f) { -+ int i; -+ if (f->source) stringmark(f->source); -+ for (i=0; isizek; i++) /* mark literals */ -+ markvalue(g, &f->k[i]); -+ for (i=0; isizeupvalues; i++) { /* mark upvalue names */ -+ if (f->upvalues[i]) -+ stringmark(f->upvalues[i]); -+ } -+ for (i=0; isizep; i++) { /* mark nested protos */ -+ if (f->p[i]) -+ markobject(g, f->p[i]); -+ } -+ for (i=0; isizelocvars; i++) { /* mark local-variable names */ -+ if (f->locvars[i].varname) -+ stringmark(f->locvars[i].varname); -+ } -+} -+ -+ -+ -+static void traverseclosure (global_State *g, Closure *cl) { -+ markobject(g, cl->c.env); -+ if (cl->c.isC) { -+ int i; -+ for (i=0; ic.nupvalues; i++) /* mark its upvalues */ -+ markvalue(g, &cl->c.upvalue[i]); -+ } -+ else { -+ int i; -+ lua_assert(cl->l.nupvalues == cl->l.p->nups); -+ markobject(g, cl->l.p); -+ for (i=0; il.nupvalues; i++) /* mark its upvalues */ -+ markobject(g, cl->l.upvals[i]); -+ } -+} -+ -+ -+static void checkstacksizes (lua_State *L, StkId max) { -+ int ci_used = cast_int(L->ci - L->base_ci); /* number of `ci' in use */ -+ int s_used = cast_int(max - L->stack); /* part of stack in use */ -+ if (L->size_ci > LUAI_MAXCALLS) /* handling overflow? */ -+ return; /* do not touch the stacks */ -+ if (4*ci_used < L->size_ci && 2*BASIC_CI_SIZE < L->size_ci) -+ luaD_reallocCI(L, L->size_ci/2); /* still big enough... */ -+ condhardstacktests(luaD_reallocCI(L, ci_used + 1)); -+ if (4*s_used < L->stacksize && -+ 2*(BASIC_STACK_SIZE+EXTRA_STACK) < L->stacksize) -+ luaD_reallocstack(L, L->stacksize/2); /* still big enough... */ -+ condhardstacktests(luaD_reallocstack(L, s_used)); -+} -+ -+ -+static void traversestack (global_State *g, lua_State *l) { -+ StkId o, lim; -+ CallInfo *ci; -+ markvalue(g, gt(l)); -+ lim = l->top; -+ for (ci = l->base_ci; ci <= l->ci; ci++) { -+ lua_assert(ci->top <= l->stack_last); -+ if (lim < ci->top) lim = ci->top; -+ } -+ for (o = l->stack; o < l->top; o++) -+ markvalue(g, o); -+ for (; o <= lim; o++) -+ setnilvalue(o); -+ checkstacksizes(l, lim); -+} -+ -+ -+/* -+** traverse one gray object, turning it to black. -+** Returns `quantity' traversed. -+*/ -+static l_mem propagatemark (global_State *g) { -+ GCObject *o = g->gray; -+ lua_assert(isgray(o)); -+ gray2black(o); -+ switch (o->gch.tt) { -+ case LUA_TTABLE: { -+ Table *h = gco2h(o); -+ g->gray = h->gclist; -+ if (traversetable(g, h)) /* table is weak? */ -+ black2gray(o); /* keep it gray */ -+ return sizeof(Table) + sizeof(TValue) * h->sizearray + -+ sizeof(Node) * sizenode(h); -+ } -+ case LUA_TFUNCTION: { -+ Closure *cl = gco2cl(o); -+ g->gray = cl->c.gclist; -+ traverseclosure(g, cl); -+ return (cl->c.isC) ? sizeCclosure(cl->c.nupvalues) : -+ sizeLclosure(cl->l.nupvalues); -+ } -+ case LUA_TTHREAD: { -+ lua_State *th = gco2th(o); -+ g->gray = th->gclist; -+ th->gclist = g->grayagain; -+ g->grayagain = o; -+ black2gray(o); -+ traversestack(g, th); -+ return sizeof(lua_State) + sizeof(TValue) * th->stacksize + -+ sizeof(CallInfo) * th->size_ci; -+ } -+ case LUA_TPROTO: { -+ Proto *p = gco2p(o); -+ g->gray = p->gclist; -+ traverseproto(g, p); -+ return sizeof(Proto) + sizeof(Instruction) * p->sizecode + -+ sizeof(Proto *) * p->sizep + -+ sizeof(TValue) * p->sizek + -+ sizeof(int) * p->sizelineinfo + -+ sizeof(LocVar) * p->sizelocvars + -+ sizeof(TString *) * p->sizeupvalues; -+ } -+ default: lua_assert(0); return 0; -+ } -+} -+ -+ -+static size_t propagateall (global_State *g) { -+ size_t m = 0; -+ while (g->gray) m += propagatemark(g); -+ return m; -+} -+ -+ -+/* -+** The next function tells whether a key or value can be cleared from -+** a weak table. Non-collectable objects are never removed from weak -+** tables. Strings behave as `values', so are never removed too. for -+** other objects: if really collected, cannot keep them; for userdata -+** being finalized, keep them in keys, but not in values -+*/ -+static int iscleared (const TValue *o, int iskey) { -+ if (!iscollectable(o)) return 0; -+ if (ttisstring(o)) { -+ stringmark(rawtsvalue(o)); /* strings are `values', so are never weak */ -+ return 0; -+ } -+ return iswhite(gcvalue(o)) || -+ (ttisuserdata(o) && (!iskey && isfinalized(uvalue(o)))); -+} -+ -+ -+/* -+** clear collected entries from weaktables -+*/ -+static void cleartable (GCObject *l) { -+ while (l) { -+ Table *h = gco2h(l); -+ int i = h->sizearray; -+ lua_assert(testbit(h->marked, VALUEWEAKBIT) || -+ testbit(h->marked, KEYWEAKBIT)); -+ if (testbit(h->marked, VALUEWEAKBIT)) { -+ while (i--) { -+ TValue *o = &h->array[i]; -+ if (iscleared(o, 0)) /* value was collected? */ -+ setnilvalue(o); /* remove value */ -+ } -+ } -+ i = sizenode(h); -+ while (i--) { -+ Node *n = gnode(h, i); -+ if (!ttisnil(gval(n)) && /* non-empty entry? */ -+ (iscleared(key2tval(n), 1) || iscleared(gval(n), 0))) { -+ setnilvalue(gval(n)); /* remove value ... */ -+ removeentry(n); /* remove entry from table */ -+ } -+ } -+ l = h->gclist; -+ } -+} -+ -+ -+static void freeobj (lua_State *L, GCObject *o) { -+ switch (o->gch.tt) { -+ case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break; -+ case LUA_TFUNCTION: luaF_freeclosure(L, gco2cl(o)); break; -+ case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break; -+ case LUA_TTABLE: luaH_free(L, gco2h(o)); break; -+ case LUA_TTHREAD: { -+ lua_assert(gco2th(o) != L && gco2th(o) != G(L)->mainthread); -+ luaE_freethread(L, gco2th(o)); -+ break; -+ } -+ case LUA_TSTRING: { -+ G(L)->strt.nuse--; -+ luaM_freemem(L, o, sizestring(gco2ts(o))); -+ break; -+ } -+ case LUA_TUSERDATA: { -+ luaM_freemem(L, o, sizeudata(gco2u(o))); -+ break; -+ } -+ default: lua_assert(0); -+ } -+} -+ -+ -+ -+#define sweepwholelist(L,p) sweeplist(L,p,MAX_LUMEM) -+ -+ -+static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { -+ GCObject *curr; -+ global_State *g = G(L); -+ int deadmask = otherwhite(g); -+ while ((curr = *p) != NULL && count-- > 0) { -+ if (curr->gch.tt == LUA_TTHREAD) /* sweep open upvalues of each thread */ -+ sweepwholelist(L, &gco2th(curr)->openupval); -+ if ((curr->gch.marked ^ WHITEBITS) & deadmask) { /* not dead? */ -+ lua_assert(!isdead(g, curr) || testbit(curr->gch.marked, FIXEDBIT)); -+ makewhite(g, curr); /* make it white (for next cycle) */ -+ p = &curr->gch.next; -+ } -+ else { /* must erase `curr' */ -+ lua_assert(isdead(g, curr) || deadmask == bitmask(SFIXEDBIT)); -+ *p = curr->gch.next; -+ if (curr == g->rootgc) /* is the first element of the list? */ -+ g->rootgc = curr->gch.next; /* adjust first */ -+ freeobj(L, curr); -+ } -+ } -+ return p; -+} -+ -+ -+static void checkSizes (lua_State *L) { -+ global_State *g = G(L); -+ /* check size of string hash */ -+ if (g->strt.nuse < cast(lu_int32, g->strt.size/4) && -+ g->strt.size > MINSTRTABSIZE*2) -+ luaS_resize(L, g->strt.size/2); /* table is too big */ -+ /* check size of buffer */ -+ if (luaZ_sizebuffer(&g->buff) > LUA_MINBUFFER*2) { /* buffer too big? */ -+ size_t newsize = luaZ_sizebuffer(&g->buff) / 2; -+ luaZ_resizebuffer(L, &g->buff, newsize); -+ } -+} -+ -+ -+static void GCTM (lua_State *L) { -+ global_State *g = G(L); -+ GCObject *o = g->tmudata->gch.next; /* get first element */ -+ Udata *udata = rawgco2u(o); -+ const TValue *tm; -+ /* remove udata from `tmudata' */ -+ if (o == g->tmudata) /* last element? */ -+ g->tmudata = NULL; -+ else -+ g->tmudata->gch.next = udata->uv.next; -+ udata->uv.next = g->mainthread->next; /* return it to `root' list */ -+ g->mainthread->next = o; -+ makewhite(g, o); -+ tm = fasttm(L, udata->uv.metatable, TM_GC); -+ if (tm != NULL) { -+ lu_byte oldah = L->allowhook; -+ lu_mem oldt = g->GCthreshold; -+ L->allowhook = 0; /* stop debug hooks during GC tag method */ -+ g->GCthreshold = 2*g->totalbytes; /* avoid GC steps */ -+ setobj2s(L, L->top, tm); -+ setuvalue(L, L->top+1, udata); -+ L->top += 2; -+ luaD_call(L, L->top - 2, 0); -+ L->allowhook = oldah; /* restore hooks */ -+ g->GCthreshold = oldt; /* restore threshold */ -+ } -+} -+ -+ -+/* -+** Call all GC tag methods -+*/ -+void luaC_callGCTM (lua_State *L) { -+ while (G(L)->tmudata) -+ GCTM(L); -+} -+ -+ -+void luaC_freeall (lua_State *L) { -+ global_State *g = G(L); -+ int i; -+ g->currentwhite = WHITEBITS | bitmask(SFIXEDBIT); /* mask to collect all elements */ -+ sweepwholelist(L, &g->rootgc); -+ for (i = 0; i < g->strt.size; i++) /* free all string lists */ -+ sweepwholelist(L, &g->strt.hash[i]); -+} -+ -+ -+static void markmt (global_State *g) { -+ int i; -+ for (i=0; imt[i]) markobject(g, g->mt[i]); -+} -+ -+ -+/* mark root set */ -+static void markroot (lua_State *L) { -+ global_State *g = G(L); -+ g->gray = NULL; -+ g->grayagain = NULL; -+ g->weak = NULL; -+ markobject(g, g->mainthread); -+ /* make global table be traversed before main stack */ -+ markvalue(g, gt(g->mainthread)); -+ markvalue(g, registry(L)); -+ markmt(g); -+ g->gcstate = GCSpropagate; -+} -+ -+ -+static void remarkupvals (global_State *g) { -+ UpVal *uv; -+ for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) { -+ lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); -+ if (isgray(obj2gco(uv))) -+ markvalue(g, uv->v); -+ } -+} -+ -+ -+static void atomic (lua_State *L) { -+ global_State *g = G(L); -+ size_t udsize; /* total size of userdata to be finalized */ -+ /* remark occasional upvalues of (maybe) dead threads */ -+ remarkupvals(g); -+ /* traverse objects cautch by write barrier and by 'remarkupvals' */ -+ propagateall(g); -+ /* remark weak tables */ -+ g->gray = g->weak; -+ g->weak = NULL; -+ lua_assert(!iswhite(obj2gco(g->mainthread))); -+ markobject(g, L); /* mark running thread */ -+ markmt(g); /* mark basic metatables (again) */ -+ propagateall(g); -+ /* remark gray again */ -+ g->gray = g->grayagain; -+ g->grayagain = NULL; -+ propagateall(g); -+ udsize = luaC_separateudata(L, 0); /* separate userdata to be finalized */ -+ marktmu(g); /* mark `preserved' userdata */ -+ udsize += propagateall(g); /* remark, to propagate `preserveness' */ -+ cleartable(g->weak); /* remove collected objects from weak tables */ -+ /* flip current white */ -+ g->currentwhite = cast_byte(otherwhite(g)); -+ g->sweepstrgc = 0; -+ g->sweepgc = &g->rootgc; -+ g->gcstate = GCSsweepstring; -+ g->estimate = g->totalbytes - udsize; /* first estimate */ -+} -+ -+ -+static l_mem singlestep (lua_State *L) { -+ global_State *g = G(L); -+ /*lua_checkmemory(L);*/ -+ switch (g->gcstate) { -+ case GCSpause: { -+ markroot(L); /* start a new collection */ -+ return 0; -+ } -+ case GCSpropagate: { -+ if (g->gray) -+ return propagatemark(g); -+ else { /* no more `gray' objects */ -+ atomic(L); /* finish mark phase */ -+ return 0; -+ } -+ } -+ case GCSsweepstring: { -+ lu_mem old = g->totalbytes; -+ sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]); -+ if (g->sweepstrgc >= g->strt.size) /* nothing more to sweep? */ -+ g->gcstate = GCSsweep; /* end sweep-string phase */ -+ lua_assert(old >= g->totalbytes); -+ g->estimate -= old - g->totalbytes; -+ return GCSWEEPCOST; -+ } -+ case GCSsweep: { -+ lu_mem old = g->totalbytes; -+ g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); -+ if (*g->sweepgc == NULL) { /* nothing more to sweep? */ -+ checkSizes(L); -+ g->gcstate = GCSfinalize; /* end sweep phase */ -+ } -+ lua_assert(old >= g->totalbytes); -+ g->estimate -= old - g->totalbytes; -+ return GCSWEEPMAX*GCSWEEPCOST; -+ } -+ case GCSfinalize: { -+ if (g->tmudata) { -+ GCTM(L); -+ if (g->estimate > GCFINALIZECOST) -+ g->estimate -= GCFINALIZECOST; -+ return GCFINALIZECOST; -+ } -+ else { -+ g->gcstate = GCSpause; /* end collection */ -+ g->gcdept = 0; -+ return 0; -+ } -+ } -+ default: lua_assert(0); return 0; -+ } -+} -+ -+ -+void luaC_step (lua_State *L) { -+ global_State *g = G(L); -+ l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul; -+ if (lim == 0) -+ lim = (MAX_LUMEM-1)/2; /* no limit */ -+ g->gcdept += g->totalbytes - g->GCthreshold; -+ do { -+ lim -= singlestep(L); -+ if (g->gcstate == GCSpause) -+ break; -+ } while (lim > 0); -+ if (g->gcstate != GCSpause) { -+ if (g->gcdept < GCSTEPSIZE) -+ g->GCthreshold = g->totalbytes + GCSTEPSIZE; /* - lim/g->gcstepmul;*/ -+ else { -+ g->gcdept -= GCSTEPSIZE; -+ g->GCthreshold = g->totalbytes; -+ } -+ } -+ else { -+ lua_assert(g->totalbytes >= g->estimate); -+ setthreshold(g); -+ } -+} -+ -+ -+void luaC_fullgc (lua_State *L) { -+ global_State *g = G(L); -+ if (g->gcstate <= GCSpropagate) { -+ /* reset sweep marks to sweep all elements (returning them to white) */ -+ g->sweepstrgc = 0; -+ g->sweepgc = &g->rootgc; -+ /* reset other collector lists */ -+ g->gray = NULL; -+ g->grayagain = NULL; -+ g->weak = NULL; -+ g->gcstate = GCSsweepstring; -+ } -+ lua_assert(g->gcstate != GCSpause && g->gcstate != GCSpropagate); -+ /* finish any pending sweep phase */ -+ while (g->gcstate != GCSfinalize) { -+ lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep); -+ singlestep(L); -+ } -+ markroot(L); -+ while (g->gcstate != GCSpause) { -+ singlestep(L); -+ } -+ setthreshold(g); -+} -+ -+ -+void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) { -+ global_State *g = G(L); -+ lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); -+ lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); -+ lua_assert(ttype(&o->gch) != LUA_TTABLE); -+ /* must keep invariant? */ -+ if (g->gcstate == GCSpropagate) -+ reallymarkobject(g, v); /* restore invariant */ -+ else /* don't mind */ -+ makewhite(g, o); /* mark as white just to avoid other barriers */ -+} -+ -+ -+void luaC_barrierback (lua_State *L, Table *t) { -+ global_State *g = G(L); -+ GCObject *o = obj2gco(t); -+ lua_assert(isblack(o) && !isdead(g, o)); -+ lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); -+ black2gray(o); /* make table gray (again) */ -+ t->gclist = g->grayagain; -+ g->grayagain = o; -+} -+ -+ -+void luaC_link (lua_State *L, GCObject *o, lu_byte tt) { -+ global_State *g = G(L); -+ o->gch.next = g->rootgc; -+ g->rootgc = o; -+ o->gch.marked = luaC_white(g); -+ o->gch.tt = tt; -+} -+ -+ -+void luaC_linkupval (lua_State *L, UpVal *uv) { -+ global_State *g = G(L); -+ GCObject *o = obj2gco(uv); -+ o->gch.next = g->rootgc; /* link upvalue into `rootgc' list */ -+ g->rootgc = o; -+ if (isgray(o)) { -+ if (g->gcstate == GCSpropagate) { -+ gray2black(o); /* closed upvalues need barrier */ -+ luaC_barrier(L, uv, uv->v); -+ } -+ else { /* sweep phase: sweep it (turning it into white) */ -+ makewhite(g, o); -+ lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); -+ } -+ } -+} -+ ---- /dev/null -+++ b/extensions/LUA/lua/lgc.h -@@ -0,0 +1,110 @@ -+/* -+** $Id: lgc.h,v 2.15.1.1 2007/12/27 13:02:25 roberto Exp $ -+** Garbage Collector -+** See Copyright Notice in lua.h -+*/ -+ -+#ifndef lgc_h -+#define lgc_h -+ -+ -+#include "lobject.h" -+ -+ -+/* -+** Possible states of the Garbage Collector -+*/ -+#define GCSpause 0 -+#define GCSpropagate 1 -+#define GCSsweepstring 2 -+#define GCSsweep 3 -+#define GCSfinalize 4 -+ -+ -+/* -+** some userful bit tricks -+*/ -+#define resetbits(x,m) ((x) &= cast(lu_byte, ~(m))) -+#define setbits(x,m) ((x) |= (m)) -+#define testbits(x,m) ((x) & (m)) -+#define bitmask(b) (1<<(b)) -+#define bit2mask(b1,b2) (bitmask(b1) | bitmask(b2)) -+#define l_setbit(x,b) setbits(x, bitmask(b)) -+#define resetbit(x,b) resetbits(x, bitmask(b)) -+#define testbit(x,b) testbits(x, bitmask(b)) -+#define set2bits(x,b1,b2) setbits(x, (bit2mask(b1, b2))) -+#define reset2bits(x,b1,b2) resetbits(x, (bit2mask(b1, b2))) -+#define test2bits(x,b1,b2) testbits(x, (bit2mask(b1, b2))) -+ -+ -+ -+/* -+** Layout for bit use in `marked' field: -+** bit 0 - object is white (type 0) -+** bit 1 - object is white (type 1) -+** bit 2 - object is black -+** bit 3 - for userdata: has been finalized -+** bit 3 - for tables: has weak keys -+** bit 4 - for tables: has weak values -+** bit 5 - object is fixed (should not be collected) -+** bit 6 - object is "super" fixed (only the main thread) -+*/ -+ -+ -+#define WHITE0BIT 0 -+#define WHITE1BIT 1 -+#define BLACKBIT 2 -+#define FINALIZEDBIT 3 -+#define KEYWEAKBIT 3 -+#define VALUEWEAKBIT 4 -+#define FIXEDBIT 5 -+#define SFIXEDBIT 6 -+#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) -+ -+ -+#define iswhite(x) test2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) -+#define isblack(x) testbit((x)->gch.marked, BLACKBIT) -+#define isgray(x) (!isblack(x) && !iswhite(x)) -+ -+#define otherwhite(g) (g->currentwhite ^ WHITEBITS) -+#define isdead(g,v) ((v)->gch.marked & otherwhite(g) & WHITEBITS) -+ -+#define changewhite(x) ((x)->gch.marked ^= WHITEBITS) -+#define gray2black(x) l_setbit((x)->gch.marked, BLACKBIT) -+ -+#define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x))) -+ -+#define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) -+ -+ -+#define luaC_checkGC(L) { \ -+ condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); \ -+ if (G(L)->totalbytes >= G(L)->GCthreshold) \ -+ luaC_step(L); } -+ -+ -+#define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \ -+ luaC_barrierf(L,obj2gco(p),gcvalue(v)); } -+ -+#define luaC_barriert(L,t,v) { if (valiswhite(v) && isblack(obj2gco(t))) \ -+ luaC_barrierback(L,t); } -+ -+#define luaC_objbarrier(L,p,o) \ -+ { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \ -+ luaC_barrierf(L,obj2gco(p),obj2gco(o)); } -+ -+#define luaC_objbarriert(L,t,o) \ -+ { if (iswhite(obj2gco(o)) && isblack(obj2gco(t))) luaC_barrierback(L,t); } -+ -+LUAI_FUNC size_t luaC_separateudata (lua_State *L, int all); -+LUAI_FUNC void luaC_callGCTM (lua_State *L); -+LUAI_FUNC void luaC_freeall (lua_State *L); -+LUAI_FUNC void luaC_step (lua_State *L); -+LUAI_FUNC void luaC_fullgc (lua_State *L); -+LUAI_FUNC void luaC_link (lua_State *L, GCObject *o, lu_byte tt); -+LUAI_FUNC void luaC_linkupval (lua_State *L, UpVal *uv); -+LUAI_FUNC void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v); -+LUAI_FUNC void luaC_barrierback (lua_State *L, Table *t); -+ -+ -+#endif ---- /dev/null -+++ b/extensions/LUA/lua/llex.c -@@ -0,0 +1,460 @@ -+/* -+** $Id: llex.c,v 2.20.1.1 2007/12/27 13:02:25 roberto Exp $ -+** Lexical Analyzer -+** See Copyright Notice in lua.h -+*/ -+ -+#include -+#include -+#include -+ -+#define llex_c -+#define LUA_CORE -+ -+#include "lua.h" -+ -+#include "ldo.h" -+#include "llex.h" -+#include "lobject.h" -+#include "lparser.h" -+#include "lstate.h" -+#include "lstring.h" -+#include "ltable.h" -+#include "lzio.h" -+ -+ -+ -+#define next(ls) (ls->current = zgetc(ls->z)) -+ -+ -+ -+ -+#define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r') -+ -+ -+/* ORDER RESERVED */ -+const char *const luaX_tokens [] = { -+ "and", "break", "do", "else", "elseif", -+ "end", "false", "for", "function", "if", -+ "in", "local", "nil", "not", "or", "repeat", -+ "return", "then", "true", "until", "while", -+ "..", "...", "==", ">=", "<=", "~=", -+ "", "", "", "", -+ NULL -+}; -+ -+ -+#define save_and_next(ls) (save(ls, ls->current), next(ls)) -+ -+ -+static void save (LexState *ls, int c) { -+ Mbuffer *b = ls->buff; -+ if (b->n + 1 > b->buffsize) { -+ size_t newsize; -+ if (b->buffsize >= MAX_SIZET/2) -+ luaX_lexerror(ls, "lexical element too long", 0); -+ newsize = b->buffsize * 2; -+ luaZ_resizebuffer(ls->L, b, newsize); -+ } -+ b->buffer[b->n++] = cast(char, c); -+} -+ -+ -+void luaX_init (lua_State *L) { -+ int i; -+ for (i=0; itsv.reserved = cast_byte(i+1); /* reserved word */ -+ } -+} -+ -+ -+#define MAXSRC 80 -+ -+ -+const char *luaX_token2str (LexState *ls, int token) { -+ if (token < FIRST_RESERVED) { -+ lua_assert(token == cast(unsigned char, token)); -+ return (iscntrl(token)) ? luaO_pushfstring(ls->L, "char(%d)", token) : -+ luaO_pushfstring(ls->L, "%c", token); -+ } -+ else -+ return luaX_tokens[token-FIRST_RESERVED]; -+} -+ -+ -+static const char *txtToken (LexState *ls, int token) { -+ switch (token) { -+ case TK_NAME: -+ case TK_STRING: -+ case TK_NUMBER: -+ save(ls, '\0'); -+ return luaZ_buffer(ls->buff); -+ default: -+ return luaX_token2str(ls, token); -+ } -+} -+ -+ -+void luaX_lexerror (LexState *ls, const char *msg, int token) { -+ char buff[MAXSRC]; -+ luaO_chunkid(buff, getstr(ls->source), MAXSRC); -+ msg = luaO_pushfstring(ls->L, "%s:%d: %s", buff, ls->linenumber, msg); -+ if (token) -+ luaO_pushfstring(ls->L, "%s near " LUA_QS, msg, txtToken(ls, token)); -+ luaD_throw(ls->L, LUA_ERRSYNTAX); -+} -+ -+ -+void luaX_syntaxerror (LexState *ls, const char *msg) { -+ luaX_lexerror(ls, msg, ls->t.token); -+} -+ -+ -+TString *luaX_newstring (LexState *ls, const char *str, size_t l) { -+ lua_State *L = ls->L; -+ TString *ts = luaS_newlstr(L, str, l); -+ TValue *o = luaH_setstr(L, ls->fs->h, ts); /* entry for `str' */ -+ if (ttisnil(o)) -+ setbvalue(o, 1); /* make sure `str' will not be collected */ -+ return ts; -+} -+ -+ -+static void inclinenumber (LexState *ls) { -+ int old = ls->current; -+ lua_assert(currIsNewline(ls)); -+ next(ls); /* skip `\n' or `\r' */ -+ if (currIsNewline(ls) && ls->current != old) -+ next(ls); /* skip `\n\r' or `\r\n' */ -+ if (++ls->linenumber >= MAX_INT) -+ luaX_syntaxerror(ls, "chunk has too many lines"); -+} -+ -+ -+void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source) { -+ ls->decpoint = '.'; -+ ls->L = L; -+ ls->lookahead.token = TK_EOS; /* no look-ahead token */ -+ ls->z = z; -+ ls->fs = NULL; -+ ls->linenumber = 1; -+ ls->lastline = 1; -+ ls->source = source; -+ luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */ -+ next(ls); /* read first char */ -+} -+ -+ -+ -+/* -+** ======================================================= -+** LEXICAL ANALYZER -+** ======================================================= -+*/ -+ -+ -+ -+static int check_next (LexState *ls, const char *set) { -+ if (!strchr(set, ls->current)) -+ return 0; -+ save_and_next(ls); -+ return 1; -+} -+ -+ -+static void buffreplace (LexState *ls, char from, char to) { -+ size_t n = luaZ_bufflen(ls->buff); -+ char *p = luaZ_buffer(ls->buff); -+ while (n--) -+ if (p[n] == from) p[n] = to; -+} -+ -+ -+static void trydecpoint (LexState *ls, SemInfo *seminfo) { -+ /* format error: try to update decimal point separator */ -+ char old = ls->decpoint; -+ struct lconv *cv = localeconv(); -+ ls->decpoint = (cv ? cv->decimal_point[0] : '.'); -+ buffreplace(ls, old, ls->decpoint); /* try updated decimal separator */ -+ if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) { -+ /* format error with correct decimal point: no more options */ -+ buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */ -+ luaX_lexerror(ls, "malformed number", TK_NUMBER); -+ } -+} -+ -+ -+/* LUA_NUMBER */ -+static void read_numeral (LexState *ls, SemInfo *seminfo) { -+ lua_assert(isdigit(ls->current)); -+ do { -+ save_and_next(ls); -+ } while (isdigit(ls->current) || ls->current == '.'); -+ if (check_next(ls, "Ee")) /* `E'? */ -+ check_next(ls, "+-"); /* optional exponent sign */ -+ while (isalnum(ls->current) || ls->current == '_') -+ save_and_next(ls); -+ save(ls, '\0'); -+ buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */ -+ if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) /* format error? */ -+ trydecpoint(ls, seminfo); /* try to update decimal point separator */ -+} -+ -+ -+static int skip_sep (LexState *ls) { -+ int count = 0; -+ int s = ls->current; -+ lua_assert(s == '[' || s == ']'); -+ save_and_next(ls); -+ while (ls->current == '=') { -+ save_and_next(ls); -+ count++; -+ } -+ return (ls->current == s) ? count : (-count) - 1; -+} -+ -+ -+static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) { -+ int cont = 0; -+ (void)(cont); /* avoid warnings when `cont' is not used */ -+ save_and_next(ls); /* skip 2nd `[' */ -+ if (currIsNewline(ls)) /* string starts with a newline? */ -+ inclinenumber(ls); /* skip it */ -+ for (;;) { -+ switch (ls->current) { -+ case EOZ: -+ luaX_lexerror(ls, (seminfo) ? "unfinished long string" : -+ "unfinished long comment", TK_EOS); -+ break; /* to avoid warnings */ -+#if defined(LUA_COMPAT_LSTR) -+ case '[': { -+ if (skip_sep(ls) == sep) { -+ save_and_next(ls); /* skip 2nd `[' */ -+ cont++; -+#if LUA_COMPAT_LSTR == 1 -+ if (sep == 0) -+ luaX_lexerror(ls, "nesting of [[...]] is deprecated", '['); -+#endif -+ } -+ break; -+ } -+#endif -+ case ']': { -+ if (skip_sep(ls) == sep) { -+ save_and_next(ls); /* skip 2nd `]' */ -+#if defined(LUA_COMPAT_LSTR) && LUA_COMPAT_LSTR == 2 -+ cont--; -+ if (sep == 0 && cont >= 0) break; -+#endif -+ goto endloop; -+ } -+ break; -+ } -+ case '\n': -+ case '\r': { -+ save(ls, '\n'); -+ inclinenumber(ls); -+ if (!seminfo) luaZ_resetbuffer(ls->buff); /* avoid wasting space */ -+ break; -+ } -+ default: { -+ if (seminfo) save_and_next(ls); -+ else next(ls); -+ } -+ } -+ } endloop: -+ if (seminfo) -+ seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + (2 + sep), -+ luaZ_bufflen(ls->buff) - 2*(2 + sep)); -+} -+ -+ -+static void read_string (LexState *ls, int del, SemInfo *seminfo) { -+ save_and_next(ls); -+ while (ls->current != del) { -+ switch (ls->current) { -+ case EOZ: -+ luaX_lexerror(ls, "unfinished string", TK_EOS); -+ continue; /* to avoid warnings */ -+ case '\n': -+ case '\r': -+ luaX_lexerror(ls, "unfinished string", TK_STRING); -+ continue; /* to avoid warnings */ -+ case '\\': { -+ int c; -+ next(ls); /* do not save the `\' */ -+ switch (ls->current) { -+ case 'a': c = '\a'; break; -+ case 'b': c = '\b'; break; -+ case 'f': c = '\f'; break; -+ case 'n': c = '\n'; break; -+ case 'r': c = '\r'; break; -+ case 't': c = '\t'; break; -+ case 'v': c = '\v'; break; -+ case '\n': /* go through */ -+ case '\r': save(ls, '\n'); inclinenumber(ls); continue; -+ case EOZ: continue; /* will raise an error next loop */ -+ default: { -+ if (!isdigit(ls->current)) -+ save_and_next(ls); /* handles \\, \", \', and \? */ -+ else { /* \xxx */ -+ int i = 0; -+ c = 0; -+ do { -+ c = 10*c + (ls->current-'0'); -+ next(ls); -+ } while (++i<3 && isdigit(ls->current)); -+ if (c > UCHAR_MAX) -+ luaX_lexerror(ls, "escape sequence too large", TK_STRING); -+ save(ls, c); -+ } -+ continue; -+ } -+ } -+ save(ls, c); -+ next(ls); -+ continue; -+ } -+ default: -+ save_and_next(ls); -+ } -+ } -+ save_and_next(ls); /* skip delimiter */ -+ seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + 1, -+ luaZ_bufflen(ls->buff) - 2); -+} -+ -+ -+static int llex (LexState *ls, SemInfo *seminfo) { -+ luaZ_resetbuffer(ls->buff); -+ for (;;) { -+ switch (ls->current) { -+ case '\n': -+ case '\r': { -+ inclinenumber(ls); -+ continue; -+ } -+ case '-': { -+ next(ls); -+ if (ls->current != '-') return '-'; -+ /* else is a comment */ -+ next(ls); -+ if (ls->current == '[') { -+ int sep = skip_sep(ls); -+ luaZ_resetbuffer(ls->buff); /* `skip_sep' may dirty the buffer */ -+ if (sep >= 0) { -+ read_long_string(ls, NULL, sep); /* long comment */ -+ luaZ_resetbuffer(ls->buff); -+ continue; -+ } -+ } -+ /* else short comment */ -+ while (!currIsNewline(ls) && ls->current != EOZ) -+ next(ls); -+ continue; -+ } -+ case '[': { -+ int sep = skip_sep(ls); -+ if (sep >= 0) { -+ read_long_string(ls, seminfo, sep); -+ return TK_STRING; -+ } -+ else if (sep == -1) return '['; -+ else luaX_lexerror(ls, "invalid long string delimiter", TK_STRING); -+ } -+ case '=': { -+ next(ls); -+ if (ls->current != '=') return '='; -+ else { next(ls); return TK_EQ; } -+ } -+ case '<': { -+ next(ls); -+ if (ls->current != '=') return '<'; -+ else { next(ls); return TK_LE; } -+ } -+ case '>': { -+ next(ls); -+ if (ls->current != '=') return '>'; -+ else { next(ls); return TK_GE; } -+ } -+ case '~': { -+ next(ls); -+ if (ls->current != '=') return '~'; -+ else { next(ls); return TK_NE; } -+ } -+ case '"': -+ case '\'': { -+ read_string(ls, ls->current, seminfo); -+ return TK_STRING; -+ } -+ case '.': { -+ save_and_next(ls); -+ if (check_next(ls, ".")) { -+ if (check_next(ls, ".")) -+ return TK_DOTS; /* ... */ -+ else return TK_CONCAT; /* .. */ -+ } -+ else if (!isdigit(ls->current)) return '.'; -+ else { -+ read_numeral(ls, seminfo); -+ return TK_NUMBER; -+ } -+ } -+ case EOZ: { -+ return TK_EOS; -+ } -+ default: { -+ if (isspace(ls->current)) { -+ lua_assert(!currIsNewline(ls)); -+ next(ls); -+ continue; -+ } -+ else if (isdigit(ls->current)) { -+ read_numeral(ls, seminfo); -+ return TK_NUMBER; -+ } -+ else if (isalpha(ls->current) || ls->current == '_') { -+ /* identifier or reserved word */ -+ TString *ts; -+ do { -+ save_and_next(ls); -+ } while (isalnum(ls->current) || ls->current == '_'); -+ ts = luaX_newstring(ls, luaZ_buffer(ls->buff), -+ luaZ_bufflen(ls->buff)); -+ if (ts->tsv.reserved > 0) /* reserved word? */ -+ return ts->tsv.reserved - 1 + FIRST_RESERVED; -+ else { -+ seminfo->ts = ts; -+ return TK_NAME; -+ } -+ } -+ else { -+ int c = ls->current; -+ next(ls); -+ return c; /* single-char tokens (+ - / ...) */ -+ } -+ } -+ } -+ } -+} -+ -+ -+void luaX_next (LexState *ls) { -+ ls->lastline = ls->linenumber; -+ if (ls->lookahead.token != TK_EOS) { /* is there a look-ahead token? */ -+ ls->t = ls->lookahead; /* use this one */ -+ ls->lookahead.token = TK_EOS; /* and discharge it */ -+ } -+ else -+ ls->t.token = llex(ls, &ls->t.seminfo); /* read next token */ -+} -+ -+ -+void luaX_lookahead (LexState *ls) { -+ lua_assert(ls->lookahead.token == TK_EOS); -+ ls->lookahead.token = llex(ls, &ls->lookahead.seminfo); -+} -+ ---- /dev/null -+++ b/extensions/LUA/lua/llex.h -@@ -0,0 +1,81 @@ -+/* -+** $Id: llex.h,v 1.58.1.1 2007/12/27 13:02:25 roberto Exp $ -+** Lexical Analyzer -+** See Copyright Notice in lua.h -+*/ -+ -+#ifndef llex_h -+#define llex_h -+ -+#include "lobject.h" -+#include "lzio.h" -+ -+ -+#define FIRST_RESERVED 257 -+ -+/* maximum length of a reserved word */ -+#define TOKEN_LEN (sizeof("function")/sizeof(char)) -+ -+ -+/* -+* WARNING: if you change the order of this enumeration, -+* grep "ORDER RESERVED" -+*/ -+enum RESERVED { -+ /* terminal symbols denoted by reserved words */ -+ TK_AND = FIRST_RESERVED, TK_BREAK, -+ TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION, -+ TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT, -+ TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE, -+ /* other terminal symbols */ -+ TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER, -+ TK_NAME, TK_STRING, TK_EOS -+}; -+ -+/* number of reserved words */ -+#define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1)) -+ -+ -+/* array with token `names' */ -+LUAI_DATA const char *const luaX_tokens []; -+ -+ -+typedef union { -+ lua_Number r; -+ TString *ts; -+} SemInfo; /* semantics information */ -+ -+ -+typedef struct Token { -+ int token; -+ SemInfo seminfo; -+} Token; -+ -+ -+typedef struct LexState { -+ int current; /* current character (charint) */ -+ int linenumber; /* input line counter */ -+ int lastline; /* line of last token `consumed' */ -+ Token t; /* current token */ -+ Token lookahead; /* look ahead token */ -+ struct FuncState *fs; /* `FuncState' is private to the parser */ -+ struct lua_State *L; -+ ZIO *z; /* input stream */ -+ Mbuffer *buff; /* buffer for tokens */ -+ TString *source; /* current source name */ -+ char decpoint; /* locale decimal point */ -+} LexState; -+ -+ -+LUAI_FUNC void luaX_init (lua_State *L); -+LUAI_FUNC void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, -+ TString *source); -+LUAI_FUNC TString *luaX_newstring (LexState *ls, const char *str, size_t l); -+LUAI_FUNC void luaX_next (LexState *ls); -+LUAI_FUNC void luaX_lookahead (LexState *ls); -+LUAI_FUNC void luaX_lexerror (LexState *ls, const char *msg, int token); -+LUAI_FUNC void luaX_syntaxerror (LexState *ls, const char *s); -+LUAI_FUNC const char *luaX_token2str (LexState *ls, int token); -+ -+ -+#endif ---- /dev/null -+++ b/extensions/LUA/lua/llimits.h -@@ -0,0 +1,125 @@ -+/* -+** $Id: llimits.h,v 1.69.1.1 2007/12/27 13:02:25 roberto Exp $ -+** Limits, basic types, and some other `installation-dependent' definitions -+** See Copyright Notice in lua.h -+*/ -+ -+#ifndef llimits_h -+#define llimits_h -+ -+#include -+#include -+ -+#include "lua.h" -+ -+typedef LUAI_UINT32 lu_int32; -+ -+typedef LUAI_UMEM lu_mem; -+ -+typedef LUAI_MEM l_mem; -+ -+ -+ -+/* chars used as small naturals (so that `char' is reserved for characters) */ -+typedef unsigned char lu_byte; -+ -+ -+#define MAX_SIZET ((size_t)(~(size_t)0)-2) -+ -+#define MAX_LUMEM ((lu_mem)(~(lu_mem)0)-2) -+ -+ -+#define MAX_INT (LUA_INT_MAX-2) /* maximum value of an int (-2 for safety) */ -+ -+/* -+** conversion of pointer to integer -+** this is for hashing only; there is no problem if the integer -+** cannot hold the whole pointer value -+*/ -+#define IntPoint(p) ((unsigned int)(lu_mem)(p)) -+ -+ -+ -+/* type to ensure maximum alignment */ -+typedef LUAI_USER_ALIGNMENT_T L_Umaxalign; -+ -+ -+/* result of a `usual argument conversion' over lua_Number */ -+typedef LUAI_UACNUMBER l_uacNumber; -+ -+ -+/* internal assertions for in-house debugging */ -+#ifdef lua_assert -+ -+#define check_exp(c,e) (lua_assert(c), (e)) -+#define api_check(l,e) lua_assert(e) -+ -+#else -+ -+#define lua_assert(c) ((void)0) -+#define check_exp(c,e) (e) -+#define api_check luai_apicheck -+ -+#endif -+ -+ -+#ifndef UNUSED -+#define UNUSED(x) ((void)(x)) /* to avoid warnings */ -+#endif -+ -+ -+#ifndef cast -+#define cast(t, exp) ((t)(exp)) -+#endif -+ -+#define cast_byte(i) cast(lu_byte, (i)) -+#define cast_num(i) cast(lua_Number, (i)) -+#define cast_int(i) cast(int, (i)) -+ -+ -+ -+/* -+** type for virtual-machine instructions -+** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h) -+*/ -+typedef lu_int32 Instruction; -+ -+ -+ -+/* maximum stack for a Lua function */ -+#define MAXSTACK 250 -+ -+ -+ -+/* minimum size for the string table (must be power of 2) */ -+#ifndef MINSTRTABSIZE -+#define MINSTRTABSIZE 32 -+#endif -+ -+ -+/* minimum size for string buffer */ -+#ifndef LUA_MINBUFFER -+#define LUA_MINBUFFER 32 -+#endif -+ -+ -+#ifndef lua_lock -+#define lua_lock(L) ((void) 0) -+#define lua_unlock(L) ((void) 0) -+#endif -+ -+#ifndef luai_threadyield -+#define luai_threadyield(L) {lua_unlock(L); lua_lock(L);} -+#endif -+ -+ -+/* -+** macro to control inclusion of some hard tests on stack reallocation -+*/ -+#ifndef HARDSTACKTESTS -+#define condhardstacktests(x) ((void)0) -+#else -+#define condhardstacktests(x) x -+#endif -+ -+#endif ---- /dev/null -+++ b/extensions/LUA/lua/lmem.c -@@ -0,0 +1,86 @@ -+/* -+** $Id: lmem.c,v 1.70.1.1 2007/12/27 13:02:25 roberto Exp $ -+** Interface to Memory Manager -+** See Copyright Notice in lua.h -+*/ -+ -+ -+#include -+ -+#define lmem_c -+#define LUA_CORE -+ -+#include "lua.h" -+ -+#include "ldebug.h" -+#include "ldo.h" -+#include "lmem.h" -+#include "lobject.h" -+#include "lstate.h" -+ -+ -+ -+/* -+** About the realloc function: -+** void * frealloc (void *ud, void *ptr, size_t osize, size_t nsize); -+** (`osize' is the old size, `nsize' is the new size) -+** -+** Lua ensures that (ptr == NULL) iff (osize == 0). -+** -+** * frealloc(ud, NULL, 0, x) creates a new block of size `x' -+** -+** * frealloc(ud, p, x, 0) frees the block `p' -+** (in this specific case, frealloc must return NULL). -+** particularly, frealloc(ud, NULL, 0, 0) does nothing -+** (which is equivalent to free(NULL) in ANSI C) -+** -+** frealloc returns NULL if it cannot create or reallocate the area -+** (any reallocation to an equal or smaller size cannot fail!) -+*/ -+ -+ -+ -+#define MINSIZEARRAY 4 -+ -+ -+void *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems, -+ int limit, const char *errormsg) { -+ void *newblock; -+ int newsize; -+ if (*size >= limit/2) { /* cannot double it? */ -+ if (*size >= limit) /* cannot grow even a little? */ -+ luaG_runerror(L, errormsg); -+ newsize = limit; /* still have at least one free place */ -+ } -+ else { -+ newsize = (*size)*2; -+ if (newsize < MINSIZEARRAY) -+ newsize = MINSIZEARRAY; /* minimum size */ -+ } -+ newblock = luaM_reallocv(L, block, *size, newsize, size_elems); -+ *size = newsize; /* update only when everything else is OK */ -+ return newblock; -+} -+ -+ -+void *luaM_toobig (lua_State *L) { -+ luaG_runerror(L, "memory allocation error: block too big"); -+ return NULL; /* to avoid warnings */ -+} -+ -+ -+ -+/* -+** generic allocation routine. -+*/ -+void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { -+ global_State *g = G(L); -+ lua_assert((osize == 0) == (block == NULL)); -+ block = (*g->frealloc)(g->ud, block, osize, nsize); -+ if (block == NULL && nsize > 0) -+ luaD_throw(L, LUA_ERRMEM); -+ lua_assert((nsize == 0) == (block == NULL)); -+ g->totalbytes = (g->totalbytes - osize) + nsize; -+ return block; -+} -+ ---- /dev/null -+++ b/extensions/LUA/lua/lmem.h -@@ -0,0 +1,49 @@ -+/* -+** $Id: lmem.h,v 1.31.1.1 2007/12/27 13:02:25 roberto Exp $ -+** Interface to Memory Manager -+** See Copyright Notice in lua.h -+*/ -+ -+#ifndef lmem_h -+#define lmem_h -+ -+ -+#include -+ -+#include "llimits.h" -+#include "lua.h" -+ -+#define MEMERRMSG "not enough memory" -+ -+ -+#define luaM_reallocv(L,b,on,n,e) \ -+ ((cast(size_t, (n)+1) <= MAX_SIZET/(e)) ? /* +1 to avoid warnings */ \ -+ luaM_realloc_(L, (b), (on)*(e), (n)*(e)) : \ -+ luaM_toobig(L)) -+ -+#define luaM_freemem(L, b, s) luaM_realloc_(L, (b), (s), 0) -+#define luaM_free(L, b) luaM_realloc_(L, (b), sizeof(*(b)), 0) -+#define luaM_freearray(L, b, n, t) luaM_reallocv(L, (b), n, 0, sizeof(t)) -+ -+#define luaM_malloc(L,t) luaM_realloc_(L, NULL, 0, (t)) -+#define luaM_new(L,t) cast(t *, luaM_malloc(L, sizeof(t))) -+#define luaM_newvector(L,n,t) \ -+ cast(t *, luaM_reallocv(L, NULL, 0, n, sizeof(t))) -+ -+#define luaM_growvector(L,v,nelems,size,t,limit,e) \ -+ if ((nelems)+1 > (size)) \ -+ ((v)=cast(t *, luaM_growaux_(L,v,&(size),sizeof(t),limit,e))) -+ -+#define luaM_reallocvector(L, v,oldn,n,t) \ -+ ((v)=cast(t *, luaM_reallocv(L, v, oldn, n, sizeof(t)))) -+ -+ -+LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize, -+ size_t size); -+LUAI_FUNC void *luaM_toobig (lua_State *L); -+LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int *size, -+ size_t size_elem, int limit, -+ const char *errormsg); -+ -+#endif -+ ---- /dev/null -+++ b/extensions/LUA/lua/lobject.c -@@ -0,0 +1,215 @@ -+/* -+** $Id: lobject.c,v 2.22.1.1 2007/12/27 13:02:25 roberto Exp $ -+** Some generic functions over Lua objects -+** See Copyright Notice in lua.h -+*/ -+ -+#include -+ -+#include -+#include -+#include -+#include -+ -+#define lobject_c -+#define LUA_CORE -+ -+#include "lua.h" -+ -+#include "ldo.h" -+#include "lmem.h" -+#include "lobject.h" -+#include "lstate.h" -+#include "lstring.h" -+#include "lvm.h" -+ -+ -+ -+const TValue luaO_nilobject_ = {{NULL}, LUA_TNIL}; -+ -+ -+/* -+** converts an integer to a "floating point byte", represented as -+** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if -+** eeeee != 0 and (xxx) otherwise. -+*/ -+int luaO_int2fb (unsigned int x) { -+ int e = 0; /* expoent */ -+ while (x >= 16) { -+ x = (x+1) >> 1; -+ e++; -+ } -+ if (x < 8) return x; -+ else return ((e+1) << 3) | (cast_int(x) - 8); -+} -+ -+ -+/* converts back */ -+int luaO_fb2int (int x) { -+ int e = (x >> 3) & 31; -+ if (e == 0) return x; -+ else return ((x & 7)+8) << (e - 1); -+} -+ -+ -+int luaO_log2 (unsigned int x) { -+ static const lu_byte log_2[256] = { -+ 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, -+ 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, -+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, -+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, -+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, -+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, -+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, -+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 -+ }; -+ int l = -1; -+ while (x >= 256) { l += 8; x >>= 8; } -+ return l + log_2[x]; -+ -+} -+ -+ -+int luaO_rawequalObj (const TValue *t1, const TValue *t2) { -+ if (ttype(t1) != ttype(t2)) return 0; -+ else switch (ttype(t1)) { -+ case LUA_TNIL: -+ return 1; -+ case LUA_TNUMBER: -+ return luai_numeq(nvalue(t1), nvalue(t2)); -+ case LUA_TBOOLEAN: -+ return bvalue(t1) == bvalue(t2); /* boolean true must be 1 !! */ -+ case LUA_TLIGHTUSERDATA: -+ return pvalue(t1) == pvalue(t2); -+ default: -+ lua_assert(iscollectable(t1)); -+ return gcvalue(t1) == gcvalue(t2); -+ } -+} -+ -+ -+int luaO_str2d (const char *s, lua_Number *result) { -+ char *endptr; -+ *result = lua_str2number(s, &endptr); -+ if (endptr == s) return 0; /* conversion failed */ -+ if (*endptr == 'x' || *endptr == 'X') /* maybe an hexadecimal constant? */ -+ *result = cast_num(strtoul(s, &endptr, 16)); -+ if (*endptr == '\0') return 1; /* most common case */ -+ while (isspace(cast(unsigned char, *endptr))) endptr++; -+ if (*endptr != '\0') return 0; /* invalid trailing characters? */ -+ return 1; -+} -+ -+ -+ -+static void pushstr (lua_State *L, const char *str) { -+ setsvalue2s(L, L->top, luaS_new(L, str)); -+ incr_top(L); -+} -+ -+ -+/* this function handles only `%d', `%c', %f, %p, and `%s' formats */ -+const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { -+ int n = 1; -+ pushstr(L, ""); -+ for (;;) { -+ const char *e = strchr(fmt, '%'); -+ if (e == NULL) break; -+ setsvalue2s(L, L->top, luaS_newlstr(L, fmt, e-fmt)); -+ incr_top(L); -+ switch (*(e+1)) { -+ case 's': { -+ const char *s = va_arg(argp, char *); -+ if (s == NULL) s = "(null)"; -+ pushstr(L, s); -+ break; -+ } -+ case 'c': { -+ char buff[2]; -+ buff[0] = cast(char, va_arg(argp, int)); -+ buff[1] = '\0'; -+ pushstr(L, buff); -+ break; -+ } -+ case 'd': { -+ setnvalue(L->top, cast_num(va_arg(argp, int))); -+ incr_top(L); -+ break; -+ } -+ case 'f': { -+ setnvalue(L->top, cast_num(va_arg(argp, l_uacNumber))); -+ incr_top(L); -+ break; -+ } -+ case 'p': { -+ char buff[4*sizeof(void *) + 8]; /* should be enough space for a `%p' */ -+ sprintf(buff, "%p", va_arg(argp, void *)); -+ pushstr(L, buff); -+ break; -+ } -+ case '%': { -+ pushstr(L, "%"); -+ break; -+ } -+ default: { -+ char buff[3]; -+ buff[0] = '%'; -+ buff[1] = *(e+1); -+ buff[2] = '\0'; -+ pushstr(L, buff); -+ break; -+ } -+ } -+ n += 2; -+ fmt = e+2; -+ } -+ pushstr(L, fmt); -+ luaV_concat(L, n+1, cast_int(L->top - L->base) - 1); -+ L->top -= n; -+ return svalue(L->top - 1); -+} -+ -+ -+const char *luaO_pushfstring (lua_State *L, const char *fmt, ...) { -+ const char *msg; -+ va_list argp; -+ va_start(argp, fmt); -+ msg = luaO_pushvfstring(L, fmt, argp); -+ va_end(argp); -+ return msg; -+} -+ -+ -+void luaO_chunkid (char *out, const char *source, size_t bufflen) { -+ if (*source == '=') { -+ strncpy(out, source+1, bufflen); /* remove first char */ -+ out[bufflen-1] = '\0'; /* ensures null termination */ -+ } -+ else { /* out = "source", or "...source" */ -+ if (*source == '@') { -+ size_t l; -+ source++; /* skip the `@' */ -+ bufflen -= sizeof(" '...' "); -+ l = strlen(source); -+ strcpy(out, ""); -+ if (l > bufflen) { -+ source += (l-bufflen); /* get last part of file name */ -+ strcat(out, "..."); -+ } -+ strcat(out, source); -+ } -+ else { /* out = [string "string"] */ -+ size_t len = strcspn(source, "\n\r"); /* stop at first newline */ -+ bufflen -= sizeof(" [string \"...\"] "); -+ if (len > bufflen) len = bufflen; -+ strcpy(out, "[string \""); -+ if (source[len] != '\0') { /* must truncate? */ -+ strncat(out, source, len); -+ strcat(out, "..."); -+ } -+ else -+ strcat(out, source); -+ strcat(out, "\"]"); -+ } -+ } -+} ---- /dev/null -+++ b/extensions/LUA/lua/lobject.h -@@ -0,0 +1,381 @@ -+/* -+** $Id: lobject.h,v 2.20.1.2 2008/08/06 13:29:48 roberto Exp $ -+** Type definitions for Lua objects -+** See Copyright Notice in lua.h -+*/ -+ -+ -+#ifndef lobject_h -+#define lobject_h -+ -+ -+#include -+ -+ -+#include "llimits.h" -+#include "lua.h" -+ -+ -+/* tags for values visible from Lua */ -+#define LAST_TAG LUA_TTHREAD -+ -+#define NUM_TAGS (LAST_TAG+1) -+ -+ -+/* -+** Extra tags for non-values -+*/ -+#define LUA_TPROTO (LAST_TAG+1) -+#define LUA_TUPVAL (LAST_TAG+2) -+#define LUA_TDEADKEY (LAST_TAG+3) -+ -+ -+/* -+** Union of all collectable objects -+*/ -+typedef union GCObject GCObject; -+ -+ -+/* -+** Common Header for all collectable objects (in macro form, to be -+** included in other objects) -+*/ -+#define CommonHeader GCObject *next; lu_byte tt; lu_byte marked -+ -+ -+/* -+** Common header in struct form -+*/ -+typedef struct GCheader { -+ CommonHeader; -+} GCheader; -+ -+ -+ -+ -+/* -+** Union of all Lua values -+*/ -+typedef union { -+ GCObject *gc; -+ void *p; -+ lua_Number n; -+ int b; -+} Value; -+ -+ -+/* -+** Tagged Values -+*/ -+ -+#define TValuefields Value value; int tt -+ -+typedef struct lua_TValue { -+ TValuefields; -+} TValue; -+ -+ -+/* Macros to test type */ -+#define ttisnil(o) (ttype(o) == LUA_TNIL) -+#define ttisnumber(o) (ttype(o) == LUA_TNUMBER) -+#define ttisstring(o) (ttype(o) == LUA_TSTRING) -+#define ttistable(o) (ttype(o) == LUA_TTABLE) -+#define ttisfunction(o) (ttype(o) == LUA_TFUNCTION) -+#define ttisboolean(o) (ttype(o) == LUA_TBOOLEAN) -+#define ttisuserdata(o) (ttype(o) == LUA_TUSERDATA) -+#define ttisthread(o) (ttype(o) == LUA_TTHREAD) -+#define ttislightuserdata(o) (ttype(o) == LUA_TLIGHTUSERDATA) -+ -+/* Macros to access values */ -+#define ttype(o) ((o)->tt) -+#define gcvalue(o) check_exp(iscollectable(o), (o)->value.gc) -+#define pvalue(o) check_exp(ttislightuserdata(o), (o)->value.p) -+#define nvalue(o) check_exp(ttisnumber(o), (o)->value.n) -+#define rawtsvalue(o) check_exp(ttisstring(o), &(o)->value.gc->ts) -+#define tsvalue(o) (&rawtsvalue(o)->tsv) -+#define rawuvalue(o) check_exp(ttisuserdata(o), &(o)->value.gc->u) -+#define uvalue(o) (&rawuvalue(o)->uv) -+#define clvalue(o) check_exp(ttisfunction(o), &(o)->value.gc->cl) -+#define hvalue(o) check_exp(ttistable(o), &(o)->value.gc->h) -+#define bvalue(o) check_exp(ttisboolean(o), (o)->value.b) -+#define thvalue(o) check_exp(ttisthread(o), &(o)->value.gc->th) -+ -+#define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0)) -+ -+/* -+** for internal debug only -+*/ -+#define checkconsistency(obj) \ -+ lua_assert(!iscollectable(obj) || (ttype(obj) == (obj)->value.gc->gch.tt)) -+ -+#define checkliveness(g,obj) \ -+ lua_assert(!iscollectable(obj) || \ -+ ((ttype(obj) == (obj)->value.gc->gch.tt) && !isdead(g, (obj)->value.gc))) -+ -+ -+/* Macros to set values */ -+#define setnilvalue(obj) ((obj)->tt=LUA_TNIL) -+ -+#define setnvalue(obj,x) \ -+ { TValue *i_o=(obj); i_o->value.n=(x); i_o->tt=LUA_TNUMBER; } -+ -+#define setpvalue(obj,x) \ -+ { TValue *i_o=(obj); i_o->value.p=(x); i_o->tt=LUA_TLIGHTUSERDATA; } -+ -+#define setbvalue(obj,x) \ -+ { TValue *i_o=(obj); i_o->value.b=(x); i_o->tt=LUA_TBOOLEAN; } -+ -+#define setsvalue(L,obj,x) \ -+ { TValue *i_o=(obj); \ -+ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TSTRING; \ -+ checkliveness(G(L),i_o); } -+ -+#define setuvalue(L,obj,x) \ -+ { TValue *i_o=(obj); \ -+ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TUSERDATA; \ -+ checkliveness(G(L),i_o); } -+ -+#define setthvalue(L,obj,x) \ -+ { TValue *i_o=(obj); \ -+ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTHREAD; \ -+ checkliveness(G(L),i_o); } -+ -+#define setclvalue(L,obj,x) \ -+ { TValue *i_o=(obj); \ -+ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TFUNCTION; \ -+ checkliveness(G(L),i_o); } -+ -+#define sethvalue(L,obj,x) \ -+ { TValue *i_o=(obj); \ -+ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTABLE; \ -+ checkliveness(G(L),i_o); } -+ -+#define setptvalue(L,obj,x) \ -+ { TValue *i_o=(obj); \ -+ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TPROTO; \ -+ checkliveness(G(L),i_o); } -+ -+ -+ -+ -+#define setobj(L,obj1,obj2) \ -+ { const TValue *o2=(obj2); TValue *o1=(obj1); \ -+ o1->value = o2->value; o1->tt=o2->tt; \ -+ checkliveness(G(L),o1); } -+ -+ -+/* -+** different types of sets, according to destination -+*/ -+ -+/* from stack to (same) stack */ -+#define setobjs2s setobj -+/* to stack (not from same stack) */ -+#define setobj2s setobj -+#define setsvalue2s setsvalue -+#define sethvalue2s sethvalue -+#define setptvalue2s setptvalue -+/* from table to same table */ -+#define setobjt2t setobj -+/* to table */ -+#define setobj2t setobj -+/* to new object */ -+#define setobj2n setobj -+#define setsvalue2n setsvalue -+ -+#define setttype(obj, tt) (ttype(obj) = (tt)) -+ -+ -+#define iscollectable(o) (ttype(o) >= LUA_TSTRING) -+ -+ -+ -+typedef TValue *StkId; /* index to stack elements */ -+ -+ -+/* -+** String headers for string table -+*/ -+typedef union TString { -+ L_Umaxalign dummy; /* ensures maximum alignment for strings */ -+ struct { -+ CommonHeader; -+ lu_byte reserved; -+ unsigned int hash; -+ size_t len; -+ } tsv; -+} TString; -+ -+ -+#define getstr(ts) cast(const char *, (ts) + 1) -+#define svalue(o) getstr(rawtsvalue(o)) -+ -+ -+ -+typedef union Udata { -+ L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */ -+ struct { -+ CommonHeader; -+ struct Table *metatable; -+ struct Table *env; -+ size_t len; -+ } uv; -+} Udata; -+ -+ -+ -+ -+/* -+** Function Prototypes -+*/ -+typedef struct Proto { -+ CommonHeader; -+ TValue *k; /* constants used by the function */ -+ Instruction *code; -+ struct Proto **p; /* functions defined inside the function */ -+ int *lineinfo; /* map from opcodes to source lines */ -+ struct LocVar *locvars; /* information about local variables */ -+ TString **upvalues; /* upvalue names */ -+ TString *source; -+ int sizeupvalues; -+ int sizek; /* size of `k' */ -+ int sizecode; -+ int sizelineinfo; -+ int sizep; /* size of `p' */ -+ int sizelocvars; -+ int linedefined; -+ int lastlinedefined; -+ GCObject *gclist; -+ lu_byte nups; /* number of upvalues */ -+ lu_byte numparams; -+ lu_byte is_vararg; -+ lu_byte maxstacksize; -+} Proto; -+ -+ -+/* masks for new-style vararg */ -+#define VARARG_HASARG 1 -+#define VARARG_ISVARARG 2 -+#define VARARG_NEEDSARG 4 -+ -+ -+typedef struct LocVar { -+ TString *varname; -+ int startpc; /* first point where variable is active */ -+ int endpc; /* first point where variable is dead */ -+} LocVar; -+ -+ -+ -+/* -+** Upvalues -+*/ -+ -+typedef struct UpVal { -+ CommonHeader; -+ TValue *v; /* points to stack or to its own value */ -+ union { -+ TValue value; /* the value (when closed) */ -+ struct { /* double linked list (when open) */ -+ struct UpVal *prev; -+ struct UpVal *next; -+ } l; -+ } u; -+} UpVal; -+ -+ -+/* -+** Closures -+*/ -+ -+#define ClosureHeader \ -+ CommonHeader; lu_byte isC; lu_byte nupvalues; GCObject *gclist; \ -+ struct Table *env -+ -+typedef struct CClosure { -+ ClosureHeader; -+ lua_CFunction f; -+ TValue upvalue[1]; -+} CClosure; -+ -+ -+typedef struct LClosure { -+ ClosureHeader; -+ struct Proto *p; -+ UpVal *upvals[1]; -+} LClosure; -+ -+ -+typedef union Closure { -+ CClosure c; -+ LClosure l; -+} Closure; -+ -+ -+#define iscfunction(o) (ttype(o) == LUA_TFUNCTION && clvalue(o)->c.isC) -+#define isLfunction(o) (ttype(o) == LUA_TFUNCTION && !clvalue(o)->c.isC) -+ -+ -+/* -+** Tables -+*/ -+ -+typedef union TKey { -+ struct { -+ TValuefields; -+ struct Node *next; /* for chaining */ -+ } nk; -+ TValue tvk; -+} TKey; -+ -+ -+typedef struct Node { -+ TValue i_val; -+ TKey i_key; -+} Node; -+ -+ -+typedef struct Table { -+ CommonHeader; -+ lu_byte flags; /* 1<

lsizenode)) -+ -+ -+#define luaO_nilobject (&luaO_nilobject_) -+ -+LUAI_DATA const TValue luaO_nilobject_; -+ -+#define ceillog2(x) (luaO_log2((x)-1) + 1) -+ -+LUAI_FUNC int luaO_log2 (unsigned int x); -+LUAI_FUNC int luaO_int2fb (unsigned int x); -+LUAI_FUNC int luaO_fb2int (int x); -+LUAI_FUNC int luaO_rawequalObj (const TValue *t1, const TValue *t2); -+LUAI_FUNC int luaO_str2d (const char *s, lua_Number *result); -+LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt, -+ va_list argp); -+LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...); -+LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t len); -+ -+ -+#endif -+ ---- /dev/null -+++ b/extensions/LUA/lua/lopcodes.c -@@ -0,0 +1,102 @@ -+/* -+** $Id: lopcodes.c,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $ -+** See Copyright Notice in lua.h -+*/ -+ -+ -+#define lopcodes_c -+#define LUA_CORE -+ -+ -+#include "lopcodes.h" -+ -+ -+/* ORDER OP */ -+ -+const char *const luaP_opnames[NUM_OPCODES+1] = { -+ "MOVE", -+ "LOADK", -+ "LOADBOOL", -+ "LOADNIL", -+ "GETUPVAL", -+ "GETGLOBAL", -+ "GETTABLE", -+ "SETGLOBAL", -+ "SETUPVAL", -+ "SETTABLE", -+ "NEWTABLE", -+ "SELF", -+ "ADD", -+ "SUB", -+ "MUL", -+ "DIV", -+ "MOD", -+ "POW", -+ "UNM", -+ "NOT", -+ "LEN", -+ "CONCAT", -+ "JMP", -+ "EQ", -+ "LT", -+ "LE", -+ "TEST", -+ "TESTSET", -+ "CALL", -+ "TAILCALL", -+ "RETURN", -+ "FORLOOP", -+ "FORPREP", -+ "TFORLOOP", -+ "SETLIST", -+ "CLOSE", -+ "CLOSURE", -+ "VARARG", -+ NULL -+}; -+ -+ -+#define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m)) -+ -+const lu_byte luaP_opmodes[NUM_OPCODES] = { -+/* T A B C mode opcode */ -+ opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_MOVE */ -+ ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_LOADK */ -+ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */ -+ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LOADNIL */ -+ ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */ -+ ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_GETGLOBAL */ -+ ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETTABLE */ -+ ,opmode(0, 0, OpArgK, OpArgN, iABx) /* OP_SETGLOBAL */ -+ ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */ -+ ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABLE */ -+ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */ -+ ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_SELF */ -+ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_ADD */ -+ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SUB */ -+ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MUL */ -+ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_DIV */ -+ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MOD */ -+ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_POW */ -+ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_UNM */ -+ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_NOT */ -+ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LEN */ -+ ,opmode(0, 1, OpArgR, OpArgR, iABC) /* OP_CONCAT */ -+ ,opmode(0, 0, OpArgR, OpArgN, iAsBx) /* OP_JMP */ -+ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */ -+ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */ -+ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */ -+ ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TEST */ -+ ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TESTSET */ -+ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */ -+ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */ -+ ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RETURN */ -+ ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORLOOP */ -+ ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORPREP */ -+ ,opmode(1, 0, OpArgN, OpArgU, iABC) /* OP_TFORLOOP */ -+ ,opmode(0, 0, OpArgU, OpArgU, iABC) /* OP_SETLIST */ -+ ,opmode(0, 0, OpArgN, OpArgN, iABC) /* OP_CLOSE */ -+ ,opmode(0, 1, OpArgU, OpArgN, iABx) /* OP_CLOSURE */ -+ ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_VARARG */ -+}; -+ ---- /dev/null -+++ b/extensions/LUA/lua/lopcodes.h -@@ -0,0 +1,268 @@ -+/* -+** $Id: lopcodes.h,v 1.125.1.1 2007/12/27 13:02:25 roberto Exp $ -+** Opcodes for Lua virtual machine -+** See Copyright Notice in lua.h -+*/ -+ -+#ifndef lopcodes_h -+#define lopcodes_h -+ -+#include "llimits.h" -+ -+ -+/*=========================================================================== -+ We assume that instructions are unsigned numbers. -+ All instructions have an opcode in the first 6 bits. -+ Instructions can have the following fields: -+ `A' : 8 bits -+ `B' : 9 bits -+ `C' : 9 bits -+ `Bx' : 18 bits (`B' and `C' together) -+ `sBx' : signed Bx -+ -+ A signed argument is represented in excess K; that is, the number -+ value is the unsigned value minus K. K is exactly the maximum value -+ for that argument (so that -max is represented by 0, and +max is -+ represented by 2*max), which is half the maximum for the corresponding -+ unsigned argument. -+===========================================================================*/ -+ -+ -+enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */ -+ -+ -+/* -+** size and position of opcode arguments. -+*/ -+#define SIZE_C 9 -+#define SIZE_B 9 -+#define SIZE_Bx (SIZE_C + SIZE_B) -+#define SIZE_A 8 -+ -+#define SIZE_OP 6 -+ -+#define POS_OP 0 -+#define POS_A (POS_OP + SIZE_OP) -+#define POS_C (POS_A + SIZE_A) -+#define POS_B (POS_C + SIZE_C) -+#define POS_Bx POS_C -+ -+ -+/* -+** limits for opcode arguments. -+** we use (signed) int to manipulate most arguments, -+** so they must fit in LUAI_BITSINT-1 bits (-1 for sign) -+*/ -+#if SIZE_Bx < LUAI_BITSINT-1 -+#define MAXARG_Bx ((1<>1) /* `sBx' is signed */ -+#else -+#define MAXARG_Bx MAX_INT -+#define MAXARG_sBx MAX_INT -+#endif -+ -+ -+#define MAXARG_A ((1<>POS_OP) & MASK1(SIZE_OP,0))) -+#define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \ -+ ((cast(Instruction, o)<>POS_A) & MASK1(SIZE_A,0))) -+#define SETARG_A(i,u) ((i) = (((i)&MASK0(SIZE_A,POS_A)) | \ -+ ((cast(Instruction, u)<>POS_B) & MASK1(SIZE_B,0))) -+#define SETARG_B(i,b) ((i) = (((i)&MASK0(SIZE_B,POS_B)) | \ -+ ((cast(Instruction, b)<>POS_C) & MASK1(SIZE_C,0))) -+#define SETARG_C(i,b) ((i) = (((i)&MASK0(SIZE_C,POS_C)) | \ -+ ((cast(Instruction, b)<>POS_Bx) & MASK1(SIZE_Bx,0))) -+#define SETARG_Bx(i,b) ((i) = (((i)&MASK0(SIZE_Bx,POS_Bx)) | \ -+ ((cast(Instruction, b)< C) then pc++ */ -+OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ -+ -+OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ -+OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ -+OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */ -+ -+OP_FORLOOP,/* A sBx R(A)+=R(A+2); -+ if R(A) =) R(A)*/ -+OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */ -+ -+OP_VARARG/* A B R(A), R(A+1), ..., R(A+B-1) = vararg */ -+} OpCode; -+ -+ -+#define NUM_OPCODES (cast(int, OP_VARARG) + 1) -+ -+ -+ -+/*=========================================================================== -+ Notes: -+ (*) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1, -+ and can be 0: OP_CALL then sets `top' to last_result+1, so -+ next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use `top'. -+ -+ (*) In OP_VARARG, if (B == 0) then use actual number of varargs and -+ set top (like in OP_CALL with C == 0). -+ -+ (*) In OP_RETURN, if (B == 0) then return up to `top' -+ -+ (*) In OP_SETLIST, if (B == 0) then B = `top'; -+ if (C == 0) then next `instruction' is real C -+ -+ (*) For comparisons, A specifies what condition the test should accept -+ (true or false). -+ -+ (*) All `skips' (pc++) assume that next instruction is a jump -+===========================================================================*/ -+ -+ -+/* -+** masks for instruction properties. The format is: -+** bits 0-1: op mode -+** bits 2-3: C arg mode -+** bits 4-5: B arg mode -+** bit 6: instruction set register A -+** bit 7: operator is a test -+*/ -+ -+enum OpArgMask { -+ OpArgN, /* argument is not used */ -+ OpArgU, /* argument is used */ -+ OpArgR, /* argument is a register or a jump offset */ -+ OpArgK /* argument is a constant or register/constant */ -+}; -+ -+LUAI_DATA const lu_byte luaP_opmodes[NUM_OPCODES]; -+ -+#define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 3)) -+#define getBMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 4) & 3)) -+#define getCMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 2) & 3)) -+#define testAMode(m) (luaP_opmodes[m] & (1 << 6)) -+#define testTMode(m) (luaP_opmodes[m] & (1 << 7)) -+ -+ -+LUAI_DATA const char *const luaP_opnames[NUM_OPCODES+1]; /* opcode names */ -+ -+ -+/* number of list items to accumulate before a SETLIST instruction */ -+#define LFIELDS_PER_FLUSH 50 -+ -+ -+#endif ---- /dev/null -+++ b/extensions/LUA/lua/lparser.c -@@ -0,0 +1,1339 @@ -+/* -+** $Id: lparser.c,v 2.42.1.3 2007/12/28 15:32:23 roberto Exp $ -+** Lua Parser -+** See Copyright Notice in lua.h -+*/ -+ -+ -+#include -+ -+#define lparser_c -+#define LUA_CORE -+ -+#include "lua.h" -+ -+#include "lcode.h" -+#include "ldebug.h" -+#include "ldo.h" -+#include "lfunc.h" -+#include "llex.h" -+#include "lmem.h" -+#include "lobject.h" -+#include "lopcodes.h" -+#include "lparser.h" -+#include "lstate.h" -+#include "lstring.h" -+#include "ltable.h" -+ -+ -+ -+#define hasmultret(k) ((k) == VCALL || (k) == VVARARG) -+ -+#define getlocvar(fs, i) ((fs)->f->locvars[(fs)->actvar[i]]) -+ -+#define luaY_checklimit(fs,v,l,m) if ((v)>(l)) errorlimit(fs,l,m) -+ -+ -+/* -+** nodes for block list (list of active blocks) -+*/ -+typedef struct BlockCnt { -+ struct BlockCnt *previous; /* chain */ -+ int breaklist; /* list of jumps out of this loop */ -+ lu_byte nactvar; /* # active locals outside the breakable structure */ -+ lu_byte upval; /* true if some variable in the block is an upvalue */ -+ lu_byte isbreakable; /* true if `block' is a loop */ -+} BlockCnt; -+ -+ -+ -+/* -+** prototypes for recursive non-terminal functions -+*/ -+static void chunk (LexState *ls); -+static void expr (LexState *ls, expdesc *v); -+ -+ -+static void anchor_token (LexState *ls) { -+ if (ls->t.token == TK_NAME || ls->t.token == TK_STRING) { -+ TString *ts = ls->t.seminfo.ts; -+ luaX_newstring(ls, getstr(ts), ts->tsv.len); -+ } -+} -+ -+ -+static void error_expected (LexState *ls, int token) { -+ luaX_syntaxerror(ls, -+ luaO_pushfstring(ls->L, LUA_QS " expected", luaX_token2str(ls, token))); -+} -+ -+ -+static void errorlimit (FuncState *fs, int limit, const char *what) { -+ const char *msg = (fs->f->linedefined == 0) ? -+ luaO_pushfstring(fs->L, "main function has more than %d %s", limit, what) : -+ luaO_pushfstring(fs->L, "function at line %d has more than %d %s", -+ fs->f->linedefined, limit, what); -+ luaX_lexerror(fs->ls, msg, 0); -+} -+ -+ -+static int testnext (LexState *ls, int c) { -+ if (ls->t.token == c) { -+ luaX_next(ls); -+ return 1; -+ } -+ else return 0; -+} -+ -+ -+static void check (LexState *ls, int c) { -+ if (ls->t.token != c) -+ error_expected(ls, c); -+} -+ -+static void checknext (LexState *ls, int c) { -+ check(ls, c); -+ luaX_next(ls); -+} -+ -+ -+#define check_condition(ls,c,msg) { if (!(c)) luaX_syntaxerror(ls, msg); } -+ -+ -+ -+static void check_match (LexState *ls, int what, int who, int where) { -+ if (!testnext(ls, what)) { -+ if (where == ls->linenumber) -+ error_expected(ls, what); -+ else { -+ luaX_syntaxerror(ls, luaO_pushfstring(ls->L, -+ LUA_QS " expected (to close " LUA_QS " at line %d)", -+ luaX_token2str(ls, what), luaX_token2str(ls, who), where)); -+ } -+ } -+} -+ -+ -+static TString *str_checkname (LexState *ls) { -+ TString *ts; -+ check(ls, TK_NAME); -+ ts = ls->t.seminfo.ts; -+ luaX_next(ls); -+ return ts; -+} -+ -+ -+static void init_exp (expdesc *e, expkind k, int i) { -+ e->f = e->t = NO_JUMP; -+ e->k = k; -+ e->u.s.info = i; -+} -+ -+ -+static void codestring (LexState *ls, expdesc *e, TString *s) { -+ init_exp(e, VK, luaK_stringK(ls->fs, s)); -+} -+ -+ -+static void checkname(LexState *ls, expdesc *e) { -+ codestring(ls, e, str_checkname(ls)); -+} -+ -+ -+static int registerlocalvar (LexState *ls, TString *varname) { -+ FuncState *fs = ls->fs; -+ Proto *f = fs->f; -+ int oldsize = f->sizelocvars; -+ luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars, -+ LocVar, SHRT_MAX, "too many local variables"); -+ while (oldsize < f->sizelocvars) f->locvars[oldsize++].varname = NULL; -+ f->locvars[fs->nlocvars].varname = varname; -+ luaC_objbarrier(ls->L, f, varname); -+ return fs->nlocvars++; -+} -+ -+ -+#define new_localvarliteral(ls,v,n) \ -+ new_localvar(ls, luaX_newstring(ls, "" v, (sizeof(v)/sizeof(char))-1), n) -+ -+ -+static void new_localvar (LexState *ls, TString *name, int n) { -+ FuncState *fs = ls->fs; -+ luaY_checklimit(fs, fs->nactvar+n+1, LUAI_MAXVARS, "local variables"); -+ fs->actvar[fs->nactvar+n] = cast(unsigned short, registerlocalvar(ls, name)); -+} -+ -+ -+static void adjustlocalvars (LexState *ls, int nvars) { -+ FuncState *fs = ls->fs; -+ fs->nactvar = cast_byte(fs->nactvar + nvars); -+ for (; nvars; nvars--) { -+ getlocvar(fs, fs->nactvar - nvars).startpc = fs->pc; -+ } -+} -+ -+ -+static void removevars (LexState *ls, int tolevel) { -+ FuncState *fs = ls->fs; -+ while (fs->nactvar > tolevel) -+ getlocvar(fs, --fs->nactvar).endpc = fs->pc; -+} -+ -+ -+static int indexupvalue (FuncState *fs, TString *name, expdesc *v) { -+ int i; -+ Proto *f = fs->f; -+ int oldsize = f->sizeupvalues; -+ for (i=0; inups; i++) { -+ if (fs->upvalues[i].k == v->k && fs->upvalues[i].info == v->u.s.info) { -+ lua_assert(f->upvalues[i] == name); -+ return i; -+ } -+ } -+ /* new one */ -+ luaY_checklimit(fs, f->nups + 1, LUAI_MAXUPVALUES, "upvalues"); -+ luaM_growvector(fs->L, f->upvalues, f->nups, f->sizeupvalues, -+ TString *, MAX_INT, ""); -+ while (oldsize < f->sizeupvalues) f->upvalues[oldsize++] = NULL; -+ f->upvalues[f->nups] = name; -+ luaC_objbarrier(fs->L, f, name); -+ lua_assert(v->k == VLOCAL || v->k == VUPVAL); -+ fs->upvalues[f->nups].k = cast_byte(v->k); -+ fs->upvalues[f->nups].info = cast_byte(v->u.s.info); -+ return f->nups++; -+} -+ -+ -+static int searchvar (FuncState *fs, TString *n) { -+ int i; -+ for (i=fs->nactvar-1; i >= 0; i--) { -+ if (n == getlocvar(fs, i).varname) -+ return i; -+ } -+ return -1; /* not found */ -+} -+ -+ -+static void markupval (FuncState *fs, int level) { -+ BlockCnt *bl = fs->bl; -+ while (bl && bl->nactvar > level) bl = bl->previous; -+ if (bl) bl->upval = 1; -+} -+ -+ -+static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { -+ if (fs == NULL) { /* no more levels? */ -+ init_exp(var, VGLOBAL, NO_REG); /* default is global variable */ -+ return VGLOBAL; -+ } -+ else { -+ int v = searchvar(fs, n); /* look up at current level */ -+ if (v >= 0) { -+ init_exp(var, VLOCAL, v); -+ if (!base) -+ markupval(fs, v); /* local will be used as an upval */ -+ return VLOCAL; -+ } -+ else { /* not found at current level; try upper one */ -+ if (singlevaraux(fs->prev, n, var, 0) == VGLOBAL) -+ return VGLOBAL; -+ var->u.s.info = indexupvalue(fs, n, var); /* else was LOCAL or UPVAL */ -+ var->k = VUPVAL; /* upvalue in this level */ -+ return VUPVAL; -+ } -+ } -+} -+ -+ -+static void singlevar (LexState *ls, expdesc *var) { -+ TString *varname = str_checkname(ls); -+ FuncState *fs = ls->fs; -+ if (singlevaraux(fs, varname, var, 1) == VGLOBAL) -+ var->u.s.info = luaK_stringK(fs, varname); /* info points to global name */ -+} -+ -+ -+static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { -+ FuncState *fs = ls->fs; -+ int extra = nvars - nexps; -+ if (hasmultret(e->k)) { -+ extra++; /* includes call itself */ -+ if (extra < 0) extra = 0; -+ luaK_setreturns(fs, e, extra); /* last exp. provides the difference */ -+ if (extra > 1) luaK_reserveregs(fs, extra-1); -+ } -+ else { -+ if (e->k != VVOID) luaK_exp2nextreg(fs, e); /* close last expression */ -+ if (extra > 0) { -+ int reg = fs->freereg; -+ luaK_reserveregs(fs, extra); -+ luaK_nil(fs, reg, extra); -+ } -+ } -+} -+ -+ -+static void enterlevel (LexState *ls) { -+ if (++ls->L->nCcalls > LUAI_MAXCCALLS) -+ luaX_lexerror(ls, "chunk has too many syntax levels", 0); -+} -+ -+ -+#define leavelevel(ls) ((ls)->L->nCcalls--) -+ -+ -+static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isbreakable) { -+ bl->breaklist = NO_JUMP; -+ bl->isbreakable = isbreakable; -+ bl->nactvar = fs->nactvar; -+ bl->upval = 0; -+ bl->previous = fs->bl; -+ fs->bl = bl; -+ lua_assert(fs->freereg == fs->nactvar); -+} -+ -+ -+static void leaveblock (FuncState *fs) { -+ BlockCnt *bl = fs->bl; -+ fs->bl = bl->previous; -+ removevars(fs->ls, bl->nactvar); -+ if (bl->upval) -+ luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0); -+ /* a block either controls scope or breaks (never both) */ -+ lua_assert(!bl->isbreakable || !bl->upval); -+ lua_assert(bl->nactvar == fs->nactvar); -+ fs->freereg = fs->nactvar; /* free registers */ -+ luaK_patchtohere(fs, bl->breaklist); -+} -+ -+ -+static void pushclosure (LexState *ls, FuncState *func, expdesc *v) { -+ FuncState *fs = ls->fs; -+ Proto *f = fs->f; -+ int oldsize = f->sizep; -+ int i; -+ luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *, -+ MAXARG_Bx, "constant table overflow"); -+ while (oldsize < f->sizep) f->p[oldsize++] = NULL; -+ f->p[fs->np++] = func->f; -+ luaC_objbarrier(ls->L, f, func->f); -+ init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np-1)); -+ for (i=0; if->nups; i++) { -+ OpCode o = (func->upvalues[i].k == VLOCAL) ? OP_MOVE : OP_GETUPVAL; -+ luaK_codeABC(fs, o, 0, func->upvalues[i].info, 0); -+ } -+} -+ -+ -+static void open_func (LexState *ls, FuncState *fs) { -+ lua_State *L = ls->L; -+ Proto *f = luaF_newproto(L); -+ fs->f = f; -+ fs->prev = ls->fs; /* linked list of funcstates */ -+ fs->ls = ls; -+ fs->L = L; -+ ls->fs = fs; -+ fs->pc = 0; -+ fs->lasttarget = -1; -+ fs->jpc = NO_JUMP; -+ fs->freereg = 0; -+ fs->nk = 0; -+ fs->np = 0; -+ fs->nlocvars = 0; -+ fs->nactvar = 0; -+ fs->bl = NULL; -+ f->source = ls->source; -+ f->maxstacksize = 2; /* registers 0/1 are always valid */ -+ fs->h = luaH_new(L, 0, 0); -+ /* anchor table of constants and prototype (to avoid being collected) */ -+ sethvalue2s(L, L->top, fs->h); -+ incr_top(L); -+ setptvalue2s(L, L->top, f); -+ incr_top(L); -+} -+ -+ -+static void close_func (LexState *ls) { -+ lua_State *L = ls->L; -+ FuncState *fs = ls->fs; -+ Proto *f = fs->f; -+ removevars(ls, 0); -+ luaK_ret(fs, 0, 0); /* final return */ -+ luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction); -+ f->sizecode = fs->pc; -+ luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int); -+ f->sizelineinfo = fs->pc; -+ luaM_reallocvector(L, f->k, f->sizek, fs->nk, TValue); -+ f->sizek = fs->nk; -+ luaM_reallocvector(L, f->p, f->sizep, fs->np, Proto *); -+ f->sizep = fs->np; -+ luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar); -+ f->sizelocvars = fs->nlocvars; -+ luaM_reallocvector(L, f->upvalues, f->sizeupvalues, f->nups, TString *); -+ f->sizeupvalues = f->nups; -+ lua_assert(luaG_checkcode(f)); -+ lua_assert(fs->bl == NULL); -+ ls->fs = fs->prev; -+ L->top -= 2; /* remove table and prototype from the stack */ -+ /* last token read was anchored in defunct function; must reanchor it */ -+ if (fs) anchor_token(ls); -+} -+ -+ -+Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) { -+ struct LexState lexstate; -+ struct FuncState funcstate; -+ lexstate.buff = buff; -+ luaX_setinput(L, &lexstate, z, luaS_new(L, name)); -+ open_func(&lexstate, &funcstate); -+ funcstate.f->is_vararg = VARARG_ISVARARG; /* main func. is always vararg */ -+ luaX_next(&lexstate); /* read first token */ -+ chunk(&lexstate); -+ check(&lexstate, TK_EOS); -+ close_func(&lexstate); -+ lua_assert(funcstate.prev == NULL); -+ lua_assert(funcstate.f->nups == 0); -+ lua_assert(lexstate.fs == NULL); -+ return funcstate.f; -+} -+ -+ -+ -+/*============================================================*/ -+/* GRAMMAR RULES */ -+/*============================================================*/ -+ -+ -+static void field (LexState *ls, expdesc *v) { -+ /* field -> ['.' | ':'] NAME */ -+ FuncState *fs = ls->fs; -+ expdesc key; -+ luaK_exp2anyreg(fs, v); -+ luaX_next(ls); /* skip the dot or colon */ -+ checkname(ls, &key); -+ luaK_indexed(fs, v, &key); -+} -+ -+ -+static void yindex (LexState *ls, expdesc *v) { -+ /* index -> '[' expr ']' */ -+ luaX_next(ls); /* skip the '[' */ -+ expr(ls, v); -+ luaK_exp2val(ls->fs, v); -+ checknext(ls, ']'); -+} -+ -+ -+/* -+** {====================================================================== -+** Rules for Constructors -+** ======================================================================= -+*/ -+ -+ -+struct ConsControl { -+ expdesc v; /* last list item read */ -+ expdesc *t; /* table descriptor */ -+ int nh; /* total number of `record' elements */ -+ int na; /* total number of array elements */ -+ int tostore; /* number of array elements pending to be stored */ -+}; -+ -+ -+static void recfield (LexState *ls, struct ConsControl *cc) { -+ /* recfield -> (NAME | `['exp1`]') = exp1 */ -+ FuncState *fs = ls->fs; -+ int reg = ls->fs->freereg; -+ expdesc key, val; -+ int rkkey; -+ if (ls->t.token == TK_NAME) { -+ luaY_checklimit(fs, cc->nh, MAX_INT, "items in a constructor"); -+ checkname(ls, &key); -+ } -+ else /* ls->t.token == '[' */ -+ yindex(ls, &key); -+ cc->nh++; -+ checknext(ls, '='); -+ rkkey = luaK_exp2RK(fs, &key); -+ expr(ls, &val); -+ luaK_codeABC(fs, OP_SETTABLE, cc->t->u.s.info, rkkey, luaK_exp2RK(fs, &val)); -+ fs->freereg = reg; /* free registers */ -+} -+ -+ -+static void closelistfield (FuncState *fs, struct ConsControl *cc) { -+ if (cc->v.k == VVOID) return; /* there is no list item */ -+ luaK_exp2nextreg(fs, &cc->v); -+ cc->v.k = VVOID; -+ if (cc->tostore == LFIELDS_PER_FLUSH) { -+ luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore); /* flush */ -+ cc->tostore = 0; /* no more items pending */ -+ } -+} -+ -+ -+static void lastlistfield (FuncState *fs, struct ConsControl *cc) { -+ if (cc->tostore == 0) return; -+ if (hasmultret(cc->v.k)) { -+ luaK_setmultret(fs, &cc->v); -+ luaK_setlist(fs, cc->t->u.s.info, cc->na, LUA_MULTRET); -+ cc->na--; /* do not count last expression (unknown number of elements) */ -+ } -+ else { -+ if (cc->v.k != VVOID) -+ luaK_exp2nextreg(fs, &cc->v); -+ luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore); -+ } -+} -+ -+ -+static void listfield (LexState *ls, struct ConsControl *cc) { -+ expr(ls, &cc->v); -+ luaY_checklimit(ls->fs, cc->na, MAX_INT, "items in a constructor"); -+ cc->na++; -+ cc->tostore++; -+} -+ -+ -+static void constructor (LexState *ls, expdesc *t) { -+ /* constructor -> ?? */ -+ FuncState *fs = ls->fs; -+ int line = ls->linenumber; -+ int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0); -+ struct ConsControl cc; -+ cc.na = cc.nh = cc.tostore = 0; -+ cc.t = t; -+ init_exp(t, VRELOCABLE, pc); -+ init_exp(&cc.v, VVOID, 0); /* no value (yet) */ -+ luaK_exp2nextreg(ls->fs, t); /* fix it at stack top (for gc) */ -+ checknext(ls, '{'); -+ do { -+ lua_assert(cc.v.k == VVOID || cc.tostore > 0); -+ if (ls->t.token == '}') break; -+ closelistfield(fs, &cc); -+ switch(ls->t.token) { -+ case TK_NAME: { /* may be listfields or recfields */ -+ luaX_lookahead(ls); -+ if (ls->lookahead.token != '=') /* expression? */ -+ listfield(ls, &cc); -+ else -+ recfield(ls, &cc); -+ break; -+ } -+ case '[': { /* constructor_item -> recfield */ -+ recfield(ls, &cc); -+ break; -+ } -+ default: { /* constructor_part -> listfield */ -+ listfield(ls, &cc); -+ break; -+ } -+ } -+ } while (testnext(ls, ',') || testnext(ls, ';')); -+ check_match(ls, '}', '{', line); -+ lastlistfield(fs, &cc); -+ SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */ -+ SETARG_C(fs->f->code[pc], luaO_int2fb(cc.nh)); /* set initial table size */ -+} -+ -+/* }====================================================================== */ -+ -+ -+ -+static void parlist (LexState *ls) { -+ /* parlist -> [ param { `,' param } ] */ -+ FuncState *fs = ls->fs; -+ Proto *f = fs->f; -+ int nparams = 0; -+ f->is_vararg = 0; -+ if (ls->t.token != ')') { /* is `parlist' not empty? */ -+ do { -+ switch (ls->t.token) { -+ case TK_NAME: { /* param -> NAME */ -+ new_localvar(ls, str_checkname(ls), nparams++); -+ break; -+ } -+ case TK_DOTS: { /* param -> `...' */ -+ luaX_next(ls); -+#if defined(LUA_COMPAT_VARARG) -+ /* use `arg' as default name */ -+ new_localvarliteral(ls, "arg", nparams++); -+ f->is_vararg = VARARG_HASARG | VARARG_NEEDSARG; -+#endif -+ f->is_vararg |= VARARG_ISVARARG; -+ break; -+ } -+ default: luaX_syntaxerror(ls, " or " LUA_QL("...") " expected"); -+ } -+ } while (!f->is_vararg && testnext(ls, ',')); -+ } -+ adjustlocalvars(ls, nparams); -+ f->numparams = cast_byte(fs->nactvar - (f->is_vararg & VARARG_HASARG)); -+ luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */ -+} -+ -+ -+static void body (LexState *ls, expdesc *e, int needself, int line) { -+ /* body -> `(' parlist `)' chunk END */ -+ FuncState new_fs; -+ open_func(ls, &new_fs); -+ new_fs.f->linedefined = line; -+ checknext(ls, '('); -+ if (needself) { -+ new_localvarliteral(ls, "self", 0); -+ adjustlocalvars(ls, 1); -+ } -+ parlist(ls); -+ checknext(ls, ')'); -+ chunk(ls); -+ new_fs.f->lastlinedefined = ls->linenumber; -+ check_match(ls, TK_END, TK_FUNCTION, line); -+ close_func(ls); -+ pushclosure(ls, &new_fs, e); -+} -+ -+ -+static int explist1 (LexState *ls, expdesc *v) { -+ /* explist1 -> expr { `,' expr } */ -+ int n = 1; /* at least one expression */ -+ expr(ls, v); -+ while (testnext(ls, ',')) { -+ luaK_exp2nextreg(ls->fs, v); -+ expr(ls, v); -+ n++; -+ } -+ return n; -+} -+ -+ -+static void funcargs (LexState *ls, expdesc *f) { -+ FuncState *fs = ls->fs; -+ expdesc args; -+ int base, nparams; -+ int line = ls->linenumber; -+ switch (ls->t.token) { -+ case '(': { /* funcargs -> `(' [ explist1 ] `)' */ -+ if (line != ls->lastline) -+ luaX_syntaxerror(ls,"ambiguous syntax (function call x new statement)"); -+ luaX_next(ls); -+ if (ls->t.token == ')') /* arg list is empty? */ -+ args.k = VVOID; -+ else { -+ explist1(ls, &args); -+ luaK_setmultret(fs, &args); -+ } -+ check_match(ls, ')', '(', line); -+ break; -+ } -+ case '{': { /* funcargs -> constructor */ -+ constructor(ls, &args); -+ break; -+ } -+ case TK_STRING: { /* funcargs -> STRING */ -+ codestring(ls, &args, ls->t.seminfo.ts); -+ luaX_next(ls); /* must use `seminfo' before `next' */ -+ break; -+ } -+ default: { -+ luaX_syntaxerror(ls, "function arguments expected"); -+ return; -+ } -+ } -+ lua_assert(f->k == VNONRELOC); -+ base = f->u.s.info; /* base register for call */ -+ if (hasmultret(args.k)) -+ nparams = LUA_MULTRET; /* open call */ -+ else { -+ if (args.k != VVOID) -+ luaK_exp2nextreg(fs, &args); /* close last argument */ -+ nparams = fs->freereg - (base+1); -+ } -+ init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2)); -+ luaK_fixline(fs, line); -+ fs->freereg = base+1; /* call remove function and arguments and leaves -+ (unless changed) one result */ -+} -+ -+ -+ -+ -+/* -+** {====================================================================== -+** Expression parsing -+** ======================================================================= -+*/ -+ -+ -+static void prefixexp (LexState *ls, expdesc *v) { -+ /* prefixexp -> NAME | '(' expr ')' */ -+ switch (ls->t.token) { -+ case '(': { -+ int line = ls->linenumber; -+ luaX_next(ls); -+ expr(ls, v); -+ check_match(ls, ')', '(', line); -+ luaK_dischargevars(ls->fs, v); -+ return; -+ } -+ case TK_NAME: { -+ singlevar(ls, v); -+ return; -+ } -+ default: { -+ luaX_syntaxerror(ls, "unexpected symbol"); -+ return; -+ } -+ } -+} -+ -+ -+static void primaryexp (LexState *ls, expdesc *v) { -+ /* primaryexp -> -+ prefixexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | funcargs } */ -+ FuncState *fs = ls->fs; -+ prefixexp(ls, v); -+ for (;;) { -+ switch (ls->t.token) { -+ case '.': { /* field */ -+ field(ls, v); -+ break; -+ } -+ case '[': { /* `[' exp1 `]' */ -+ expdesc key; -+ luaK_exp2anyreg(fs, v); -+ yindex(ls, &key); -+ luaK_indexed(fs, v, &key); -+ break; -+ } -+ case ':': { /* `:' NAME funcargs */ -+ expdesc key; -+ luaX_next(ls); -+ checkname(ls, &key); -+ luaK_self(fs, v, &key); -+ funcargs(ls, v); -+ break; -+ } -+ case '(': case TK_STRING: case '{': { /* funcargs */ -+ luaK_exp2nextreg(fs, v); -+ funcargs(ls, v); -+ break; -+ } -+ default: return; -+ } -+ } -+} -+ -+ -+static void simpleexp (LexState *ls, expdesc *v) { -+ /* simpleexp -> NUMBER | STRING | NIL | true | false | ... | -+ constructor | FUNCTION body | primaryexp */ -+ switch (ls->t.token) { -+ case TK_NUMBER: { -+ init_exp(v, VKNUM, 0); -+ v->u.nval = ls->t.seminfo.r; -+ break; -+ } -+ case TK_STRING: { -+ codestring(ls, v, ls->t.seminfo.ts); -+ break; -+ } -+ case TK_NIL: { -+ init_exp(v, VNIL, 0); -+ break; -+ } -+ case TK_TRUE: { -+ init_exp(v, VTRUE, 0); -+ break; -+ } -+ case TK_FALSE: { -+ init_exp(v, VFALSE, 0); -+ break; -+ } -+ case TK_DOTS: { /* vararg */ -+ FuncState *fs = ls->fs; -+ check_condition(ls, fs->f->is_vararg, -+ "cannot use " LUA_QL("...") " outside a vararg function"); -+ fs->f->is_vararg &= ~VARARG_NEEDSARG; /* don't need 'arg' */ -+ init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0)); -+ break; -+ } -+ case '{': { /* constructor */ -+ constructor(ls, v); -+ return; -+ } -+ case TK_FUNCTION: { -+ luaX_next(ls); -+ body(ls, v, 0, ls->linenumber); -+ return; -+ } -+ default: { -+ primaryexp(ls, v); -+ return; -+ } -+ } -+ luaX_next(ls); -+} -+ -+ -+static UnOpr getunopr (int op) { -+ switch (op) { -+ case TK_NOT: return OPR_NOT; -+ case '-': return OPR_MINUS; -+ case '#': return OPR_LEN; -+ default: return OPR_NOUNOPR; -+ } -+} -+ -+ -+static BinOpr getbinopr (int op) { -+ switch (op) { -+ case '+': return OPR_ADD; -+ case '-': return OPR_SUB; -+ case '*': return OPR_MUL; -+ case '/': return OPR_DIV; -+ case '%': return OPR_MOD; -+ case '^': return OPR_POW; -+ case TK_CONCAT: return OPR_CONCAT; -+ case TK_NE: return OPR_NE; -+ case TK_EQ: return OPR_EQ; -+ case '<': return OPR_LT; -+ case TK_LE: return OPR_LE; -+ case '>': return OPR_GT; -+ case TK_GE: return OPR_GE; -+ case TK_AND: return OPR_AND; -+ case TK_OR: return OPR_OR; -+ default: return OPR_NOBINOPR; -+ } -+} -+ -+ -+static const struct { -+ lu_byte left; /* left priority for each binary operator */ -+ lu_byte right; /* right priority */ -+} priority[] = { /* ORDER OPR */ -+ {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7}, /* `+' `-' `/' `%' */ -+ {10, 9}, {5, 4}, /* power and concat (right associative) */ -+ {3, 3}, {3, 3}, /* equality and inequality */ -+ {3, 3}, {3, 3}, {3, 3}, {3, 3}, /* order */ -+ {2, 2}, {1, 1} /* logical (and/or) */ -+}; -+ -+#define UNARY_PRIORITY 8 /* priority for unary operators */ -+ -+ -+/* -+** subexpr -> (simpleexp | unop subexpr) { binop subexpr } -+** where `binop' is any binary operator with a priority higher than `limit' -+*/ -+static BinOpr subexpr (LexState *ls, expdesc *v, unsigned int limit) { -+ BinOpr op; -+ UnOpr uop; -+ enterlevel(ls); -+ uop = getunopr(ls->t.token); -+ if (uop != OPR_NOUNOPR) { -+ luaX_next(ls); -+ subexpr(ls, v, UNARY_PRIORITY); -+ luaK_prefix(ls->fs, uop, v); -+ } -+ else simpleexp(ls, v); -+ /* expand while operators have priorities higher than `limit' */ -+ op = getbinopr(ls->t.token); -+ while (op != OPR_NOBINOPR && priority[op].left > limit) { -+ expdesc v2; -+ BinOpr nextop; -+ luaX_next(ls); -+ luaK_infix(ls->fs, op, v); -+ /* read sub-expression with higher priority */ -+ nextop = subexpr(ls, &v2, priority[op].right); -+ luaK_posfix(ls->fs, op, v, &v2); -+ op = nextop; -+ } -+ leavelevel(ls); -+ return op; /* return first untreated operator */ -+} -+ -+ -+static void expr (LexState *ls, expdesc *v) { -+ subexpr(ls, v, 0); -+} -+ -+/* }==================================================================== */ -+ -+ -+ -+/* -+** {====================================================================== -+** Rules for Statements -+** ======================================================================= -+*/ -+ -+ -+static int block_follow (int token) { -+ switch (token) { -+ case TK_ELSE: case TK_ELSEIF: case TK_END: -+ case TK_UNTIL: case TK_EOS: -+ return 1; -+ default: return 0; -+ } -+} -+ -+ -+static void block (LexState *ls) { -+ /* block -> chunk */ -+ FuncState *fs = ls->fs; -+ BlockCnt bl; -+ enterblock(fs, &bl, 0); -+ chunk(ls); -+ lua_assert(bl.breaklist == NO_JUMP); -+ leaveblock(fs); -+} -+ -+ -+/* -+** structure to chain all variables in the left-hand side of an -+** assignment -+*/ -+struct LHS_assign { -+ struct LHS_assign *prev; -+ expdesc v; /* variable (global, local, upvalue, or indexed) */ -+}; -+ -+ -+/* -+** check whether, in an assignment to a local variable, the local variable -+** is needed in a previous assignment (to a table). If so, save original -+** local value in a safe place and use this safe copy in the previous -+** assignment. -+*/ -+static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { -+ FuncState *fs = ls->fs; -+ int extra = fs->freereg; /* eventual position to save local variable */ -+ int conflict = 0; -+ for (; lh; lh = lh->prev) { -+ if (lh->v.k == VINDEXED) { -+ if (lh->v.u.s.info == v->u.s.info) { /* conflict? */ -+ conflict = 1; -+ lh->v.u.s.info = extra; /* previous assignment will use safe copy */ -+ } -+ if (lh->v.u.s.aux == v->u.s.info) { /* conflict? */ -+ conflict = 1; -+ lh->v.u.s.aux = extra; /* previous assignment will use safe copy */ -+ } -+ } -+ } -+ if (conflict) { -+ luaK_codeABC(fs, OP_MOVE, fs->freereg, v->u.s.info, 0); /* make copy */ -+ luaK_reserveregs(fs, 1); -+ } -+} -+ -+ -+static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { -+ expdesc e; -+ check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXED, -+ "syntax error"); -+ if (testnext(ls, ',')) { /* assignment -> `,' primaryexp assignment */ -+ struct LHS_assign nv; -+ nv.prev = lh; -+ primaryexp(ls, &nv.v); -+ if (nv.v.k == VLOCAL) -+ check_conflict(ls, lh, &nv.v); -+ luaY_checklimit(ls->fs, nvars, LUAI_MAXCCALLS - ls->L->nCcalls, -+ "variables in assignment"); -+ assignment(ls, &nv, nvars+1); -+ } -+ else { /* assignment -> `=' explist1 */ -+ int nexps; -+ checknext(ls, '='); -+ nexps = explist1(ls, &e); -+ if (nexps != nvars) { -+ adjust_assign(ls, nvars, nexps, &e); -+ if (nexps > nvars) -+ ls->fs->freereg -= nexps - nvars; /* remove extra values */ -+ } -+ else { -+ luaK_setoneret(ls->fs, &e); /* close last expression */ -+ luaK_storevar(ls->fs, &lh->v, &e); -+ return; /* avoid default */ -+ } -+ } -+ init_exp(&e, VNONRELOC, ls->fs->freereg-1); /* default assignment */ -+ luaK_storevar(ls->fs, &lh->v, &e); -+} -+ -+ -+static int cond (LexState *ls) { -+ /* cond -> exp */ -+ expdesc v; -+ expr(ls, &v); /* read condition */ -+ if (v.k == VNIL) v.k = VFALSE; /* `falses' are all equal here */ -+ luaK_goiftrue(ls->fs, &v); -+ return v.f; -+} -+ -+ -+static void breakstat (LexState *ls) { -+ FuncState *fs = ls->fs; -+ BlockCnt *bl = fs->bl; -+ int upval = 0; -+ while (bl && !bl->isbreakable) { -+ upval |= bl->upval; -+ bl = bl->previous; -+ } -+ if (!bl) -+ luaX_syntaxerror(ls, "no loop to break"); -+ if (upval) -+ luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0); -+ luaK_concat(fs, &bl->breaklist, luaK_jump(fs)); -+} -+ -+ -+static void whilestat (LexState *ls, int line) { -+ /* whilestat -> WHILE cond DO block END */ -+ FuncState *fs = ls->fs; -+ int whileinit; -+ int condexit; -+ BlockCnt bl; -+ luaX_next(ls); /* skip WHILE */ -+ whileinit = luaK_getlabel(fs); -+ condexit = cond(ls); -+ enterblock(fs, &bl, 1); -+ checknext(ls, TK_DO); -+ block(ls); -+ luaK_patchlist(fs, luaK_jump(fs), whileinit); -+ check_match(ls, TK_END, TK_WHILE, line); -+ leaveblock(fs); -+ luaK_patchtohere(fs, condexit); /* false conditions finish the loop */ -+} -+ -+ -+static void repeatstat (LexState *ls, int line) { -+ /* repeatstat -> REPEAT block UNTIL cond */ -+ int condexit; -+ FuncState *fs = ls->fs; -+ int repeat_init = luaK_getlabel(fs); -+ BlockCnt bl1, bl2; -+ enterblock(fs, &bl1, 1); /* loop block */ -+ enterblock(fs, &bl2, 0); /* scope block */ -+ luaX_next(ls); /* skip REPEAT */ -+ chunk(ls); -+ check_match(ls, TK_UNTIL, TK_REPEAT, line); -+ condexit = cond(ls); /* read condition (inside scope block) */ -+ if (!bl2.upval) { /* no upvalues? */ -+ leaveblock(fs); /* finish scope */ -+ luaK_patchlist(ls->fs, condexit, repeat_init); /* close the loop */ -+ } -+ else { /* complete semantics when there are upvalues */ -+ breakstat(ls); /* if condition then break */ -+ luaK_patchtohere(ls->fs, condexit); /* else... */ -+ leaveblock(fs); /* finish scope... */ -+ luaK_patchlist(ls->fs, luaK_jump(fs), repeat_init); /* and repeat */ -+ } -+ leaveblock(fs); /* finish loop */ -+} -+ -+ -+static int exp1 (LexState *ls) { -+ expdesc e; -+ int k; -+ expr(ls, &e); -+ k = e.k; -+ luaK_exp2nextreg(ls->fs, &e); -+ return k; -+} -+ -+ -+static void forbody (LexState *ls, int base, int line, int nvars, int isnum) { -+ /* forbody -> DO block */ -+ BlockCnt bl; -+ FuncState *fs = ls->fs; -+ int prep, endfor; -+ adjustlocalvars(ls, 3); /* control variables */ -+ checknext(ls, TK_DO); -+ prep = isnum ? luaK_codeAsBx(fs, OP_FORPREP, base, NO_JUMP) : luaK_jump(fs); -+ enterblock(fs, &bl, 0); /* scope for declared variables */ -+ adjustlocalvars(ls, nvars); -+ luaK_reserveregs(fs, nvars); -+ block(ls); -+ leaveblock(fs); /* end of scope for declared variables */ -+ luaK_patchtohere(fs, prep); -+ endfor = (isnum) ? luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP) : -+ luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars); -+ luaK_fixline(fs, line); /* pretend that `OP_FOR' starts the loop */ -+ luaK_patchlist(fs, (isnum ? endfor : luaK_jump(fs)), prep + 1); -+} -+ -+ -+static void fornum (LexState *ls, TString *varname, int line) { -+ /* fornum -> NAME = exp1,exp1[,exp1] forbody */ -+ FuncState *fs = ls->fs; -+ int base = fs->freereg; -+ new_localvarliteral(ls, "(for index)", 0); -+ new_localvarliteral(ls, "(for limit)", 1); -+ new_localvarliteral(ls, "(for step)", 2); -+ new_localvar(ls, varname, 3); -+ checknext(ls, '='); -+ exp1(ls); /* initial value */ -+ checknext(ls, ','); -+ exp1(ls); /* limit */ -+ if (testnext(ls, ',')) -+ exp1(ls); /* optional step */ -+ else { /* default step = 1 */ -+ luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1)); -+ luaK_reserveregs(fs, 1); -+ } -+ forbody(ls, base, line, 1, 1); -+} -+ -+ -+static void forlist (LexState *ls, TString *indexname) { -+ /* forlist -> NAME {,NAME} IN explist1 forbody */ -+ FuncState *fs = ls->fs; -+ expdesc e; -+ int nvars = 0; -+ int line; -+ int base = fs->freereg; -+ /* create control variables */ -+ new_localvarliteral(ls, "(for generator)", nvars++); -+ new_localvarliteral(ls, "(for state)", nvars++); -+ new_localvarliteral(ls, "(for control)", nvars++); -+ /* create declared variables */ -+ new_localvar(ls, indexname, nvars++); -+ while (testnext(ls, ',')) -+ new_localvar(ls, str_checkname(ls), nvars++); -+ checknext(ls, TK_IN); -+ line = ls->linenumber; -+ adjust_assign(ls, 3, explist1(ls, &e), &e); -+ luaK_checkstack(fs, 3); /* extra space to call generator */ -+ forbody(ls, base, line, nvars - 3, 0); -+} -+ -+ -+static void forstat (LexState *ls, int line) { -+ /* forstat -> FOR (fornum | forlist) END */ -+ FuncState *fs = ls->fs; -+ TString *varname; -+ BlockCnt bl; -+ enterblock(fs, &bl, 1); /* scope for loop and control variables */ -+ luaX_next(ls); /* skip `for' */ -+ varname = str_checkname(ls); /* first variable name */ -+ switch (ls->t.token) { -+ case '=': fornum(ls, varname, line); break; -+ case ',': case TK_IN: forlist(ls, varname); break; -+ default: luaX_syntaxerror(ls, LUA_QL("=") " or " LUA_QL("in") " expected"); -+ } -+ check_match(ls, TK_END, TK_FOR, line); -+ leaveblock(fs); /* loop scope (`break' jumps to this point) */ -+} -+ -+ -+static int test_then_block (LexState *ls) { -+ /* test_then_block -> [IF | ELSEIF] cond THEN block */ -+ int condexit; -+ luaX_next(ls); /* skip IF or ELSEIF */ -+ condexit = cond(ls); -+ checknext(ls, TK_THEN); -+ block(ls); /* `then' part */ -+ return condexit; -+} -+ -+ -+static void ifstat (LexState *ls, int line) { -+ /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */ -+ FuncState *fs = ls->fs; -+ int flist; -+ int escapelist = NO_JUMP; -+ flist = test_then_block(ls); /* IF cond THEN block */ -+ while (ls->t.token == TK_ELSEIF) { -+ luaK_concat(fs, &escapelist, luaK_jump(fs)); -+ luaK_patchtohere(fs, flist); -+ flist = test_then_block(ls); /* ELSEIF cond THEN block */ -+ } -+ if (ls->t.token == TK_ELSE) { -+ luaK_concat(fs, &escapelist, luaK_jump(fs)); -+ luaK_patchtohere(fs, flist); -+ luaX_next(ls); /* skip ELSE (after patch, for correct line info) */ -+ block(ls); /* `else' part */ -+ } -+ else -+ luaK_concat(fs, &escapelist, flist); -+ luaK_patchtohere(fs, escapelist); -+ check_match(ls, TK_END, TK_IF, line); -+} -+ -+ -+static void localfunc (LexState *ls) { -+ expdesc v, b; -+ FuncState *fs = ls->fs; -+ new_localvar(ls, str_checkname(ls), 0); -+ init_exp(&v, VLOCAL, fs->freereg); -+ luaK_reserveregs(fs, 1); -+ adjustlocalvars(ls, 1); -+ body(ls, &b, 0, ls->linenumber); -+ luaK_storevar(fs, &v, &b); -+ /* debug information will only see the variable after this point! */ -+ getlocvar(fs, fs->nactvar - 1).startpc = fs->pc; -+} -+ -+ -+static void localstat (LexState *ls) { -+ /* stat -> LOCAL NAME {`,' NAME} [`=' explist1] */ -+ int nvars = 0; -+ int nexps; -+ expdesc e; -+ do { -+ new_localvar(ls, str_checkname(ls), nvars++); -+ } while (testnext(ls, ',')); -+ if (testnext(ls, '=')) -+ nexps = explist1(ls, &e); -+ else { -+ e.k = VVOID; -+ nexps = 0; -+ } -+ adjust_assign(ls, nvars, nexps, &e); -+ adjustlocalvars(ls, nvars); -+} -+ -+ -+static int funcname (LexState *ls, expdesc *v) { -+ /* funcname -> NAME {field} [`:' NAME] */ -+ int needself = 0; -+ singlevar(ls, v); -+ while (ls->t.token == '.') -+ field(ls, v); -+ if (ls->t.token == ':') { -+ needself = 1; -+ field(ls, v); -+ } -+ return needself; -+} -+ -+ -+static void funcstat (LexState *ls, int line) { -+ /* funcstat -> FUNCTION funcname body */ -+ int needself; -+ expdesc v, b; -+ luaX_next(ls); /* skip FUNCTION */ -+ needself = funcname(ls, &v); -+ body(ls, &b, needself, line); -+ luaK_storevar(ls->fs, &v, &b); -+ luaK_fixline(ls->fs, line); /* definition `happens' in the first line */ -+} -+ -+ -+static void exprstat (LexState *ls) { -+ /* stat -> func | assignment */ -+ FuncState *fs = ls->fs; -+ struct LHS_assign v; -+ primaryexp(ls, &v.v); -+ if (v.v.k == VCALL) /* stat -> func */ -+ SETARG_C(getcode(fs, &v.v), 1); /* call statement uses no results */ -+ else { /* stat -> assignment */ -+ v.prev = NULL; -+ assignment(ls, &v, 1); -+ } -+} -+ -+ -+static void retstat (LexState *ls) { -+ /* stat -> RETURN explist */ -+ FuncState *fs = ls->fs; -+ expdesc e; -+ int first, nret; /* registers with returned values */ -+ luaX_next(ls); /* skip RETURN */ -+ if (block_follow(ls->t.token) || ls->t.token == ';') -+ first = nret = 0; /* return no values */ -+ else { -+ nret = explist1(ls, &e); /* optional return values */ -+ if (hasmultret(e.k)) { -+ luaK_setmultret(fs, &e); -+ if (e.k == VCALL && nret == 1) { /* tail call? */ -+ SET_OPCODE(getcode(fs,&e), OP_TAILCALL); -+ lua_assert(GETARG_A(getcode(fs,&e)) == fs->nactvar); -+ } -+ first = fs->nactvar; -+ nret = LUA_MULTRET; /* return all values */ -+ } -+ else { -+ if (nret == 1) /* only one single value? */ -+ first = luaK_exp2anyreg(fs, &e); -+ else { -+ luaK_exp2nextreg(fs, &e); /* values must go to the `stack' */ -+ first = fs->nactvar; /* return all `active' values */ -+ lua_assert(nret == fs->freereg - first); -+ } -+ } -+ } -+ luaK_ret(fs, first, nret); -+} -+ -+ -+static int statement (LexState *ls) { -+ int line = ls->linenumber; /* may be needed for error messages */ -+ switch (ls->t.token) { -+ case TK_IF: { /* stat -> ifstat */ -+ ifstat(ls, line); -+ return 0; -+ } -+ case TK_WHILE: { /* stat -> whilestat */ -+ whilestat(ls, line); -+ return 0; -+ } -+ case TK_DO: { /* stat -> DO block END */ -+ luaX_next(ls); /* skip DO */ -+ block(ls); -+ check_match(ls, TK_END, TK_DO, line); -+ return 0; -+ } -+ case TK_FOR: { /* stat -> forstat */ -+ forstat(ls, line); -+ return 0; -+ } -+ case TK_REPEAT: { /* stat -> repeatstat */ -+ repeatstat(ls, line); -+ return 0; -+ } -+ case TK_FUNCTION: { -+ funcstat(ls, line); /* stat -> funcstat */ -+ return 0; -+ } -+ case TK_LOCAL: { /* stat -> localstat */ -+ luaX_next(ls); /* skip LOCAL */ -+ if (testnext(ls, TK_FUNCTION)) /* local function? */ -+ localfunc(ls); -+ else -+ localstat(ls); -+ return 0; -+ } -+ case TK_RETURN: { /* stat -> retstat */ -+ retstat(ls); -+ return 1; /* must be last statement */ -+ } -+ case TK_BREAK: { /* stat -> breakstat */ -+ luaX_next(ls); /* skip BREAK */ -+ breakstat(ls); -+ return 1; /* must be last statement */ -+ } -+ default: { -+ exprstat(ls); -+ return 0; /* to avoid warnings */ -+ } -+ } -+} -+ -+ -+static void chunk (LexState *ls) { -+ /* chunk -> { stat [`;'] } */ -+ int islast = 0; -+ enterlevel(ls); -+ while (!islast && !block_follow(ls->t.token)) { -+ islast = statement(ls); -+ testnext(ls, ';'); -+ lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg && -+ ls->fs->freereg >= ls->fs->nactvar); -+ ls->fs->freereg = ls->fs->nactvar; /* free registers */ -+ } -+ leavelevel(ls); -+} -+ -+/* }====================================================================== */ ---- /dev/null -+++ b/extensions/LUA/lua/lparser.h -@@ -0,0 +1,82 @@ -+/* -+** $Id: lparser.h,v 1.57.1.1 2007/12/27 13:02:25 roberto Exp $ -+** Lua Parser -+** See Copyright Notice in lua.h -+*/ -+ -+#ifndef lparser_h -+#define lparser_h -+ -+#include "llimits.h" -+#include "lobject.h" -+#include "lzio.h" -+ -+ -+/* -+** Expression descriptor -+*/ -+ -+typedef enum { -+ VVOID, /* no value */ -+ VNIL, -+ VTRUE, -+ VFALSE, -+ VK, /* info = index of constant in `k' */ -+ VKNUM, /* nval = numerical value */ -+ VLOCAL, /* info = local register */ -+ VUPVAL, /* info = index of upvalue in `upvalues' */ -+ VGLOBAL, /* info = index of table; aux = index of global name in `k' */ -+ VINDEXED, /* info = table register; aux = index register (or `k') */ -+ VJMP, /* info = instruction pc */ -+ VRELOCABLE, /* info = instruction pc */ -+ VNONRELOC, /* info = result register */ -+ VCALL, /* info = instruction pc */ -+ VVARARG /* info = instruction pc */ -+} expkind; -+ -+typedef struct expdesc { -+ expkind k; -+ union { -+ struct { int info, aux; } s; -+ lua_Number nval; -+ } u; -+ int t; /* patch list of `exit when true' */ -+ int f; /* patch list of `exit when false' */ -+} expdesc; -+ -+ -+typedef struct upvaldesc { -+ lu_byte k; -+ lu_byte info; -+} upvaldesc; -+ -+ -+struct BlockCnt; /* defined in lparser.c */ -+ -+ -+/* state needed to generate code for a given function */ -+typedef struct FuncState { -+ Proto *f; /* current function header */ -+ Table *h; /* table to find (and reuse) elements in `k' */ -+ struct FuncState *prev; /* enclosing function */ -+ struct LexState *ls; /* lexical state */ -+ struct lua_State *L; /* copy of the Lua state */ -+ struct BlockCnt *bl; /* chain of current blocks */ -+ int pc; /* next position to code (equivalent to `ncode') */ -+ int lasttarget; /* `pc' of last `jump target' */ -+ int jpc; /* list of pending jumps to `pc' */ -+ int freereg; /* first free register */ -+ int nk; /* number of elements in `k' */ -+ int np; /* number of elements in `p' */ -+ short nlocvars; /* number of elements in `locvars' */ -+ lu_byte nactvar; /* number of active local variables */ -+ upvaldesc upvalues[LUAI_MAXUPVALUES]; /* upvalues */ -+ unsigned short actvar[LUAI_MAXVARS]; /* declared-variable stack */ -+} FuncState; -+ -+ -+LUAI_FUNC Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, -+ const char *name); -+ -+ -+#endif ---- /dev/null -+++ b/extensions/LUA/lua/lstate.c -@@ -0,0 +1,214 @@ -+/* -+** $Id: lstate.c,v 2.36.1.2 2008/01/03 15:20:39 roberto Exp $ -+** Global State -+** See Copyright Notice in lua.h -+*/ -+ -+ -+#include -+ -+#define lstate_c -+#define LUA_CORE -+ -+#include "lua.h" -+ -+#include "ldebug.h" -+#include "ldo.h" -+#include "lfunc.h" -+#include "lgc.h" -+#include "llex.h" -+#include "lmem.h" -+#include "lstate.h" -+#include "lstring.h" -+#include "ltable.h" -+#include "ltm.h" -+ -+ -+#define state_size(x) (sizeof(x) + LUAI_EXTRASPACE) -+#define fromstate(l) (cast(lu_byte *, (l)) - LUAI_EXTRASPACE) -+#define tostate(l) (cast(lua_State *, cast(lu_byte *, l) + LUAI_EXTRASPACE)) -+ -+ -+/* -+** Main thread combines a thread state and the global state -+*/ -+typedef struct LG { -+ lua_State l; -+ global_State g; -+} LG; -+ -+ -+ -+static void stack_init (lua_State *L1, lua_State *L) { -+ /* initialize CallInfo array */ -+ L1->base_ci = luaM_newvector(L, BASIC_CI_SIZE, CallInfo); -+ L1->ci = L1->base_ci; -+ L1->size_ci = BASIC_CI_SIZE; -+ L1->end_ci = L1->base_ci + L1->size_ci - 1; -+ /* initialize stack array */ -+ L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TValue); -+ L1->stacksize = BASIC_STACK_SIZE + EXTRA_STACK; -+ L1->top = L1->stack; -+ L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1; -+ /* initialize first ci */ -+ L1->ci->func = L1->top; -+ setnilvalue(L1->top++); /* `function' entry for this `ci' */ -+ L1->base = L1->ci->base = L1->top; -+ L1->ci->top = L1->top + LUA_MINSTACK; -+} -+ -+ -+static void freestack (lua_State *L, lua_State *L1) { -+ luaM_freearray(L, L1->base_ci, L1->size_ci, CallInfo); -+ luaM_freearray(L, L1->stack, L1->stacksize, TValue); -+} -+ -+ -+/* -+** open parts that may cause memory-allocation errors -+*/ -+static void f_luaopen (lua_State *L, void *ud) { -+ global_State *g = G(L); -+ UNUSED(ud); -+ stack_init(L, L); /* init stack */ -+ sethvalue(L, gt(L), luaH_new(L, 0, 2)); /* table of globals */ -+ sethvalue(L, registry(L), luaH_new(L, 0, 2)); /* registry */ -+ luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */ -+ luaT_init(L); -+ luaX_init(L); -+ luaS_fix(luaS_newliteral(L, MEMERRMSG)); -+ g->GCthreshold = 4*g->totalbytes; -+} -+ -+ -+static void preinit_state (lua_State *L, global_State *g) { -+ G(L) = g; -+ L->stack = NULL; -+ L->stacksize = 0; -+ L->errorJmp = NULL; -+ L->hook = NULL; -+ L->hookmask = 0; -+ L->basehookcount = 0; -+ L->allowhook = 1; -+ resethookcount(L); -+ L->openupval = NULL; -+ L->size_ci = 0; -+ L->nCcalls = L->baseCcalls = 0; -+ L->status = 0; -+ L->base_ci = L->ci = NULL; -+ L->savedpc = NULL; -+ L->errfunc = 0; -+ setnilvalue(gt(L)); -+} -+ -+ -+static void close_state (lua_State *L) { -+ global_State *g = G(L); -+ luaF_close(L, L->stack); /* close all upvalues for this thread */ -+ luaC_freeall(L); /* collect all objects */ -+ lua_assert(g->rootgc == obj2gco(L)); -+ lua_assert(g->strt.nuse == 0); -+ luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *); -+ luaZ_freebuffer(L, &g->buff); -+ freestack(L, L); -+ lua_assert(g->totalbytes == sizeof(LG)); -+ (*g->frealloc)(g->ud, fromstate(L), state_size(LG), 0); -+} -+ -+ -+lua_State *luaE_newthread (lua_State *L) { -+ lua_State *L1 = tostate(luaM_malloc(L, state_size(lua_State))); -+ luaC_link(L, obj2gco(L1), LUA_TTHREAD); -+ preinit_state(L1, G(L)); -+ stack_init(L1, L); /* init stack */ -+ setobj2n(L, gt(L1), gt(L)); /* share table of globals */ -+ L1->hookmask = L->hookmask; -+ L1->basehookcount = L->basehookcount; -+ L1->hook = L->hook; -+ resethookcount(L1); -+ lua_assert(iswhite(obj2gco(L1))); -+ return L1; -+} -+ -+ -+void luaE_freethread (lua_State *L, lua_State *L1) { -+ luaF_close(L1, L1->stack); /* close all upvalues for this thread */ -+ lua_assert(L1->openupval == NULL); -+ luai_userstatefree(L1); -+ freestack(L, L1); -+ luaM_freemem(L, fromstate(L1), state_size(lua_State)); -+} -+ -+ -+LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { -+ int i; -+ lua_State *L; -+ global_State *g; -+ void *l = (*f)(ud, NULL, 0, state_size(LG)); -+ if (l == NULL) return NULL; -+ L = tostate(l); -+ g = &((LG *)L)->g; -+ L->next = NULL; -+ L->tt = LUA_TTHREAD; -+ g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT); -+ L->marked = luaC_white(g); -+ set2bits(L->marked, FIXEDBIT, SFIXEDBIT); -+ preinit_state(L, g); -+ g->frealloc = f; -+ g->ud = ud; -+ g->mainthread = L; -+ g->uvhead.u.l.prev = &g->uvhead; -+ g->uvhead.u.l.next = &g->uvhead; -+ g->GCthreshold = 0; /* mark it as unfinished state */ -+ g->strt.size = 0; -+ g->strt.nuse = 0; -+ g->strt.hash = NULL; -+ setnilvalue(registry(L)); -+ luaZ_initbuffer(L, &g->buff); -+ g->panic = NULL; -+ g->gcstate = GCSpause; -+ g->rootgc = obj2gco(L); -+ g->sweepstrgc = 0; -+ g->sweepgc = &g->rootgc; -+ g->gray = NULL; -+ g->grayagain = NULL; -+ g->weak = NULL; -+ g->tmudata = NULL; -+ g->totalbytes = sizeof(LG); -+ g->gcpause = LUAI_GCPAUSE; -+ g->gcstepmul = LUAI_GCMUL; -+ g->gcdept = 0; -+ for (i=0; imt[i] = NULL; -+ if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) { -+ /* memory allocation error: free partial state */ -+ close_state(L); -+ L = NULL; -+ } -+ else -+ luai_userstateopen(L); -+ return L; -+} -+ -+ -+static void callallgcTM (lua_State *L, void *ud) { -+ UNUSED(ud); -+ luaC_callGCTM(L); /* call GC metamethods for all udata */ -+} -+ -+ -+LUA_API void lua_close (lua_State *L) { -+ L = G(L)->mainthread; /* only the main thread can be closed */ -+ lua_lock(L); -+ luaF_close(L, L->stack); /* close all upvalues for this thread */ -+ luaC_separateudata(L, 1); /* separate udata that have GC metamethods */ -+ L->errfunc = 0; /* no error function during GC metamethods */ -+ do { /* repeat until no more errors */ -+ L->ci = L->base_ci; -+ L->base = L->top = L->ci->base; -+ L->nCcalls = L->baseCcalls = 0; -+ } while (luaD_rawrunprotected(L, callallgcTM, NULL) != 0); -+ lua_assert(G(L)->tmudata == NULL); -+ luai_userstateclose(L); -+ close_state(L); -+} -+ ---- /dev/null -+++ b/extensions/LUA/lua/lstate.h -@@ -0,0 +1,169 @@ -+/* -+** $Id: lstate.h,v 2.24.1.2 2008/01/03 15:20:39 roberto Exp $ -+** Global State -+** See Copyright Notice in lua.h -+*/ -+ -+#ifndef lstate_h -+#define lstate_h -+ -+#include "lua.h" -+ -+#include "lobject.h" -+#include "ltm.h" -+#include "lzio.h" -+ -+ -+ -+struct lua_longjmp; /* defined in ldo.c */ -+ -+ -+/* table of globals */ -+#define gt(L) (&L->l_gt) -+ -+/* registry */ -+#define registry(L) (&G(L)->l_registry) -+ -+ -+/* extra stack space to handle TM calls and some other extras */ -+#define EXTRA_STACK 5 -+ -+ -+#define BASIC_CI_SIZE 8 -+ -+#define BASIC_STACK_SIZE (2*LUA_MINSTACK) -+ -+ -+ -+typedef struct stringtable { -+ GCObject **hash; -+ lu_int32 nuse; /* number of elements */ -+ int size; -+} stringtable; -+ -+ -+/* -+** informations about a call -+*/ -+typedef struct CallInfo { -+ StkId base; /* base for this function */ -+ StkId func; /* function index in the stack */ -+ StkId top; /* top for this function */ -+ const Instruction *savedpc; -+ int nresults; /* expected number of results from this function */ -+ int tailcalls; /* number of tail calls lost under this entry */ -+} CallInfo; -+ -+ -+ -+#define curr_func(L) (clvalue(L->ci->func)) -+#define ci_func(ci) (clvalue((ci)->func)) -+#define f_isLua(ci) (!ci_func(ci)->c.isC) -+#define isLua(ci) (ttisfunction((ci)->func) && f_isLua(ci)) -+ -+ -+/* -+** `global state', shared by all threads of this state -+*/ -+typedef struct global_State { -+ stringtable strt; /* hash table for strings */ -+ lua_Alloc frealloc; /* function to reallocate memory */ -+ void *ud; /* auxiliary data to `frealloc' */ -+ lu_byte currentwhite; -+ lu_byte gcstate; /* state of garbage collector */ -+ int sweepstrgc; /* position of sweep in `strt' */ -+ GCObject *rootgc; /* list of all collectable objects */ -+ GCObject **sweepgc; /* position of sweep in `rootgc' */ -+ GCObject *gray; /* list of gray objects */ -+ GCObject *grayagain; /* list of objects to be traversed atomically */ -+ GCObject *weak; /* list of weak tables (to be cleared) */ -+ GCObject *tmudata; /* last element of list of userdata to be GC */ -+ Mbuffer buff; /* temporary buffer for string concatentation */ -+ lu_mem GCthreshold; -+ lu_mem totalbytes; /* number of bytes currently allocated */ -+ lu_mem estimate; /* an estimate of number of bytes actually in use */ -+ lu_mem gcdept; /* how much GC is `behind schedule' */ -+ int gcpause; /* size of pause between successive GCs */ -+ int gcstepmul; /* GC `granularity' */ -+ lua_CFunction panic; /* to be called in unprotected errors */ -+ TValue l_registry; -+ struct lua_State *mainthread; -+ UpVal uvhead; /* head of double-linked list of all open upvalues */ -+ struct Table *mt[NUM_TAGS]; /* metatables for basic types */ -+ TString *tmname[TM_N]; /* array with tag-method names */ -+} global_State; -+ -+ -+/* -+** `per thread' state -+*/ -+struct lua_State { -+ CommonHeader; -+ lu_byte status; -+ StkId top; /* first free slot in the stack */ -+ StkId base; /* base of current function */ -+ global_State *l_G; -+ CallInfo *ci; /* call info for current function */ -+ const Instruction *savedpc; /* `savedpc' of current function */ -+ StkId stack_last; /* last free slot in the stack */ -+ StkId stack; /* stack base */ -+ CallInfo *end_ci; /* points after end of ci array*/ -+ CallInfo *base_ci; /* array of CallInfo's */ -+ int stacksize; -+ int size_ci; /* size of array `base_ci' */ -+ unsigned short nCcalls; /* number of nested C calls */ -+ unsigned short baseCcalls; /* nested C calls when resuming coroutine */ -+ lu_byte hookmask; -+ lu_byte allowhook; -+ int basehookcount; -+ int hookcount; -+ lua_Hook hook; -+ TValue l_gt; /* table of globals */ -+ TValue env; /* temporary place for environments */ -+ GCObject *openupval; /* list of open upvalues in this stack */ -+ GCObject *gclist; -+ struct lua_longjmp *errorJmp; /* current error recover point */ -+ ptrdiff_t errfunc; /* current error handling function (stack index) */ -+}; -+ -+ -+#define G(L) (L->l_G) -+ -+ -+/* -+** Union of all collectable objects -+*/ -+union GCObject { -+ GCheader gch; -+ union TString ts; -+ union Udata u; -+ union Closure cl; -+ struct Table h; -+ struct Proto p; -+ struct UpVal uv; -+ struct lua_State th; /* thread */ -+}; -+ -+ -+/* macros to convert a GCObject into a specific value */ -+#define rawgco2ts(o) check_exp((o)->gch.tt == LUA_TSTRING, &((o)->ts)) -+#define gco2ts(o) (&rawgco2ts(o)->tsv) -+#define rawgco2u(o) check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u)) -+#define gco2u(o) (&rawgco2u(o)->uv) -+#define gco2cl(o) check_exp((o)->gch.tt == LUA_TFUNCTION, &((o)->cl)) -+#define gco2h(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h)) -+#define gco2p(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p)) -+#define gco2uv(o) check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv)) -+#define ngcotouv(o) \ -+ check_exp((o) == NULL || (o)->gch.tt == LUA_TUPVAL, &((o)->uv)) -+#define gco2th(o) check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th)) -+ -+/* macro to convert any Lua object into a GCObject */ -+#define obj2gco(v) (cast(GCObject *, (v))) -+ -+ -+LUAI_FUNC lua_State *luaE_newthread (lua_State *L); -+LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1); -+ -+#endif -+ ---- /dev/null -+++ b/extensions/LUA/lua/lstring.c -@@ -0,0 +1,110 @@ -+/* -+** $Id: lstring.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $ -+** String table (keeps all strings handled by Lua) -+** See Copyright Notice in lua.h -+*/ -+ -+#include -+ -+#define lstring_c -+#define LUA_CORE -+ -+#include "lua.h" -+ -+#include "lmem.h" -+#include "lobject.h" -+#include "lstate.h" -+#include "lstring.h" -+ -+ -+ -+void luaS_resize (lua_State *L, int newsize) { -+ GCObject **newhash; -+ stringtable *tb; -+ int i; -+ if (G(L)->gcstate == GCSsweepstring) -+ return; /* cannot resize during GC traverse */ -+ newhash = luaM_newvector(L, newsize, GCObject *); -+ tb = &G(L)->strt; -+ for (i=0; isize; i++) { -+ GCObject *p = tb->hash[i]; -+ while (p) { /* for each node in the list */ -+ GCObject *next = p->gch.next; /* save next */ -+ unsigned int h = gco2ts(p)->hash; -+ int h1 = lmod(h, newsize); /* new position */ -+ lua_assert(cast_int(h%newsize) == lmod(h, newsize)); -+ p->gch.next = newhash[h1]; /* chain it */ -+ newhash[h1] = p; -+ p = next; -+ } -+ } -+ luaM_freearray(L, tb->hash, tb->size, TString *); -+ tb->size = newsize; -+ tb->hash = newhash; -+} -+ -+ -+static TString *newlstr (lua_State *L, const char *str, size_t l, -+ unsigned int h) { -+ TString *ts; -+ stringtable *tb; -+ if (l+1 > (MAX_SIZET - sizeof(TString))/sizeof(char)) -+ luaM_toobig(L); -+ ts = cast(TString *, luaM_malloc(L, (l+1)*sizeof(char)+sizeof(TString))); -+ ts->tsv.len = l; -+ ts->tsv.hash = h; -+ ts->tsv.marked = luaC_white(G(L)); -+ ts->tsv.tt = LUA_TSTRING; -+ ts->tsv.reserved = 0; -+ memcpy(ts+1, str, l*sizeof(char)); -+ ((char *)(ts+1))[l] = '\0'; /* ending 0 */ -+ tb = &G(L)->strt; -+ h = lmod(h, tb->size); -+ ts->tsv.next = tb->hash[h]; /* chain new entry */ -+ tb->hash[h] = obj2gco(ts); -+ tb->nuse++; -+ if (tb->nuse > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2) -+ luaS_resize(L, tb->size*2); /* too crowded */ -+ return ts; -+} -+ -+ -+TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { -+ GCObject *o; -+ unsigned int h = cast(unsigned int, l); /* seed */ -+ size_t step = (l>>5)+1; /* if string is too long, don't hash all its chars */ -+ size_t l1; -+ for (l1=l; l1>=step; l1-=step) /* compute hash */ -+ h = h ^ ((h<<5)+(h>>2)+cast(unsigned char, str[l1-1])); -+ for (o = G(L)->strt.hash[lmod(h, G(L)->strt.size)]; -+ o != NULL; -+ o = o->gch.next) { -+ TString *ts = rawgco2ts(o); -+ if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0)) { -+ /* string may be dead */ -+ if (isdead(G(L), o)) changewhite(o); -+ return ts; -+ } -+ } -+ return newlstr(L, str, l, h); /* not found */ -+} -+ -+ -+Udata *luaS_newudata (lua_State *L, size_t s, Table *e) { -+ Udata *u; -+ if (s > MAX_SIZET - sizeof(Udata)) -+ luaM_toobig(L); -+ u = cast(Udata *, luaM_malloc(L, s + sizeof(Udata))); -+ u->uv.marked = luaC_white(G(L)); /* is not finalized */ -+ u->uv.tt = LUA_TUSERDATA; -+ u->uv.len = s; -+ u->uv.metatable = NULL; -+ u->uv.env = e; -+ /* chain it on udata list (after main thread) */ -+ u->uv.next = G(L)->mainthread->next; -+ G(L)->mainthread->next = obj2gco(u); -+ return u; -+} -+ ---- /dev/null -+++ b/extensions/LUA/lua/lstring.h -@@ -0,0 +1,31 @@ -+/* -+** $Id: lstring.h,v 1.43.1.1 2007/12/27 13:02:25 roberto Exp $ -+** String table (keep all strings handled by Lua) -+** See Copyright Notice in lua.h -+*/ -+ -+#ifndef lstring_h -+#define lstring_h -+ -+ -+#include "lgc.h" -+#include "lobject.h" -+#include "lstate.h" -+ -+ -+#define sizestring(s) (sizeof(union TString)+((s)->len+1)*sizeof(char)) -+ -+#define sizeudata(u) (sizeof(union Udata)+(u)->len) -+ -+#define luaS_new(L, s) (luaS_newlstr(L, s, strlen(s))) -+#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ -+ (sizeof(s)/sizeof(char))-1)) -+ -+#define luaS_fix(s) l_setbit((s)->tsv.marked, FIXEDBIT) -+ -+LUAI_FUNC void luaS_resize (lua_State *L, int newsize); -+LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e); -+LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l); -+ -+ -+#endif ---- /dev/null -+++ b/extensions/LUA/lua/lstrlib.c -@@ -0,0 +1,883 @@ -+/* -+** $Id: lstrlib.c,v 1.132.1.4 2008/07/11 17:27:21 roberto Exp $ -+** Standard library for string operations and pattern-matching -+** See Copyright Notice in lua.h -+*/ -+ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#define lstrlib_c -+#define LUA_LIB -+ -+#include "lua.h" -+ -+#include "lauxlib.h" -+#include "lualib.h" -+ -+ -+/* macro to `unsign' a character */ -+#define uchar(c) ((unsigned char)(c)) -+ -+ -+ -+static int str_len (lua_State *L) { -+ size_t l; -+ luaL_checklstring(L, 1, &l); -+ lua_pushinteger(L, l); -+ return 1; -+} -+ -+ -+static ptrdiff_t posrelat (ptrdiff_t pos, size_t len) { -+ /* relative string position: negative means back from end */ -+ if (pos < 0) pos += (ptrdiff_t)len + 1; -+ return (pos >= 0) ? pos : 0; -+} -+ -+ -+static int str_sub (lua_State *L) { -+ size_t l; -+ const char *s = luaL_checklstring(L, 1, &l); -+ ptrdiff_t start = posrelat(luaL_checkinteger(L, 2), l); -+ ptrdiff_t end = posrelat(luaL_optinteger(L, 3, -1), l); -+ if (start < 1) start = 1; -+ if (end > (ptrdiff_t)l) end = (ptrdiff_t)l; -+ if (start <= end) -+ lua_pushlstring(L, s+start-1, end-start+1); -+ else lua_pushliteral(L, ""); -+ return 1; -+} -+ -+ -+static int str_reverse (lua_State *L) { -+ size_t l; -+ const char *s = luaL_checklstring(L, 1, &l); -+ luaL_Buffer *b = (luaL_Buffer *)kmalloc(sizeof(luaL_Buffer) + BUFSIZ, GFP_ATOMIC); -+ if(!b) luaL_error(L, "str_reverse: cannot allocate memory"); -+ luaL_buffinit(L, b); -+ while (l--) luaL_addchar(b, s[l]); -+ luaL_pushresult(b); -+ kfree(b); -+ return 1; -+} -+ -+ -+static int str_lower (lua_State *L) { -+ size_t l; -+ size_t i; -+ const char *s = luaL_checklstring(L, 1, &l); -+ luaL_Buffer *b = (luaL_Buffer *)kmalloc(sizeof(luaL_Buffer) + BUFSIZ, GFP_ATOMIC); -+ if(!b) luaL_error(L, "str_lower: cannot allocate memory"); -+ luaL_buffinit(L, b); -+ for (i=0; i 0) -+ luaL_addlstring(b, s, l); -+ luaL_pushresult(b); -+ kfree(b); -+ return 1; -+} -+ -+ -+static int str_byte (lua_State *L) { -+ size_t l; -+ const char *s = luaL_checklstring(L, 1, &l); -+ ptrdiff_t posi = posrelat(luaL_optinteger(L, 2, 1), l); -+ ptrdiff_t pose = posrelat(luaL_optinteger(L, 3, posi), l); -+ int n, i; -+ if (posi <= 0) posi = 1; -+ if ((size_t)pose > l) pose = l; -+ if (posi > pose) return 0; /* empty interval; return no values */ -+ n = (int)(pose - posi + 1); -+ if (posi + n <= pose) /* overflow? */ -+ luaL_error(L, "string slice too long"); -+ luaL_checkstack(L, n, "string slice too long"); -+ for (i=0; i= ms->level || ms->capture[l].len == CAP_UNFINISHED) -+ return luaL_error(ms->L, "invalid capture index"); -+ return l; -+} -+ -+ -+static int capture_to_close (MatchState *ms) { -+ int level = ms->level; -+ for (level--; level>=0; level--) -+ if (ms->capture[level].len == CAP_UNFINISHED) return level; -+ return luaL_error(ms->L, "invalid pattern capture"); -+} -+ -+ -+static const char *classend (MatchState *ms, const char *p) { -+ switch (*p++) { -+ case L_ESC: { -+ if (*p == '\0') -+ luaL_error(ms->L, "malformed pattern (ends with " LUA_QL("%%") ")"); -+ return p+1; -+ } -+ case '[': { -+ if (*p == '^') p++; -+ do { /* look for a `]' */ -+ if (*p == '\0') -+ luaL_error(ms->L, "malformed pattern (missing " LUA_QL("]") ")"); -+ if (*(p++) == L_ESC && *p != '\0') -+ p++; /* skip escapes (e.g. `%]') */ -+ } while (*p != ']'); -+ return p+1; -+ } -+ default: { -+ return p; -+ } -+ } -+} -+ -+ -+static int match_class (int c, int cl) { -+ int res; -+ switch (tolower(cl)) { -+ case 'a' : res = isalpha(c); break; -+ case 'c' : res = iscntrl(c); break; -+ case 'd' : res = isdigit(c); break; -+ case 'l' : res = islower(c); break; -+ case 'p' : res = ispunct(c); break; -+ case 's' : res = isspace(c); break; -+ case 'u' : res = isupper(c); break; -+ case 'w' : res = isalnum(c); break; -+ case 'x' : res = isxdigit(c); break; -+ case 'z' : res = (c == 0); break; -+ default: return (cl == c); -+ } -+ return (islower(cl) ? res : !res); -+} -+ -+ -+static int matchbracketclass (int c, const char *p, const char *ec) { -+ int sig = 1; -+ if (*(p+1) == '^') { -+ sig = 0; -+ p++; /* skip the `^' */ -+ } -+ while (++p < ec) { -+ if (*p == L_ESC) { -+ p++; -+ if (match_class(c, uchar(*p))) -+ return sig; -+ } -+ else if ((*(p+1) == '-') && (p+2 < ec)) { -+ p+=2; -+ if (uchar(*(p-2)) <= c && c <= uchar(*p)) -+ return sig; -+ } -+ else if (uchar(*p) == c) return sig; -+ } -+ return !sig; -+} -+ -+ -+static int singlematch (int c, const char *p, const char *ep) { -+ switch (*p) { -+ case '.': return 1; /* matches any char */ -+ case L_ESC: return match_class(c, uchar(*(p+1))); -+ case '[': return matchbracketclass(c, p, ep-1); -+ default: return (uchar(*p) == c); -+ } -+} -+ -+ -+static const char *match (MatchState *ms, const char *s, const char *p); -+ -+ -+static const char *matchbalance (MatchState *ms, const char *s, -+ const char *p) { -+ if (*p == 0 || *(p+1) == 0) -+ luaL_error(ms->L, "unbalanced pattern"); -+ if (*s != *p) return NULL; -+ else { -+ int b = *p; -+ int e = *(p+1); -+ int cont = 1; -+ while (++s < ms->src_end) { -+ if (*s == e) { -+ if (--cont == 0) return s+1; -+ } -+ else if (*s == b) cont++; -+ } -+ } -+ return NULL; /* string ends out of balance */ -+} -+ -+ -+static const char *max_expand (MatchState *ms, const char *s, -+ const char *p, const char *ep) { -+ ptrdiff_t i = 0; /* counts maximum expand for item */ -+ while ((s+i)src_end && singlematch(uchar(*(s+i)), p, ep)) -+ i++; -+ /* keeps trying to match with the maximum repetitions */ -+ while (i>=0) { -+ const char *res = match(ms, (s+i), ep+1); -+ if (res) return res; -+ i--; /* else didn't match; reduce 1 repetition to try again */ -+ } -+ return NULL; -+} -+ -+ -+static const char *min_expand (MatchState *ms, const char *s, -+ const char *p, const char *ep) { -+ for (;;) { -+ const char *res = match(ms, s, ep+1); -+ if (res != NULL) -+ return res; -+ else if (ssrc_end && singlematch(uchar(*s), p, ep)) -+ s++; /* try with one more repetition */ -+ else return NULL; -+ } -+} -+ -+ -+static const char *start_capture (MatchState *ms, const char *s, -+ const char *p, int what) { -+ const char *res; -+ int level = ms->level; -+ if (level >= LUA_MAXCAPTURES) luaL_error(ms->L, "too many captures"); -+ ms->capture[level].init = s; -+ ms->capture[level].len = what; -+ ms->level = level+1; -+ if ((res=match(ms, s, p)) == NULL) /* match failed? */ -+ ms->level--; /* undo capture */ -+ return res; -+} -+ -+ -+static const char *end_capture (MatchState *ms, const char *s, -+ const char *p) { -+ int l = capture_to_close(ms); -+ const char *res; -+ ms->capture[l].len = s - ms->capture[l].init; /* close capture */ -+ if ((res = match(ms, s, p)) == NULL) /* match failed? */ -+ ms->capture[l].len = CAP_UNFINISHED; /* undo capture */ -+ return res; -+} -+ -+ -+static const char *match_capture (MatchState *ms, const char *s, int l) { -+ size_t len; -+ l = check_capture(ms, l); -+ len = ms->capture[l].len; -+ if ((size_t)(ms->src_end-s) >= len && -+ memcmp(ms->capture[l].init, s, len) == 0) -+ return s+len; -+ else return NULL; -+} -+ -+ -+static const char *match (MatchState *ms, const char *s, const char *p) { -+ init: /* using goto's to optimize tail recursion */ -+ switch (*p) { -+ case '(': { /* start capture */ -+ if (*(p+1) == ')') /* position capture? */ -+ return start_capture(ms, s, p+2, CAP_POSITION); -+ else -+ return start_capture(ms, s, p+1, CAP_UNFINISHED); -+ } -+ case ')': { /* end capture */ -+ return end_capture(ms, s, p+1); -+ } -+ case L_ESC: { -+ switch (*(p+1)) { -+ case 'b': { /* balanced string? */ -+ s = matchbalance(ms, s, p+2); -+ if (s == NULL) return NULL; -+ p+=4; goto init; /* else return match(ms, s, p+4); */ -+ } -+ case 'f': { /* frontier? */ -+ const char *ep; char previous; -+ p += 2; -+ if (*p != '[') -+ luaL_error(ms->L, "missing " LUA_QL("[") " after " -+ LUA_QL("%%f") " in pattern"); -+ ep = classend(ms, p); /* points to what is next */ -+ previous = (s == ms->src_init) ? '\0' : *(s-1); -+ if (matchbracketclass(uchar(previous), p, ep-1) || -+ !matchbracketclass(uchar(*s), p, ep-1)) return NULL; -+ p=ep; goto init; /* else return match(ms, s, ep); */ -+ } -+ default: { -+ if (isdigit(uchar(*(p+1)))) { /* capture results (%0-%9)? */ -+ s = match_capture(ms, s, uchar(*(p+1))); -+ if (s == NULL) return NULL; -+ p+=2; goto init; /* else return match(ms, s, p+2) */ -+ } -+ goto dflt; /* case default */ -+ } -+ } -+ } -+ case '\0': { /* end of pattern */ -+ return s; /* match succeeded */ -+ } -+ case '$': { -+ if (*(p+1) == '\0') /* is the `$' the last char in pattern? */ -+ return (s == ms->src_end) ? s : NULL; /* check end of string */ -+ else goto dflt; -+ } -+ default: dflt: { /* it is a pattern item */ -+ const char *ep = classend(ms, p); /* points to what is next */ -+ int m = ssrc_end && singlematch(uchar(*s), p, ep); -+ switch (*ep) { -+ case '?': { /* optional */ -+ const char *res; -+ if (m && ((res=match(ms, s+1, ep+1)) != NULL)) -+ return res; -+ p=ep+1; goto init; /* else return match(ms, s, ep+1); */ -+ } -+ case '*': { /* 0 or more repetitions */ -+ return max_expand(ms, s, p, ep); -+ } -+ case '+': { /* 1 or more repetitions */ -+ return (m ? max_expand(ms, s+1, p, ep) : NULL); -+ } -+ case '-': { /* 0 or more repetitions (minimum) */ -+ return min_expand(ms, s, p, ep); -+ } -+ default: { -+ if (!m) return NULL; -+ s++; p=ep; goto init; /* else return match(ms, s+1, ep); */ -+ } -+ } -+ } -+ } -+} -+ -+ -+ -+static const char *lmemfind (const char *s1, size_t l1, -+ const char *s2, size_t l2) { -+ if (l2 == 0) return s1; /* empty strings are everywhere */ -+ else if (l2 > l1) return NULL; /* avoids a negative `l1' */ -+ else { -+ const char *init; /* to search for a `*s2' inside `s1' */ -+ l2--; /* 1st char will be checked by `memchr' */ -+ l1 = l1-l2; /* `s2' cannot be found after that */ -+ while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) { -+ init++; /* 1st char is already checked */ -+ if (memcmp(init, s2+1, l2) == 0) -+ return init-1; -+ else { /* correct `l1' and `s1' to try again */ -+ l1 -= init-s1; -+ s1 = init; -+ } -+ } -+ return NULL; /* not found */ -+ } -+} -+ -+ -+static void push_onecapture (MatchState *ms, int i, const char *s, -+ const char *e) { -+ if (i >= ms->level) { -+ if (i == 0) /* ms->level == 0, too */ -+ lua_pushlstring(ms->L, s, e - s); /* add whole match */ -+ else -+ luaL_error(ms->L, "invalid capture index"); -+ } -+ else { -+ ptrdiff_t l = ms->capture[i].len; -+ if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture"); -+ if (l == CAP_POSITION) -+ lua_pushinteger(ms->L, ms->capture[i].init - ms->src_init + 1); -+ else -+ lua_pushlstring(ms->L, ms->capture[i].init, l); -+ } -+} -+ -+ -+static int push_captures (MatchState *ms, const char *s, const char *e) { -+ int i; -+ int nlevels = (ms->level == 0 && s) ? 1 : ms->level; -+ luaL_checkstack(ms->L, nlevels, "too many captures"); -+ for (i = 0; i < nlevels; i++) -+ push_onecapture(ms, i, s, e); -+ return nlevels; /* number of strings pushed */ -+} -+ -+ -+static int str_find_aux (lua_State *L, int find) { -+ size_t l1, l2; -+ const char *s = luaL_checklstring(L, 1, &l1); -+ const char *p = luaL_checklstring(L, 2, &l2); -+ ptrdiff_t init = posrelat(luaL_optinteger(L, 3, 1), l1) - 1; -+ if (init < 0) init = 0; -+ else if ((size_t)(init) > l1) init = (ptrdiff_t)l1; -+ if (find && (lua_toboolean(L, 4) || /* explicit request? */ -+ strpbrk(p, SPECIALS) == NULL)) { /* or no special characters? */ -+ /* do a plain search */ -+ const char *s2 = lmemfind(s+init, l1-init, p, l2); -+ if (s2) { -+ lua_pushinteger(L, s2-s+1); -+ lua_pushinteger(L, s2-s+l2); -+ return 2; -+ } -+ } -+ else { -+ MatchState ms; -+ int anchor = (*p == '^') ? (p++, 1) : 0; -+ const char *s1=s+init; -+ ms.L = L; -+ ms.src_init = s; -+ ms.src_end = s+l1; -+ do { -+ const char *res; -+ ms.level = 0; -+ if ((res=match(&ms, s1, p)) != NULL) { -+ if (find) { -+ lua_pushinteger(L, s1-s+1); /* start */ -+ lua_pushinteger(L, res-s); /* end */ -+ return push_captures(&ms, NULL, 0) + 2; -+ } -+ else -+ return push_captures(&ms, s1, res); -+ } -+ } while (s1++ < ms.src_end && !anchor); -+ } -+ lua_pushnil(L); /* not found */ -+ return 1; -+} -+ -+ -+static int str_find (lua_State *L) { -+ return str_find_aux(L, 1); -+} -+ -+ -+static int str_match (lua_State *L) { -+ return str_find_aux(L, 0); -+} -+ -+ -+static int gmatch_aux (lua_State *L) { -+ MatchState ms; -+ size_t ls; -+ const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls); -+ const char *p = lua_tostring(L, lua_upvalueindex(2)); -+ const char *src; -+ ms.L = L; -+ ms.src_init = s; -+ ms.src_end = s+ls; -+ for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3)); -+ src <= ms.src_end; -+ src++) { -+ const char *e; -+ ms.level = 0; -+ if ((e = match(&ms, src, p)) != NULL) { -+ lua_Integer newstart = e-s; -+ if (e == src) newstart++; /* empty match? go at least one position */ -+ lua_pushinteger(L, newstart); -+ lua_replace(L, lua_upvalueindex(3)); -+ return push_captures(&ms, src, e); -+ } -+ } -+ return 0; /* not found */ -+} -+ -+ -+static int gmatch (lua_State *L) { -+ luaL_checkstring(L, 1); -+ luaL_checkstring(L, 2); -+ lua_settop(L, 2); -+ lua_pushinteger(L, 0); -+ lua_pushcclosure(L, gmatch_aux, 3); -+ return 1; -+} -+ -+ -+static int gfind_nodef (lua_State *L) { -+ return luaL_error(L, LUA_QL("string.gfind") " was renamed to " -+ LUA_QL("string.gmatch")); -+} -+ -+ -+static void add_s (MatchState *ms, luaL_Buffer *b, const char *s, -+ const char *e) { -+ size_t l, i; -+ const char *news = lua_tolstring(ms->L, 3, &l); -+ for (i = 0; i < l; i++) { -+ if (news[i] != L_ESC) -+ luaL_addchar(b, news[i]); -+ else { -+ i++; /* skip ESC */ -+ if (!isdigit(uchar(news[i]))) -+ luaL_addchar(b, news[i]); -+ else if (news[i] == '0') -+ luaL_addlstring(b, s, e - s); -+ else { -+ push_onecapture(ms, news[i] - '1', s, e); -+ luaL_addvalue(b); /* add capture to accumulated result */ -+ } -+ } -+ } -+} -+ -+ -+static void add_value (MatchState *ms, luaL_Buffer *b, const char *s, -+ const char *e) { -+ lua_State *L = ms->L; -+ switch (lua_type(L, 3)) { -+ case LUA_TNUMBER: -+ case LUA_TSTRING: { -+ add_s(ms, b, s, e); -+ return; -+ } -+ case LUA_TFUNCTION: { -+ int n; -+ lua_pushvalue(L, 3); -+ n = push_captures(ms, s, e); -+ lua_call(L, n, 1); -+ break; -+ } -+ case LUA_TTABLE: { -+ push_onecapture(ms, 0, s, e); -+ lua_gettable(L, 3); -+ break; -+ } -+ } -+ if (!lua_toboolean(L, -1)) { /* nil or false? */ -+ lua_pop(L, 1); -+ lua_pushlstring(L, s, e - s); /* keep original text */ -+ } -+ else if (!lua_isstring(L, -1)) -+ luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1)); -+ luaL_addvalue(b); /* add result to accumulator */ -+} -+ -+ -+static int str_gsub (lua_State *L) { -+ size_t srcl; -+ const char *src = luaL_checklstring(L, 1, &srcl); -+ const char *p = luaL_checkstring(L, 2); -+ int tr = lua_type(L, 3); -+ int max_s = luaL_optint(L, 4, srcl+1); -+ int anchor = (*p == '^') ? (p++, 1) : 0; -+ int n = 0; -+ MatchState ms; -+ luaL_Buffer *b = (luaL_Buffer *)kmalloc(sizeof(luaL_Buffer) + BUFSIZ, GFP_ATOMIC); -+ if(!b) luaL_error(L, "str_gsub: cannot allocate memory"); -+ luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING || -+ tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3, -+ "string/function/table expected"); -+ luaL_buffinit(L, b); -+ ms.L = L; -+ ms.src_init = src; -+ ms.src_end = src+srcl; -+ while (n < max_s) { -+ const char *e; -+ ms.level = 0; -+ e = match(&ms, src, p); -+ if (e) { -+ n++; -+ add_value(&ms, b, src, e); -+ } -+ if (e && e>src) /* non empty match? */ -+ src = e; /* skip it */ -+ else if (src < ms.src_end) -+ luaL_addchar(b, *src++); -+ else break; -+ if (anchor) break; -+ } -+ luaL_addlstring(b, src, ms.src_end-src); -+ luaL_pushresult(b); -+ lua_pushinteger(L, n); /* number of substitutions */ -+ kfree(b); -+ return 2; -+} -+ -+/* }====================================================== */ -+ -+ -+/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */ -+#define MAX_ITEM 512 -+/* valid flags in a format specification */ -+#define FLAGS "-+ #0" -+/* -+** maximum size of each format specification (such as '%-099.99d') -+** (+10 accounts for %99.99x plus margin of error) -+*/ -+#define MAX_FORMAT (sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10) -+ -+ -+static void addquoted (lua_State *L, luaL_Buffer *b, int arg) { -+ size_t l; -+ const char *s = luaL_checklstring(L, arg, &l); -+ luaL_addchar(b, '"'); -+ while (l--) { -+ switch (*s) { -+ case '"': case '\\': case '\n': { -+ luaL_addchar(b, '\\'); -+ luaL_addchar(b, *s); -+ break; -+ } -+ case '\r': { -+ luaL_addlstring(b, "\\r", 2); -+ break; -+ } -+ case '\0': { -+ luaL_addlstring(b, "\\000", 4); -+ break; -+ } -+ default: { -+ luaL_addchar(b, *s); -+ break; -+ } -+ } -+ s++; -+ } -+ luaL_addchar(b, '"'); -+} -+ -+static const char *scanformat (lua_State *L, const char *strfrmt, char *form) { -+ const char *p = strfrmt; -+ while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */ -+ if ((size_t)(p - strfrmt) >= sizeof(FLAGS)) -+ luaL_error(L, "invalid format (repeated flags)"); -+ if (isdigit(uchar(*p))) p++; /* skip width */ -+ if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ -+ if (*p == '.') { -+ p++; -+ if (isdigit(uchar(*p))) p++; /* skip precision */ -+ if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ -+ } -+ if (isdigit(uchar(*p))) -+ luaL_error(L, "invalid format (width or precision too long)"); -+ *(form++) = '%'; -+ strncpy(form, strfrmt, p - strfrmt + 1); -+ form += p - strfrmt + 1; -+ *form = '\0'; -+ return p; -+} -+ -+ -+static void addintlen (char *form) { -+ size_t l = strlen(form); -+ char spec = form[l - 1]; -+ strcpy(form + l - 1, LUA_INTFRMLEN); -+ form[l + sizeof(LUA_INTFRMLEN) - 2] = spec; -+ form[l + sizeof(LUA_INTFRMLEN) - 1] = '\0'; -+} -+ -+ -+static int str_format (lua_State *L) { -+ int arg = 1; -+ size_t sfl; -+ const char *strfrmt = luaL_checklstring(L, arg, &sfl); -+ const char *strfrmt_end = strfrmt+sfl; -+ luaL_Buffer *b = (luaL_Buffer *)kmalloc(sizeof(luaL_Buffer) + BUFSIZ, GFP_ATOMIC); -+ if(!b) luaL_error(L, "str_format: cannot allocate memory"); -+ luaL_buffinit(L, b); -+ while (strfrmt < strfrmt_end) { -+ if (*strfrmt != L_ESC) -+ luaL_addchar(b, *strfrmt++); -+ else if (*++strfrmt == L_ESC) -+ luaL_addchar(b, *strfrmt++); /* %% */ -+ else { /* format item */ -+ char form[MAX_FORMAT]; /* to store the format (`%...') */ -+ char buff[MAX_ITEM]; /* to store the formatted item */ -+ arg++; -+ strfrmt = scanformat(L, strfrmt, form); -+ switch (*strfrmt++) { -+ case 'c': { -+ sprintf(buff, form, (int)luaL_checknumber(L, arg)); -+ break; -+ } -+ case 'd': case 'i': { -+ addintlen(form); -+ sprintf(buff, form, (LUA_INTFRM_T)luaL_checknumber(L, arg)); -+ break; -+ } -+ case 'o': case 'u': case 'x': case 'X': { -+ addintlen(form); -+ sprintf(buff, form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg)); -+ break; -+ } -+ case 'q': { -+ addquoted(L, b, arg); -+ continue; /* skip the 'addsize' at the end */ -+ } -+ case 's': { -+ size_t l; -+ const char *s = luaL_checklstring(L, arg, &l); -+ if (!strchr(form, '.') && l >= 100) { -+ /* no precision and string is too long to be formatted; -+ keep original string */ -+ lua_pushvalue(L, arg); -+ luaL_addvalue(b); -+ continue; /* skip the `addsize' at the end */ -+ } -+ else { -+ sprintf(buff, form, s); -+ break; -+ } -+ } -+ default: { /* also treat cases `pnLlh' */ -+ kfree(b); -+ return luaL_error(L, "invalid option " LUA_QL("%%%c") " to " -+ LUA_QL("format"), *(strfrmt - 1)); -+ } -+ } -+ luaL_addlstring(b, buff, strlen(buff)); -+ } -+ } -+ luaL_pushresult(b); -+ kfree(b); -+ return 1; -+} -+ -+ -+static const luaL_Reg strlib[] = { -+ {"byte", str_byte}, -+ {"char", str_char}, -+ {"dump", str_dump}, -+ {"find", str_find}, -+ {"format", str_format}, -+ {"gfind", gfind_nodef}, -+ {"gmatch", gmatch}, -+ {"gsub", str_gsub}, -+ {"len", str_len}, -+ {"lower", str_lower}, -+ {"match", str_match}, -+ {"rep", str_rep}, -+ {"reverse", str_reverse}, -+ {"sub", str_sub}, -+ {"upper", str_upper}, -+ {NULL, NULL} -+}; -+ -+ -+static void createmetatable (lua_State *L) { -+ lua_createtable(L, 0, 1); /* create metatable for strings */ -+ lua_pushliteral(L, ""); /* dummy string */ -+ lua_pushvalue(L, -2); -+ lua_setmetatable(L, -2); /* set string metatable */ -+ lua_pop(L, 1); /* pop dummy string */ -+ lua_pushvalue(L, -2); /* string library... */ -+ lua_setfield(L, -2, "__index"); /* ...is the __index metamethod */ -+ lua_pop(L, 1); /* pop metatable */ -+} -+ -+ -+/* -+** Open string library -+*/ -+LUALIB_API int luaopen_string (lua_State *L) { -+ luaL_register(L, LUA_STRLIBNAME, strlib); -+#if defined(LUA_COMPAT_GFIND) -+ lua_getfield(L, -1, "gmatch"); -+ lua_setfield(L, -2, "gfind"); -+#endif -+ createmetatable(L); -+ return 1; -+} ---- /dev/null -+++ b/extensions/LUA/lua/ltable.c -@@ -0,0 +1,588 @@ -+/* -+** $Id: ltable.c,v 2.32.1.2 2007/12/28 15:32:23 roberto Exp $ -+** Lua tables (hash) -+** See Copyright Notice in lua.h -+*/ -+ -+ -+/* -+** Implementation of tables (aka arrays, objects, or hash tables). -+** Tables keep its elements in two parts: an array part and a hash part. -+** Non-negative integer keys are all candidates to be kept in the array -+** part. The actual size of the array is the largest `n' such that at -+** least half the slots between 0 and n are in use. -+** Hash uses a mix of chained scatter table with Brent's variation. -+** A main invariant of these tables is that, if an element is not -+** in its main position (i.e. the `original' position that its hash gives -+** to it), then the colliding element is in its own main position. -+** Hence even when the load factor reaches 100%, performance remains good. -+*/ -+ -+#include -+#include -+ -+#define ltable_c -+#define LUA_CORE -+ -+#include "lua.h" -+ -+#include "ldebug.h" -+#include "ldo.h" -+#include "lgc.h" -+#include "lmem.h" -+#include "lobject.h" -+#include "lstate.h" -+#include "ltable.h" -+ -+ -+/* -+** max size of array part is 2^MAXBITS -+*/ -+#if LUAI_BITSINT > 26 -+#define MAXBITS 26 -+#else -+#define MAXBITS (LUAI_BITSINT-2) -+#endif -+ -+#define MAXASIZE (1 << MAXBITS) -+ -+ -+#define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t)))) -+ -+#define hashstr(t,str) hashpow2(t, (str)->tsv.hash) -+#define hashboolean(t,p) hashpow2(t, p) -+ -+ -+/* -+** for some types, it is better to avoid modulus by power of 2, as -+** they tend to have many 2 factors. -+*/ -+#define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1)))) -+ -+ -+#define hashpointer(t,p) hashmod(t, IntPoint(p)) -+ -+ -+/* -+** number of ints inside a lua_Number -+*/ -+#define numints cast_int(sizeof(lua_Number)/sizeof(int)) -+ -+ -+ -+#define dummynode (&dummynode_) -+ -+static const Node dummynode_ = { -+ {{NULL}, LUA_TNIL}, /* value */ -+ {{{NULL}, LUA_TNIL, NULL}} /* key */ -+}; -+ -+ -+/* -+** hash for lua_Numbers -+*/ -+static Node *hashnum (const Table *t, lua_Number n) { -+ unsigned int a[numints]; -+ int i; -+ if (luai_numeq(n, 0)) /* avoid problems with -0 */ -+ return gnode(t, 0); -+ memcpy(a, &n, sizeof(a)); -+ for (i = 1; i < numints; i++) a[0] += a[i]; -+ return hashmod(t, a[0]); -+} -+ -+ -+ -+/* -+** returns the `main' position of an element in a table (that is, the index -+** of its hash value) -+*/ -+static Node *mainposition (const Table *t, const TValue *key) { -+ switch (ttype(key)) { -+ case LUA_TNUMBER: -+ return hashnum(t, nvalue(key)); -+ case LUA_TSTRING: -+ return hashstr(t, rawtsvalue(key)); -+ case LUA_TBOOLEAN: -+ return hashboolean(t, bvalue(key)); -+ case LUA_TLIGHTUSERDATA: -+ return hashpointer(t, pvalue(key)); -+ default: -+ return hashpointer(t, gcvalue(key)); -+ } -+} -+ -+ -+/* -+** returns the index for `key' if `key' is an appropriate key to live in -+** the array part of the table, -1 otherwise. -+*/ -+static int arrayindex (const TValue *key) { -+ if (ttisnumber(key)) { -+ lua_Number n = nvalue(key); -+ int k; -+ lua_number2int(k, n); -+ if (luai_numeq(cast_num(k), n)) -+ return k; -+ } -+ return -1; /* `key' did not match some condition */ -+} -+ -+ -+/* -+** returns the index of a `key' for table traversals. First goes all -+** elements in the array part, then elements in the hash part. The -+** beginning of a traversal is signalled by -1. -+*/ -+static int findindex (lua_State *L, Table *t, StkId key) { -+ int i; -+ if (ttisnil(key)) return -1; /* first iteration */ -+ i = arrayindex(key); -+ if (0 < i && i <= t->sizearray) /* is `key' inside array part? */ -+ return i-1; /* yes; that's the index (corrected to C) */ -+ else { -+ Node *n = mainposition(t, key); -+ do { /* check whether `key' is somewhere in the chain */ -+ /* key may be dead already, but it is ok to use it in `next' */ -+ if (luaO_rawequalObj(key2tval(n), key) || -+ (ttype(gkey(n)) == LUA_TDEADKEY && iscollectable(key) && -+ gcvalue(gkey(n)) == gcvalue(key))) { -+ i = cast_int(n - gnode(t, 0)); /* key index in hash table */ -+ /* hash elements are numbered after array ones */ -+ return i + t->sizearray; -+ } -+ else n = gnext(n); -+ } while (n); -+ luaG_runerror(L, "invalid key to " LUA_QL("next")); /* key not found */ -+ return 0; /* to avoid warnings */ -+ } -+} -+ -+ -+int luaH_next (lua_State *L, Table *t, StkId key) { -+ int i = findindex(L, t, key); /* find original element */ -+ for (i++; i < t->sizearray; i++) { /* try first array part */ -+ if (!ttisnil(&t->array[i])) { /* a non-nil value? */ -+ setnvalue(key, cast_num(i+1)); -+ setobj2s(L, key+1, &t->array[i]); -+ return 1; -+ } -+ } -+ for (i -= t->sizearray; i < sizenode(t); i++) { /* then hash part */ -+ if (!ttisnil(gval(gnode(t, i)))) { /* a non-nil value? */ -+ setobj2s(L, key, key2tval(gnode(t, i))); -+ setobj2s(L, key+1, gval(gnode(t, i))); -+ return 1; -+ } -+ } -+ return 0; /* no more elements */ -+} -+ -+ -+/* -+** {============================================================= -+** Rehash -+** ============================================================== -+*/ -+ -+ -+static int computesizes (int nums[], int *narray) { -+ int i; -+ int twotoi; /* 2^i */ -+ int a = 0; /* number of elements smaller than 2^i */ -+ int na = 0; /* number of elements to go to array part */ -+ int n = 0; /* optimal size for array part */ -+ for (i = 0, twotoi = 1; twotoi/2 < *narray; i++, twotoi *= 2) { -+ if (nums[i] > 0) { -+ a += nums[i]; -+ if (a > twotoi/2) { /* more than half elements present? */ -+ n = twotoi; /* optimal size (till now) */ -+ na = a; /* all elements smaller than n will go to array part */ -+ } -+ } -+ if (a == *narray) break; /* all elements already counted */ -+ } -+ *narray = n; -+ lua_assert(*narray/2 <= na && na <= *narray); -+ return na; -+} -+ -+ -+static int countint (const TValue *key, int *nums) { -+ int k = arrayindex(key); -+ if (0 < k && k <= MAXASIZE) { /* is `key' an appropriate array index? */ -+ nums[ceillog2(k)]++; /* count as such */ -+ return 1; -+ } -+ else -+ return 0; -+} -+ -+ -+static int numusearray (const Table *t, int *nums) { -+ int lg; -+ int ttlg; /* 2^lg */ -+ int ause = 0; /* summation of `nums' */ -+ int i = 1; /* count to traverse all array keys */ -+ for (lg=0, ttlg=1; lg<=MAXBITS; lg++, ttlg*=2) { /* for each slice */ -+ int lc = 0; /* counter */ -+ int lim = ttlg; -+ if (lim > t->sizearray) { -+ lim = t->sizearray; /* adjust upper limit */ -+ if (i > lim) -+ break; /* no more elements to count */ -+ } -+ /* count elements in range (2^(lg-1), 2^lg] */ -+ for (; i <= lim; i++) { -+ if (!ttisnil(&t->array[i-1])) -+ lc++; -+ } -+ nums[lg] += lc; -+ ause += lc; -+ } -+ return ause; -+} -+ -+ -+static int numusehash (const Table *t, int *nums, int *pnasize) { -+ int totaluse = 0; /* total number of elements */ -+ int ause = 0; /* summation of `nums' */ -+ int i = sizenode(t); -+ while (i--) { -+ Node *n = &t->node[i]; -+ if (!ttisnil(gval(n))) { -+ ause += countint(key2tval(n), nums); -+ totaluse++; -+ } -+ } -+ *pnasize += ause; -+ return totaluse; -+} -+ -+ -+static void setarrayvector (lua_State *L, Table *t, int size) { -+ int i; -+ luaM_reallocvector(L, t->array, t->sizearray, size, TValue); -+ for (i=t->sizearray; iarray[i]); -+ t->sizearray = size; -+} -+ -+ -+static void setnodevector (lua_State *L, Table *t, int size) { -+ int lsize; -+ if (size == 0) { /* no elements to hash part? */ -+ t->node = cast(Node *, dummynode); /* use common `dummynode' */ -+ lsize = 0; -+ } -+ else { -+ int i; -+ lsize = ceillog2(size); -+ if (lsize > MAXBITS) -+ luaG_runerror(L, "table overflow"); -+ size = twoto(lsize); -+ t->node = luaM_newvector(L, size, Node); -+ for (i=0; ilsizenode = cast_byte(lsize); -+ t->lastfree = gnode(t, size); /* all positions are free */ -+} -+ -+ -+static void resize (lua_State *L, Table *t, int nasize, int nhsize) { -+ int i; -+ int oldasize = t->sizearray; -+ int oldhsize = t->lsizenode; -+ Node *nold = t->node; /* save old hash ... */ -+ if (nasize > oldasize) /* array part must grow? */ -+ setarrayvector(L, t, nasize); -+ /* create new hash part with appropriate size */ -+ setnodevector(L, t, nhsize); -+ if (nasize < oldasize) { /* array part must shrink? */ -+ t->sizearray = nasize; -+ /* re-insert elements from vanishing slice */ -+ for (i=nasize; iarray[i])) -+ setobjt2t(L, luaH_setnum(L, t, i+1), &t->array[i]); -+ } -+ /* shrink array */ -+ luaM_reallocvector(L, t->array, oldasize, nasize, TValue); -+ } -+ /* re-insert elements from hash part */ -+ for (i = twoto(oldhsize) - 1; i >= 0; i--) { -+ Node *old = nold+i; -+ if (!ttisnil(gval(old))) -+ setobjt2t(L, luaH_set(L, t, key2tval(old)), gval(old)); -+ } -+ if (nold != dummynode) -+ luaM_freearray(L, nold, twoto(oldhsize), Node); /* free old array */ -+} -+ -+ -+void luaH_resizearray (lua_State *L, Table *t, int nasize) { -+ int nsize = (t->node == dummynode) ? 0 : sizenode(t); -+ resize(L, t, nasize, nsize); -+} -+ -+ -+static void rehash (lua_State *L, Table *t, const TValue *ek) { -+ int nasize, na; -+ int nums[MAXBITS+1]; /* nums[i] = number of keys between 2^(i-1) and 2^i */ -+ int i; -+ int totaluse; -+ for (i=0; i<=MAXBITS; i++) nums[i] = 0; /* reset counts */ -+ nasize = numusearray(t, nums); /* count keys in array part */ -+ totaluse = nasize; /* all those keys are integer keys */ -+ totaluse += numusehash(t, nums, &nasize); /* count keys in hash part */ -+ /* count extra key */ -+ nasize += countint(ek, nums); -+ totaluse++; -+ /* compute new size for array part */ -+ na = computesizes(nums, &nasize); -+ /* resize the table to new computed sizes */ -+ resize(L, t, nasize, totaluse - na); -+} -+ -+ -+ -+/* -+** }============================================================= -+*/ -+ -+ -+Table *luaH_new (lua_State *L, int narray, int nhash) { -+ Table *t = luaM_new(L, Table); -+ luaC_link(L, obj2gco(t), LUA_TTABLE); -+ t->metatable = NULL; -+ t->flags = cast_byte(~0); -+ /* temporary values (kept only if some malloc fails) */ -+ t->array = NULL; -+ t->sizearray = 0; -+ t->lsizenode = 0; -+ t->node = cast(Node *, dummynode); -+ setarrayvector(L, t, narray); -+ setnodevector(L, t, nhash); -+ return t; -+} -+ -+ -+void luaH_free (lua_State *L, Table *t) { -+ if (t->node != dummynode) -+ luaM_freearray(L, t->node, sizenode(t), Node); -+ luaM_freearray(L, t->array, t->sizearray, TValue); -+ luaM_free(L, t); -+} -+ -+ -+static Node *getfreepos (Table *t) { -+ while (t->lastfree-- > t->node) { -+ if (ttisnil(gkey(t->lastfree))) -+ return t->lastfree; -+ } -+ return NULL; /* could not find a free place */ -+} -+ -+ -+ -+/* -+** inserts a new key into a hash table; first, check whether key's main -+** position is free. If not, check whether colliding node is in its main -+** position or not: if it is not, move colliding node to an empty place and -+** put new key in its main position; otherwise (colliding node is in its main -+** position), new key goes to an empty position. -+*/ -+static TValue *newkey (lua_State *L, Table *t, const TValue *key) { -+ Node *mp = mainposition(t, key); -+ if (!ttisnil(gval(mp)) || mp == dummynode) { -+ Node *othern; -+ Node *n = getfreepos(t); /* get a free place */ -+ if (n == NULL) { /* cannot find a free place? */ -+ rehash(L, t, key); /* grow table */ -+ return luaH_set(L, t, key); /* re-insert key into grown table */ -+ } -+ lua_assert(n != dummynode); -+ othern = mainposition(t, key2tval(mp)); -+ if (othern != mp) { /* is colliding node out of its main position? */ -+ /* yes; move colliding node into free position */ -+ while (gnext(othern) != mp) othern = gnext(othern); /* find previous */ -+ gnext(othern) = n; /* redo the chain with `n' in place of `mp' */ -+ *n = *mp; /* copy colliding node into free pos. (mp->next also goes) */ -+ gnext(mp) = NULL; /* now `mp' is free */ -+ setnilvalue(gval(mp)); -+ } -+ else { /* colliding node is in its own main position */ -+ /* new node will go into free position */ -+ gnext(n) = gnext(mp); /* chain new position */ -+ gnext(mp) = n; -+ mp = n; -+ } -+ } -+ gkey(mp)->value = key->value; gkey(mp)->tt = key->tt; -+ luaC_barriert(L, t, key); -+ lua_assert(ttisnil(gval(mp))); -+ return gval(mp); -+} -+ -+ -+/* -+** search function for integers -+*/ -+const TValue *luaH_getnum (Table *t, int key) { -+ /* (1 <= key && key <= t->sizearray) */ -+ if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray)) -+ return &t->array[key-1]; -+ else { -+ lua_Number nk = cast_num(key); -+ Node *n = hashnum(t, nk); -+ do { /* check whether `key' is somewhere in the chain */ -+ if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk)) -+ return gval(n); /* that's it */ -+ else n = gnext(n); -+ } while (n); -+ return luaO_nilobject; -+ } -+} -+ -+ -+/* -+** search function for strings -+*/ -+const TValue *luaH_getstr (Table *t, TString *key) { -+ Node *n = hashstr(t, key); -+ do { /* check whether `key' is somewhere in the chain */ -+ if (ttisstring(gkey(n)) && rawtsvalue(gkey(n)) == key) -+ return gval(n); /* that's it */ -+ else n = gnext(n); -+ } while (n); -+ return luaO_nilobject; -+} -+ -+ -+/* -+** main search function -+*/ -+const TValue *luaH_get (Table *t, const TValue *key) { -+ switch (ttype(key)) { -+ case LUA_TNIL: return luaO_nilobject; -+ case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key)); -+ case LUA_TNUMBER: { -+ int k; -+ lua_Number n = nvalue(key); -+ lua_number2int(k, n); -+ if (luai_numeq(cast_num(k), nvalue(key))) /* index is int? */ -+ return luaH_getnum(t, k); /* use specialized version */ -+ /* else go through */ -+ } -+ default: { -+ Node *n = mainposition(t, key); -+ do { /* check whether `key' is somewhere in the chain */ -+ if (luaO_rawequalObj(key2tval(n), key)) -+ return gval(n); /* that's it */ -+ else n = gnext(n); -+ } while (n); -+ return luaO_nilobject; -+ } -+ } -+} -+ -+ -+TValue *luaH_set (lua_State *L, Table *t, const TValue *key) { -+ const TValue *p = luaH_get(t, key); -+ t->flags = 0; -+ if (p != luaO_nilobject) -+ return cast(TValue *, p); -+ else { -+ if (ttisnil(key)) luaG_runerror(L, "table index is nil"); -+ else if (ttisnumber(key) && luai_numisnan(nvalue(key))) -+ luaG_runerror(L, "table index is NaN"); -+ return newkey(L, t, key); -+ } -+} -+ -+ -+TValue *luaH_setnum (lua_State *L, Table *t, int key) { -+ const TValue *p = luaH_getnum(t, key); -+ if (p != luaO_nilobject) -+ return cast(TValue *, p); -+ else { -+ TValue k; -+ setnvalue(&k, cast_num(key)); -+ return newkey(L, t, &k); -+ } -+} -+ -+ -+TValue *luaH_setstr (lua_State *L, Table *t, TString *key) { -+ const TValue *p = luaH_getstr(t, key); -+ if (p != luaO_nilobject) -+ return cast(TValue *, p); -+ else { -+ TValue k; -+ setsvalue(L, &k, key); -+ return newkey(L, t, &k); -+ } -+} -+ -+ -+static int unbound_search (Table *t, unsigned int j) { -+ unsigned int i = j; /* i is zero or a present index */ -+ j++; -+ /* find `i' and `j' such that i is present and j is not */ -+ while (!ttisnil(luaH_getnum(t, j))) { -+ i = j; -+ j *= 2; -+ if (j > cast(unsigned int, MAX_INT)) { /* overflow? */ -+ /* table was built with bad purposes: resort to linear search */ -+ i = 1; -+ while (!ttisnil(luaH_getnum(t, i))) i++; -+ return i - 1; -+ } -+ } -+ /* now do a binary search between them */ -+ while (j - i > 1) { -+ unsigned int m = (i+j)/2; -+ if (ttisnil(luaH_getnum(t, m))) j = m; -+ else i = m; -+ } -+ return i; -+} -+ -+ -+/* -+** Try to find a boundary in table `t'. A `boundary' is an integer index -+** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil). -+*/ -+int luaH_getn (Table *t) { -+ unsigned int j = t->sizearray; -+ if (j > 0 && ttisnil(&t->array[j - 1])) { -+ /* there is a boundary in the array part: (binary) search for it */ -+ unsigned int i = 0; -+ while (j - i > 1) { -+ unsigned int m = (i+j)/2; -+ if (ttisnil(&t->array[m - 1])) j = m; -+ else i = m; -+ } -+ return i; -+ } -+ /* else must find a boundary in hash part */ -+ else if (t->node == dummynode) /* hash part is empty? */ -+ return j; /* that is easy... */ -+ else return unbound_search(t, j); -+} -+ -+ -+ -+#if defined(LUA_DEBUG) -+ -+Node *luaH_mainposition (const Table *t, const TValue *key) { -+ return mainposition(t, key); -+} -+ -+int luaH_isdummy (Node *n) { return n == dummynode; } -+ -+#endif ---- /dev/null -+++ b/extensions/LUA/lua/ltable.h -@@ -0,0 +1,40 @@ -+/* -+** $Id: ltable.h,v 2.10.1.1 2007/12/27 13:02:25 roberto Exp $ -+** Lua tables (hash) -+** See Copyright Notice in lua.h -+*/ -+ -+#ifndef ltable_h -+#define ltable_h -+ -+#include "lobject.h" -+ -+ -+#define gnode(t,i) (&(t)->node[i]) -+#define gkey(n) (&(n)->i_key.nk) -+#define gval(n) (&(n)->i_val) -+#define gnext(n) ((n)->i_key.nk.next) -+ -+#define key2tval(n) (&(n)->i_key.tvk) -+ -+ -+LUAI_FUNC const TValue *luaH_getnum (Table *t, int key); -+LUAI_FUNC TValue *luaH_setnum (lua_State *L, Table *t, int key); -+LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key); -+LUAI_FUNC TValue *luaH_setstr (lua_State *L, Table *t, TString *key); -+LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key); -+LUAI_FUNC TValue *luaH_set (lua_State *L, Table *t, const TValue *key); -+LUAI_FUNC Table *luaH_new (lua_State *L, int narray, int lnhash); -+LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, int nasize); -+LUAI_FUNC void luaH_free (lua_State *L, Table *t); -+LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key); -+LUAI_FUNC int luaH_getn (Table *t); -+ -+ -+#if defined(LUA_DEBUG) -+LUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key); -+LUAI_FUNC int luaH_isdummy (Node *n); -+#endif -+ -+ -+#endif ---- /dev/null -+++ b/extensions/LUA/lua/ltablib.c -@@ -0,0 +1,288 @@ -+/* -+** $Id: ltablib.c,v 1.38.1.3 2008/02/14 16:46:58 roberto Exp $ -+** Library for Table Manipulation -+** See Copyright Notice in lua.h -+*/ -+ -+ -+#include -+ -+#define ltablib_c -+#define LUA_LIB -+ -+#include "lua.h" -+ -+#include "lauxlib.h" -+#include "lualib.h" -+ -+ -+#define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_getn(L, n)) -+ -+ -+static int foreachi (lua_State *L) { -+ int i; -+ int n = aux_getn(L, 1); -+ luaL_checktype(L, 2, LUA_TFUNCTION); -+ for (i=1; i <= n; i++) { -+ lua_pushvalue(L, 2); /* function */ -+ lua_pushinteger(L, i); /* 1st argument */ -+ lua_rawgeti(L, 1, i); /* 2nd argument */ -+ lua_call(L, 2, 1); -+ if (!lua_isnil(L, -1)) -+ return 1; -+ lua_pop(L, 1); /* remove nil result */ -+ } -+ return 0; -+} -+ -+ -+static int foreach (lua_State *L) { -+ luaL_checktype(L, 1, LUA_TTABLE); -+ luaL_checktype(L, 2, LUA_TFUNCTION); -+ lua_pushnil(L); /* first key */ -+ while (lua_next(L, 1)) { -+ lua_pushvalue(L, 2); /* function */ -+ lua_pushvalue(L, -3); /* key */ -+ lua_pushvalue(L, -3); /* value */ -+ lua_call(L, 2, 1); -+ if (!lua_isnil(L, -1)) -+ return 1; -+ lua_pop(L, 2); /* remove value and result */ -+ } -+ return 0; -+} -+ -+ -+static int maxn (lua_State *L) { -+ lua_Number max = 0; -+ luaL_checktype(L, 1, LUA_TTABLE); -+ lua_pushnil(L); /* first key */ -+ while (lua_next(L, 1)) { -+ lua_pop(L, 1); /* remove value */ -+ if (lua_type(L, -1) == LUA_TNUMBER) { -+ lua_Number v = lua_tonumber(L, -1); -+ if (v > max) max = v; -+ } -+ } -+ lua_pushnumber(L, max); -+ return 1; -+} -+ -+ -+static int getn (lua_State *L) { -+ lua_pushinteger(L, aux_getn(L, 1)); -+ return 1; -+} -+ -+ -+static int setn (lua_State *L) { -+ luaL_checktype(L, 1, LUA_TTABLE); -+#ifndef luaL_setn -+ luaL_setn(L, 1, luaL_checkint(L, 2)); -+#else -+ luaL_error(L, LUA_QL("setn") " is obsolete"); -+#endif -+ lua_pushvalue(L, 1); -+ return 1; -+} -+ -+ -+static int tinsert (lua_State *L) { -+ int e = aux_getn(L, 1) + 1; /* first empty element */ -+ int pos; /* where to insert new element */ -+ switch (lua_gettop(L)) { -+ case 2: { /* called with only 2 arguments */ -+ pos = e; /* insert new element at the end */ -+ break; -+ } -+ case 3: { -+ int i; -+ pos = luaL_checkint(L, 2); /* 2nd argument is the position */ -+ if (pos > e) e = pos; /* `grow' array if necessary */ -+ for (i = e; i > pos; i--) { /* move up elements */ -+ lua_rawgeti(L, 1, i-1); -+ lua_rawseti(L, 1, i); /* t[i] = t[i-1] */ -+ } -+ break; -+ } -+ default: { -+ return luaL_error(L, "wrong number of arguments to " LUA_QL("insert")); -+ } -+ } -+ luaL_setn(L, 1, e); /* new size */ -+ lua_rawseti(L, 1, pos); /* t[pos] = v */ -+ return 0; -+} -+ -+ -+static int tremove (lua_State *L) { -+ int e = aux_getn(L, 1); -+ int pos = luaL_optint(L, 2, e); -+ if (!(1 <= pos && pos <= e)) /* position is outside bounds? */ -+ return 0; /* nothing to remove */ -+ luaL_setn(L, 1, e - 1); /* t.n = n-1 */ -+ lua_rawgeti(L, 1, pos); /* result = t[pos] */ -+ for ( ;pos= P */ -+ while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) { -+ if (i>u) luaL_error(L, "invalid order function for sorting"); -+ lua_pop(L, 1); /* remove a[i] */ -+ } -+ /* repeat --j until a[j] <= P */ -+ while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) { -+ if (j -+ -+#define ltm_c -+#define LUA_CORE -+ -+#include "lua.h" -+ -+#include "lobject.h" -+#include "lstate.h" -+#include "lstring.h" -+#include "ltable.h" -+#include "ltm.h" -+ -+ -+ -+const char *const luaT_typenames[] = { -+ "nil", "boolean", "userdata", "number", -+ "string", "table", "function", "userdata", "thread", -+ "proto", "upval" -+}; -+ -+ -+void luaT_init (lua_State *L) { -+ static const char *const luaT_eventname[] = { /* ORDER TM */ -+ "__index", "__newindex", -+ "__gc", "__mode", "__eq", -+ "__add", "__sub", "__mul", "__div", "__mod", -+ "__pow", "__unm", "__len", "__lt", "__le", -+ "__concat", "__call" -+ }; -+ int i; -+ for (i=0; itmname[i] = luaS_new(L, luaT_eventname[i]); -+ luaS_fix(G(L)->tmname[i]); /* never collect these names */ -+ } -+} -+ -+ -+/* -+** function to be used with macro "fasttm": optimized for absence of -+** tag methods -+*/ -+const TValue *luaT_gettm (Table *events, TMS event, TString *ename) { -+ const TValue *tm = luaH_getstr(events, ename); -+ lua_assert(event <= TM_EQ); -+ if (ttisnil(tm)) { /* no tag method? */ -+ events->flags |= cast_byte(1u<metatable; -+ break; -+ case LUA_TUSERDATA: -+ mt = uvalue(o)->metatable; -+ break; -+ default: -+ mt = G(L)->mt[ttype(o)]; -+ } -+ return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject); -+} -+ ---- /dev/null -+++ b/extensions/LUA/lua/ltm.h -@@ -0,0 +1,54 @@ -+/* -+** $Id: ltm.h,v 2.6.1.1 2007/12/27 13:02:25 roberto Exp $ -+** Tag methods -+** See Copyright Notice in lua.h -+*/ -+ -+#ifndef ltm_h -+#define ltm_h -+ -+ -+#include "lobject.h" -+ -+ -+/* -+* WARNING: if you change the order of this enumeration, -+* grep "ORDER TM" -+*/ -+typedef enum { -+ TM_INDEX, -+ TM_NEWINDEX, -+ TM_GC, -+ TM_MODE, -+ TM_EQ, /* last tag method with `fast' access */ -+ TM_ADD, -+ TM_SUB, -+ TM_MUL, -+ TM_DIV, -+ TM_MOD, -+ TM_POW, -+ TM_UNM, -+ TM_LEN, -+ TM_LT, -+ TM_LE, -+ TM_CONCAT, -+ TM_CALL, -+ TM_N /* number of elements in the enum */ -+} TMS; -+ -+ -+ -+#define gfasttm(g,et,e) ((et) == NULL ? NULL : \ -+ ((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e])) -+ -+#define fasttm(l,et,e) gfasttm(G(l), et, e) -+ -+LUAI_DATA const char *const luaT_typenames[]; -+ -+ -+LUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename); -+LUAI_FUNC const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, -+ TMS event); -+LUAI_FUNC void luaT_init (lua_State *L); -+ -+#endif ---- /dev/null -+++ b/extensions/LUA/lua/luaconf.h -@@ -0,0 +1,797 @@ -+/* -+** $Id: luaconf.h,v 1.82.1.7 2008/02/11 16:25:08 roberto Exp $ -+** Configuration file for Lua -+** See Copyright Notice in lua.h -+*/ -+ -+ -+#ifndef lconfig_h -+#define lconfig_h -+ -+#include -+ -+#if !defined(__KERNEL__) -+#include -+#else -+#define UCHAR_MAX 255 -+#define SHRT_MAX 32767 -+#define BUFSIZ 8192 -+#define NO_FPU -+#endif -+ -+/* -+** ================================================================== -+** Search for "@@" to find all configurable definitions. -+** =================================================================== -+*/ -+ -+ -+/* -+@@ LUA_ANSI controls the use of non-ansi features. -+** CHANGE it (define it) if you want Lua to avoid the use of any -+** non-ansi feature or library. -+*/ -+#if defined(__STRICT_ANSI__) -+#define LUA_ANSI -+#endif -+ -+ -+#if !defined(LUA_ANSI) && defined(_WIN32) -+#define LUA_WIN -+#endif -+ -+#if defined(LUA_USE_LINUX) -+#define LUA_USE_POSIX -+#define LUA_USE_DLOPEN /* needs an extra library: -ldl */ -+#define LUA_USE_READLINE /* needs some extra libraries */ -+#endif -+ -+#if defined(LUA_USE_MACOSX) -+#define LUA_USE_POSIX -+#define LUA_DL_DYLD /* does not need extra library */ -+#endif -+ -+ -+ -+/* -+@@ LUA_USE_POSIX includes all functionallity listed as X/Open System -+@* Interfaces Extension (XSI). -+** CHANGE it (define it) if your system is XSI compatible. -+*/ -+#if defined(LUA_USE_POSIX) -+#define LUA_USE_MKSTEMP -+#define LUA_USE_ISATTY -+#define LUA_USE_POPEN -+#define LUA_USE_ULONGJMP -+#endif -+ -+ -+/* -+@@ LUA_PATH and LUA_CPATH are the names of the environment variables that -+@* Lua check to set its paths. -+@@ LUA_INIT is the name of the environment variable that Lua -+@* checks for initialization code. -+** CHANGE them if you want different names. -+*/ -+#define LUA_PATH "LUA_PATH" -+#define LUA_CPATH "LUA_CPATH" -+#define LUA_INIT "LUA_INIT" -+ -+ -+/* -+@@ LUA_PATH_DEFAULT is the default path that Lua uses to look for -+@* Lua libraries. -+@@ LUA_CPATH_DEFAULT is the default path that Lua uses to look for -+@* C libraries. -+** CHANGE them if your machine has a non-conventional directory -+** hierarchy or if you want to install your libraries in -+** non-conventional directories. -+*/ -+#if defined(_WIN32) -+/* -+** In Windows, any exclamation mark ('!') in the path is replaced by the -+** path of the directory of the executable file of the current process. -+*/ -+#define LUA_LDIR "!\\lua\\" -+#define LUA_CDIR "!\\" -+#define LUA_PATH_DEFAULT \ -+ ".\\?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \ -+ LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua" -+#define LUA_CPATH_DEFAULT \ -+ ".\\?.dll;" LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll" -+ -+#else -+#define LUA_ROOT "/usr/local/" -+#define LUA_LDIR LUA_ROOT "share/lua/5.1/" -+#define LUA_CDIR LUA_ROOT "lib/lua/5.1/" -+#define LUA_PATH_DEFAULT \ -+ "./?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \ -+ LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua" -+#define LUA_CPATH_DEFAULT \ -+ "./?.so;" LUA_CDIR"?.so;" LUA_CDIR"loadall.so" -+#endif -+ -+ -+/* -+@@ LUA_DIRSEP is the directory separator (for submodules). -+** CHANGE it if your machine does not use "/" as the directory separator -+** and is not Windows. (On Windows Lua automatically uses "\".) -+*/ -+#if defined(_WIN32) -+#define LUA_DIRSEP "\\" -+#else -+#define LUA_DIRSEP "/" -+#endif -+ -+ -+/* -+@@ LUA_PATHSEP is the character that separates templates in a path. -+@@ LUA_PATH_MARK is the string that marks the substitution points in a -+@* template. -+@@ LUA_EXECDIR in a Windows path is replaced by the executable's -+@* directory. -+@@ LUA_IGMARK is a mark to ignore all before it when bulding the -+@* luaopen_ function name. -+** CHANGE them if for some reason your system cannot use those -+** characters. (E.g., if one of those characters is a common character -+** in file/directory names.) Probably you do not need to change them. -+*/ -+#define LUA_PATHSEP ";" -+#define LUA_PATH_MARK "?" -+#define LUA_EXECDIR "!" -+#define LUA_IGMARK "-" -+ -+ -+/* -+@@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger. -+** CHANGE that if ptrdiff_t is not adequate on your machine. (On most -+** machines, ptrdiff_t gives a good choice between int or long.) -+*/ -+#define LUA_INTEGER ptrdiff_t -+ -+ -+/* -+@@ LUA_API is a mark for all core API functions. -+@@ LUALIB_API is a mark for all standard library functions. -+** CHANGE them if you need to define those functions in some special way. -+** For instance, if you want to create one Windows DLL with the core and -+** the libraries, you may want to use the following definition (define -+** LUA_BUILD_AS_DLL to get it). -+*/ -+#if defined(LUA_BUILD_AS_DLL) -+ -+#if defined(LUA_CORE) || defined(LUA_LIB) -+#define LUA_API __declspec(dllexport) -+#else -+#define LUA_API __declspec(dllimport) -+#endif -+ -+#else -+ -+#define LUA_API extern -+ -+#endif -+ -+/* more often than not the libs go together with the core */ -+#define LUALIB_API LUA_API -+ -+ -+/* -+@@ LUAI_FUNC is a mark for all extern functions that are not to be -+@* exported to outside modules. -+@@ LUAI_DATA is a mark for all extern (const) variables that are not to -+@* be exported to outside modules. -+** CHANGE them if you need to mark them in some special way. Elf/gcc -+** (versions 3.2 and later) mark them as "hidden" to optimize access -+** when Lua is compiled as a shared library. -+*/ -+#if defined(luaall_c) -+#define LUAI_FUNC static -+#define LUAI_DATA /* empty */ -+ -+#elif defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \ -+ defined(__ELF__) -+#define LUAI_FUNC __attribute__((visibility("hidden"))) extern -+#define LUAI_DATA LUAI_FUNC -+ -+#else -+#define LUAI_FUNC extern -+#define LUAI_DATA extern -+#endif -+ -+ -+ -+/* -+@@ LUA_QL describes how error messages quote program elements. -+** CHANGE it if you want a different appearance. -+*/ -+#define LUA_QL(x) "'" x "'" -+#define LUA_QS LUA_QL("%s") -+ -+ -+/* -+@@ LUA_IDSIZE gives the maximum size for the description of the source -+@* of a function in debug information. -+** CHANGE it if you want a different size. -+*/ -+#define LUA_IDSIZE 60 -+ -+ -+/* -+** {================================================================== -+** Stand-alone configuration -+** =================================================================== -+*/ -+ -+#if defined(lua_c) || defined(luaall_c) -+ -+/* -+@@ lua_stdin_is_tty detects whether the standard input is a 'tty' (that -+@* is, whether we're running lua interactively). -+** CHANGE it if you have a better definition for non-POSIX/non-Windows -+** systems. -+*/ -+#if defined(LUA_USE_ISATTY) -+#include -+#define lua_stdin_is_tty() isatty(0) -+#elif defined(LUA_WIN) -+#include -+#include -+#define lua_stdin_is_tty() _isatty(_fileno(stdin)) -+#else -+#define lua_stdin_is_tty() 1 /* assume stdin is a tty */ -+#endif -+ -+ -+/* -+@@ LUA_PROMPT is the default prompt used by stand-alone Lua. -+@@ LUA_PROMPT2 is the default continuation prompt used by stand-alone Lua. -+** CHANGE them if you want different prompts. (You can also change the -+** prompts dynamically, assigning to globals _PROMPT/_PROMPT2.) -+*/ -+#define LUA_PROMPT "> " -+#define LUA_PROMPT2 ">> " -+ -+ -+/* -+@@ LUA_PROGNAME is the default name for the stand-alone Lua program. -+** CHANGE it if your stand-alone interpreter has a different name and -+** your system is not able to detect that name automatically. -+*/ -+#define LUA_PROGNAME "lua" -+ -+ -+/* -+@@ LUA_MAXINPUT is the maximum length for an input line in the -+@* stand-alone interpreter. -+** CHANGE it if you need longer lines. -+*/ -+#define LUA_MAXINPUT 512 -+ -+ -+/* -+@@ lua_readline defines how to show a prompt and then read a line from -+@* the standard input. -+@@ lua_saveline defines how to "save" a read line in a "history". -+@@ lua_freeline defines how to free a line read by lua_readline. -+** CHANGE them if you want to improve this functionality (e.g., by using -+** GNU readline and history facilities). -+*/ -+#if defined(LUA_USE_READLINE) -+#include -+#include -+#include -+#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL) -+#define lua_saveline(L,idx) \ -+ if (lua_strlen(L,idx) > 0) /* non-empty line? */ \ -+ add_history(lua_tostring(L, idx)); /* add it to history */ -+#define lua_freeline(L,b) ((void)L, free(b)) -+#else -+#define lua_readline(L,b,p) \ -+ ((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \ -+ fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */ -+#define lua_saveline(L,idx) { (void)L; (void)idx; } -+#define lua_freeline(L,b) { (void)L; (void)b; } -+#endif -+ -+#endif -+ -+/* }================================================================== */ -+ -+ -+/* -+@@ LUAI_GCPAUSE defines the default pause between garbage-collector cycles -+@* as a percentage. -+** CHANGE it if you want the GC to run faster or slower (higher values -+** mean larger pauses which mean slower collection.) You can also change -+** this value dynamically. -+*/ -+#define LUAI_GCPAUSE 200 /* 200% (wait memory to double before next GC) */ -+ -+ -+/* -+@@ LUAI_GCMUL defines the default speed of garbage collection relative to -+@* memory allocation as a percentage. -+** CHANGE it if you want to change the granularity of the garbage -+** collection. (Higher values mean coarser collections. 0 represents -+** infinity, where each step performs a full collection.) You can also -+** change this value dynamically. -+*/ -+#define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */ -+ -+ -+ -+/* -+@@ LUA_COMPAT_GETN controls compatibility with old getn behavior. -+** CHANGE it (define it) if you want exact compatibility with the -+** behavior of setn/getn in Lua 5.0. -+*/ -+#undef LUA_COMPAT_GETN -+ -+/* -+@@ LUA_COMPAT_LOADLIB controls compatibility about global loadlib. -+** CHANGE it to undefined as soon as you do not need a global 'loadlib' -+** function (the function is still available as 'package.loadlib'). -+*/ -+#undef LUA_COMPAT_LOADLIB -+ -+/* -+@@ LUA_COMPAT_VARARG controls compatibility with old vararg feature. -+** CHANGE it to undefined as soon as your programs use only '...' to -+** access vararg parameters (instead of the old 'arg' table). -+*/ -+#define LUA_COMPAT_VARARG -+ -+/* -+@@ LUA_COMPAT_MOD controls compatibility with old math.mod function. -+** CHANGE it to undefined as soon as your programs use 'math.fmod' or -+** the new '%' operator instead of 'math.mod'. -+*/ -+#define LUA_COMPAT_MOD -+ -+/* -+@@ LUA_COMPAT_LSTR controls compatibility with old long string nesting -+@* facility. -+** CHANGE it to 2 if you want the old behaviour, or undefine it to turn -+** off the advisory error when nesting [[...]]. -+*/ -+#define LUA_COMPAT_LSTR 1 -+ -+/* -+@@ LUA_COMPAT_GFIND controls compatibility with old 'string.gfind' name. -+** CHANGE it to undefined as soon as you rename 'string.gfind' to -+** 'string.gmatch'. -+*/ -+#define LUA_COMPAT_GFIND -+ -+/* -+@@ LUA_COMPAT_OPENLIB controls compatibility with old 'luaL_openlib' -+@* behavior. -+** CHANGE it to undefined as soon as you replace to 'luaL_register' -+** your uses of 'luaL_openlib' -+*/ -+#define LUA_COMPAT_OPENLIB -+ -+ -+ -+/* -+@@ luai_apicheck is the assert macro used by the Lua-C API. -+** CHANGE luai_apicheck if you want Lua to perform some checks in the -+** parameters it gets from API calls. This may slow down the interpreter -+** a bit, but may be quite useful when debugging C code that interfaces -+** with Lua. A useful redefinition is to use assert.h. -+*/ -+#if defined(LUA_USE_APICHECK) -+#include -+#define luai_apicheck(L,o) { (void)L; assert(o); } -+#else -+#define luai_apicheck(L,o) { (void)L; } -+#endif -+ -+ -+/* -+@@ LUAI_BITSINT defines the number of bits in an int. -+** CHANGE here if Lua cannot automatically detect the number of bits of -+** your machine. Probably you do not need to change this. -+*/ -+/* avoid overflows in comparison */ -+#if !defined(__KERNEL__) -+#include -+#define LUA_INT_MAX INT_MAX -+#else -+#define LUA_INT_MAX (~0U>>1) -+#endif -+ -+#if LUA_INT_MAX-20 < 32760 -+#define LUAI_BITSINT 16 -+#elif LUA_INT_MAX > 2147483640L -+/* int has at least 32 bits */ -+#define LUAI_BITSINT 32 -+#else -+#error "you must define LUA_BITSINT with number of bits in an integer" -+#endif -+ -+ -+/* -+@@ LUAI_UINT32 is an unsigned integer with at least 32 bits. -+@@ LUAI_INT32 is an signed integer with at least 32 bits. -+@@ LUAI_UMEM is an unsigned integer big enough to count the total -+@* memory used by Lua. -+@@ LUAI_MEM is a signed integer big enough to count the total memory -+@* used by Lua. -+** CHANGE here if for some weird reason the default definitions are not -+** good enough for your machine. (The definitions in the 'else' -+** part always works, but may waste space on machines with 64-bit -+** longs.) Probably you do not need to change this. -+*/ -+#if LUAI_BITSINT >= 32 -+#define LUAI_UINT32 unsigned int -+#define LUAI_INT32 int -+#define LUAI_MAXINT32 INT_MAX -+#define LUAI_UMEM size_t -+#define LUAI_MEM ptrdiff_t -+#else -+/* 16-bit ints */ -+#define LUAI_UINT32 unsigned long -+#define LUAI_INT32 long -+#define LUAI_MAXINT32 LONG_MAX -+#define LUAI_UMEM unsigned long -+#define LUAI_MEM long -+#endif -+ -+ -+/* -+@@ LUAI_MAXCALLS limits the number of nested calls. -+** CHANGE it if you need really deep recursive calls. This limit is -+** arbitrary; its only purpose is to stop infinite recursion before -+** exhausting memory. -+*/ -+#define LUAI_MAXCALLS 20000 -+ -+ -+/* -+@@ LUAI_MAXCSTACK limits the number of Lua stack slots that a C function -+@* can use. -+** CHANGE it if you need lots of (Lua) stack space for your C -+** functions. This limit is arbitrary; its only purpose is to stop C -+** functions to consume unlimited stack space. (must be smaller than -+** -LUA_REGISTRYINDEX) -+*/ -+#define LUAI_MAXCSTACK 8000 -+ -+ -+ -+/* -+** {================================================================== -+** CHANGE (to smaller values) the following definitions if your system -+** has a small C stack. (Or you may want to change them to larger -+** values if your system has a large C stack and these limits are -+** too rigid for you.) Some of these constants control the size of -+** stack-allocated arrays used by the compiler or the interpreter, while -+** others limit the maximum number of recursive calls that the compiler -+** or the interpreter can perform. Values too large may cause a C stack -+** overflow for some forms of deep constructs. -+** =================================================================== -+*/ -+ -+ -+/* -+@@ LUAI_MAXCCALLS is the maximum depth for nested C calls (short) and -+@* syntactical nested non-terminals in a program. -+*/ -+#define LUAI_MAXCCALLS 200 -+ -+ -+/* -+@@ LUAI_MAXVARS is the maximum number of local variables per function -+@* (must be smaller than 250). -+*/ -+#define LUAI_MAXVARS 200 -+ -+ -+/* -+@@ LUAI_MAXUPVALUES is the maximum number of upvalues per function -+@* (must be smaller than 250). -+*/ -+#define LUAI_MAXUPVALUES 60 -+ -+ -+/* -+@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system. -+*/ -+#define LUAL_BUFFERSIZE BUFSIZ -+ -+/* }================================================================== */ -+ -+ -+ -+ -+/* -+** {================================================================== -+@@ LUA_NUMBER is the type of numbers in Lua. -+** CHANGE the following definitions only if you want to build Lua -+** with a number type different from double. You may also need to -+** change lua_number2int & lua_number2integer. -+** =================================================================== -+*/ -+#if !defined(NO_FPU) -+#define LUA_NUMBER_DOUBLE -+#define LUA_NUMBER double -+#else -+#define LUA_NUMBER long -+#endif -+ -+/* -+@@ LUAI_UACNUMBER is the result of an 'usual argument conversion' -+@* over a number. -+*/ -+#define LUAI_UACNUMBER LUA_NUMBER -+ -+ -+/* -+@@ LUA_NUMBER_SCAN is the format for reading numbers. -+@@ LUA_NUMBER_FMT is the format for writing numbers. -+@@ lua_number2str converts a number to a string. -+@@ LUAI_MAXNUMBER2STR is maximum size of previous conversion. -+@@ lua_str2number converts a string to a number. -+*/ -+#if !defined(NO_FPU) -+#define LUA_NUMBER_SCAN "%lf" -+#define LUA_NUMBER_FMT "%.14g" -+#define lua_str2number(s,p) strtod((s), (p)) -+#else -+#define LUA_NUMBER_SCAN "%ld" -+#define LUA_NUMBER_FMT "%ld" -+#if !defined(__KERNEL__) -+#define lua_str2number(s,p) strtol((s), (p), 10) -+#else -+#define lua_str2number(s,p) simple_strtol((s), (p), 10) -+#endif -+#endif -+ -+#define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */ -+#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n)) -+ -+/* -+@@ The luai_num* macros define the primitive operations over numbers. -+*/ -+#if defined(LUA_CORE) -+#define luai_numadd(a,b) ((a)+(b)) -+#define luai_numsub(a,b) ((a)-(b)) -+#define luai_nummul(a,b) ((a)*(b)) -+#define luai_numdiv(a,b) ((a)/(b)) -+#define luai_numunm(a) (-(a)) -+#define luai_numeq(a,b) ((a)==(b)) -+#define luai_numlt(a,b) ((a)<(b)) -+#define luai_numle(a,b) ((a)<=(b)) -+#define luai_numisnan(a) (!luai_numeq((a), (a))) -+#if !defined(NO_FPU) -+#include -+#define luai_nummod(a,b) ((a) - floor((a)/(b))*(b)) -+#define luai_numpow(a,b) (pow(a,b)) -+#else -+#define luai_nummod(a,b) ((a)%(b)) -+#define luai_numpow(a,b) luai_nummul(a,b) -+#endif -+#endif -+ -+ -+/* -+@@ lua_number2int is a macro to convert lua_Number to int. -+@@ lua_number2integer is a macro to convert lua_Number to lua_Integer. -+** CHANGE them if you know a faster way to convert a lua_Number to -+** int (with any rounding method and without throwing errors) in your -+** system. In Pentium machines, a naive typecast from double to int -+** in C is extremely slow, so any alternative is worth trying. -+*/ -+ -+/* On a Pentium, resort to a trick */ -+#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && \ -+ (defined(__i386) || defined (_M_IX86) || defined(__i386__)) -+ -+/* On a Microsoft compiler, use assembler */ -+#if defined(_MSC_VER) -+ -+#define lua_number2int(i,d) __asm fld d __asm fistp i -+#define lua_number2integer(i,n) lua_number2int(i, n) -+ -+/* the next trick should work on any Pentium, but sometimes clashes -+ with a DirectX idiosyncrasy */ -+#else -+ -+union luai_Cast { double l_d; long l_l; }; -+#define lua_number2int(i,d) \ -+ { volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; } -+#define lua_number2integer(i,n) lua_number2int(i, n) -+ -+#endif -+ -+ -+/* this option always works, but may be slow */ -+#else -+#define lua_number2int(i,d) ((i)=(int)(d)) -+#define lua_number2integer(i,d) ((i)=(lua_Integer)(d)) -+ -+#endif -+ -+/* }================================================================== */ -+ -+ -+/* -+@@ LUAI_USER_ALIGNMENT_T is a type that requires maximum alignment. -+** CHANGE it if your system requires alignments larger than double. (For -+** instance, if your system supports long doubles and they must be -+** aligned in 16-byte boundaries, then you should add long double in the -+** union.) Probably you do not need to change this. -+*/ -+#define LUAI_USER_ALIGNMENT_T union { double u; void *s; long l; } -+ -+ -+/* -+@@ LUAI_THROW/LUAI_TRY define how Lua does exception handling. -+** CHANGE them if you prefer to use longjmp/setjmp even with C++ -+** or if want/don't to use _longjmp/_setjmp instead of regular -+** longjmp/setjmp. By default, Lua handles errors with exceptions when -+** compiling as C++ code, with _longjmp/_setjmp when asked to use them, -+** and with longjmp/setjmp otherwise. -+*/ -+#if defined(__KERNEL__) -+#undef LUA_USE_ULONGJMP -+#endif -+ -+#if defined(__cplusplus) -+/* C++ exceptions */ -+#define LUAI_THROW(L,c) throw(c) -+#define LUAI_TRY(L,c,a) try { a } catch(...) \ -+ { if ((c)->status == 0) (c)->status = -1; } -+#define luai_jmpbuf int /* dummy variable */ -+ -+#elif defined(LUA_USE_ULONGJMP) -+/* in Unix, try _longjmp/_setjmp (more efficient) */ -+#define LUAI_THROW(L,c) _longjmp((c)->b, 1) -+#define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a } -+#define luai_jmpbuf jmp_buf -+ -+#else -+/* default handling with long jumps */ -+#define LUAI_THROW(L,c) longjmp((c)->b, 1) -+#define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a } -+#define luai_jmpbuf jmp_buf -+ -+#endif -+ -+ -+/* -+@@ LUA_MAXCAPTURES is the maximum number of captures that a pattern -+@* can do during pattern-matching. -+** CHANGE it if you need more captures. This limit is arbitrary. -+*/ -+#define LUA_MAXCAPTURES 32 -+ -+ -+/* -+@@ lua_tmpnam is the function that the OS library uses to create a -+@* temporary name. -+@@ LUA_TMPNAMBUFSIZE is the maximum size of a name created by lua_tmpnam. -+** CHANGE them if you have an alternative to tmpnam (which is considered -+** insecure) or if you want the original tmpnam anyway. By default, Lua -+** uses tmpnam except when POSIX is available, where it uses mkstemp. -+*/ -+#if defined(loslib_c) || defined(luaall_c) -+ -+#if defined(LUA_USE_MKSTEMP) -+#include -+#define LUA_TMPNAMBUFSIZE 32 -+#define lua_tmpnam(b,e) { \ -+ strcpy(b, "/tmp/lua_XXXXXX"); \ -+ e = mkstemp(b); \ -+ if (e != -1) close(e); \ -+ e = (e == -1); } -+ -+#else -+#define LUA_TMPNAMBUFSIZE L_tmpnam -+#define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); } -+#endif -+ -+#endif -+ -+ -+/* -+@@ lua_popen spawns a new process connected to the current one through -+@* the file streams. -+** CHANGE it if you have a way to implement it in your system. -+*/ -+#if defined(LUA_USE_POPEN) -+ -+#define lua_popen(L,c,m) ((void)L, fflush(NULL), popen(c,m)) -+#define lua_pclose(L,file) ((void)L, (pclose(file) != -1)) -+ -+#elif defined(LUA_WIN) -+ -+#define lua_popen(L,c,m) ((void)L, _popen(c,m)) -+#define lua_pclose(L,file) ((void)L, (_pclose(file) != -1)) -+ -+#else -+ -+#define lua_popen(L,c,m) ((void)((void)c, m), \ -+ luaL_error(L, LUA_QL("popen") " not supported"), (FILE*)0) -+#define lua_pclose(L,file) ((void)((void)L, file), 0) -+ -+#endif -+ -+/* -+@@ LUA_DL_* define which dynamic-library system Lua should use. -+** CHANGE here if Lua has problems choosing the appropriate -+** dynamic-library system for your platform (either Windows' DLL, Mac's -+** dyld, or Unix's dlopen). If your system is some kind of Unix, there -+** is a good chance that it has dlopen, so LUA_DL_DLOPEN will work for -+** it. To use dlopen you also need to adapt the src/Makefile (probably -+** adding -ldl to the linker options), so Lua does not select it -+** automatically. (When you change the makefile to add -ldl, you must -+** also add -DLUA_USE_DLOPEN.) -+** If you do not want any kind of dynamic library, undefine all these -+** options. -+** By default, _WIN32 gets LUA_DL_DLL and MAC OS X gets LUA_DL_DYLD. -+*/ -+#if defined(LUA_USE_DLOPEN) -+#define LUA_DL_DLOPEN -+#endif -+ -+#if defined(LUA_WIN) -+#define LUA_DL_DLL -+#endif -+ -+ -+/* -+@@ LUAI_EXTRASPACE allows you to add user-specific data in a lua_State -+@* (the data goes just *before* the lua_State pointer). -+** CHANGE (define) this if you really need that. This value must be -+** a multiple of the maximum alignment required for your machine. -+*/ -+#define LUAI_EXTRASPACE 0 -+ -+ -+/* -+@@ luai_userstate* allow user-specific actions on threads. -+** CHANGE them if you defined LUAI_EXTRASPACE and need to do something -+** extra when a thread is created/deleted/resumed/yielded. -+*/ -+#define luai_userstateopen(L) ((void)L) -+#define luai_userstateclose(L) ((void)L) -+#define luai_userstatethread(L,L1) ((void)L) -+#define luai_userstatefree(L) ((void)L) -+#define luai_userstateresume(L,n) ((void)L) -+#define luai_userstateyield(L,n) ((void)L) -+ -+ -+/* -+@@ LUA_INTFRMLEN is the length modifier for integer conversions -+@* in 'string.format'. -+@@ LUA_INTFRM_T is the integer type correspoding to the previous length -+@* modifier. -+** CHANGE them if your system supports long long or does not support long. -+*/ -+ -+#if defined(LUA_USELONGLONG) -+ -+#define LUA_INTFRMLEN "ll" -+#define LUA_INTFRM_T long long -+ -+#else -+ -+#define LUA_INTFRMLEN "l" -+#define LUA_INTFRM_T long -+ -+#endif -+ -+/* =================================================================== */ -+ -+/* -+** Local configuration. You can use this space to add your redefinitions -+** without modifying the main part of the file. -+*/ -+ -+ -+ -+#endif -+ ---- /dev/null -+++ b/extensions/LUA/lua/lua.h -@@ -0,0 +1,387 @@ -+/* -+** $Id: lua.h,v 1.218.1.5 2008/08/06 13:30:12 roberto Exp $ -+** Lua - An Extensible Extension Language -+** Lua.org, PUC-Rio, Brazil (http://www.lua.org) -+** See Copyright Notice at the end of this file -+*/ -+ -+ -+#ifndef lua_h -+#define lua_h -+ -+#include -+#include -+ -+#include "luaconf.h" -+ -+ -+#define LUA_VERSION "Lua 5.1" -+#define LUA_RELEASE "Lua 5.1.4" -+#define LUA_VERSION_NUM 501 -+#define LUA_COPYRIGHT "Copyright (C) 1994-2008 Lua.org, PUC-Rio" -+#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes" -+ -+ -+/* mark for precompiled code (`Lua') */ -+#define LUA_SIGNATURE "\033Lua" -+ -+/* option for multiple returns in `lua_pcall' and `lua_call' */ -+#define LUA_MULTRET (-1) -+ -+ -+/* -+** pseudo-indices -+*/ -+#define LUA_REGISTRYINDEX (-10000) -+#define LUA_ENVIRONINDEX (-10001) -+#define LUA_GLOBALSINDEX (-10002) -+#define lua_upvalueindex(i) (LUA_GLOBALSINDEX-(i)) -+ -+ -+/* thread status; 0 is OK */ -+#define LUA_YIELD 1 -+#define LUA_ERRRUN 2 -+#define LUA_ERRSYNTAX 3 -+#define LUA_ERRMEM 4 -+#define LUA_ERRERR 5 -+ -+ -+typedef struct lua_State lua_State; -+ -+typedef int (*lua_CFunction) (lua_State *L); -+ -+ -+/* -+** functions that read/write blocks when loading/dumping Lua chunks -+*/ -+typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz); -+ -+typedef int (*lua_Writer) (lua_State *L, const void* p, size_t sz, void* ud); -+ -+ -+/* -+** prototype for memory-allocation functions -+*/ -+typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); -+ -+ -+/* -+** basic types -+*/ -+#define LUA_TNONE (-1) -+ -+#define LUA_TNIL 0 -+#define LUA_TBOOLEAN 1 -+#define LUA_TLIGHTUSERDATA 2 -+#define LUA_TNUMBER 3 -+#define LUA_TSTRING 4 -+#define LUA_TTABLE 5 -+#define LUA_TFUNCTION 6 -+#define LUA_TUSERDATA 7 -+#define LUA_TTHREAD 8 -+ -+ -+ -+/* minimum Lua stack available to a C function */ -+#define LUA_MINSTACK 20 -+ -+ -+/* -+** generic extra include file -+*/ -+#if defined(LUA_USER_H) -+#include LUA_USER_H -+#endif -+ -+ -+/* type of numbers in Lua */ -+typedef LUA_NUMBER lua_Number; -+ -+ -+/* type for integer functions */ -+typedef LUA_INTEGER lua_Integer; -+ -+ -+ -+/* -+** state manipulation -+*/ -+LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud); -+LUA_API void (lua_close) (lua_State *L); -+LUA_API lua_State *(lua_newthread) (lua_State *L); -+ -+LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf); -+ -+ -+/* -+** basic stack manipulation -+*/ -+LUA_API int (lua_gettop) (lua_State *L); -+LUA_API void (lua_settop) (lua_State *L, int idx); -+LUA_API void (lua_pushvalue) (lua_State *L, int idx); -+LUA_API void (lua_remove) (lua_State *L, int idx); -+LUA_API void (lua_insert) (lua_State *L, int idx); -+LUA_API void (lua_replace) (lua_State *L, int idx); -+LUA_API int (lua_checkstack) (lua_State *L, int sz); -+ -+LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n); -+ -+ -+/* -+** access functions (stack -> C) -+*/ -+ -+LUA_API int (lua_isnumber) (lua_State *L, int idx); -+LUA_API int (lua_isstring) (lua_State *L, int idx); -+LUA_API int (lua_iscfunction) (lua_State *L, int idx); -+LUA_API int (lua_isuserdata) (lua_State *L, int idx); -+LUA_API int (lua_type) (lua_State *L, int idx); -+LUA_API const char *(lua_typename) (lua_State *L, int tp); -+ -+LUA_API int (lua_equal) (lua_State *L, int idx1, int idx2); -+LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2); -+LUA_API int (lua_lessthan) (lua_State *L, int idx1, int idx2); -+ -+LUA_API lua_Number (lua_tonumber) (lua_State *L, int idx); -+LUA_API lua_Integer (lua_tointeger) (lua_State *L, int idx); -+LUA_API int (lua_toboolean) (lua_State *L, int idx); -+LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len); -+LUA_API size_t (lua_objlen) (lua_State *L, int idx); -+LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx); -+LUA_API void *(lua_touserdata) (lua_State *L, int idx); -+LUA_API lua_State *(lua_tothread) (lua_State *L, int idx); -+LUA_API const void *(lua_topointer) (lua_State *L, int idx); -+ -+ -+/* -+** push functions (C -> stack) -+*/ -+LUA_API void (lua_pushnil) (lua_State *L); -+LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n); -+LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n); -+LUA_API void (lua_pushlstring) (lua_State *L, const char *s, size_t l); -+LUA_API void (lua_pushstring) (lua_State *L, const char *s); -+LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt, -+ va_list argp); -+LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...); -+LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n); -+LUA_API void (lua_pushboolean) (lua_State *L, int b); -+LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p); -+LUA_API int (lua_pushthread) (lua_State *L); -+ -+ -+/* -+** get functions (Lua -> stack) -+*/ -+LUA_API void (lua_gettable) (lua_State *L, int idx); -+LUA_API void (lua_getfield) (lua_State *L, int idx, const char *k); -+LUA_API void (lua_rawget) (lua_State *L, int idx); -+LUA_API void (lua_rawgeti) (lua_State *L, int idx, int n); -+LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec); -+LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz); -+LUA_API int (lua_getmetatable) (lua_State *L, int objindex); -+LUA_API void (lua_getfenv) (lua_State *L, int idx); -+ -+ -+/* -+** set functions (stack -> Lua) -+*/ -+LUA_API void (lua_settable) (lua_State *L, int idx); -+LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k); -+LUA_API void (lua_rawset) (lua_State *L, int idx); -+LUA_API void (lua_rawseti) (lua_State *L, int idx, int n); -+LUA_API int (lua_setmetatable) (lua_State *L, int objindex); -+LUA_API int (lua_setfenv) (lua_State *L, int idx); -+ -+ -+/* -+** `load' and `call' functions (load and run Lua code) -+*/ -+LUA_API void (lua_call) (lua_State *L, int nargs, int nresults); -+LUA_API int (lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc); -+LUA_API int (lua_cpcall) (lua_State *L, lua_CFunction func, void *ud); -+LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt, -+ const char *chunkname); -+ -+LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data); -+ -+ -+/* -+** coroutine functions -+*/ -+LUA_API int (lua_yield) (lua_State *L, int nresults); -+LUA_API int (lua_resume) (lua_State *L, int narg); -+LUA_API int (lua_status) (lua_State *L); -+ -+/* -+** garbage-collection function and options -+*/ -+ -+#define LUA_GCSTOP 0 -+#define LUA_GCRESTART 1 -+#define LUA_GCCOLLECT 2 -+#define LUA_GCCOUNT 3 -+#define LUA_GCCOUNTB 4 -+#define LUA_GCSTEP 5 -+#define LUA_GCSETPAUSE 6 -+#define LUA_GCSETSTEPMUL 7 -+ -+LUA_API int (lua_gc) (lua_State *L, int what, int data); -+ -+ -+/* -+** miscellaneous functions -+*/ -+ -+LUA_API int (lua_error) (lua_State *L); -+ -+LUA_API int (lua_next) (lua_State *L, int idx); -+ -+LUA_API void (lua_concat) (lua_State *L, int n); -+ -+LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud); -+LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud); -+ -+ -+ -+/* -+** =============================================================== -+** some useful macros -+** =============================================================== -+*/ -+ -+#define lua_pop(L,n) lua_settop(L, -(n)-1) -+ -+#define lua_newtable(L) lua_createtable(L, 0, 0) -+ -+#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n))) -+ -+#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0) -+ -+#define lua_strlen(L,i) lua_objlen(L, (i)) -+ -+#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION) -+#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE) -+#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA) -+#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL) -+#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN) -+#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD) -+#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE) -+#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0) -+ -+#define lua_pushliteral(L, s) \ -+ lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1) -+ -+#define lua_setglobal(L,s) lua_setfield(L, LUA_GLOBALSINDEX, (s)) -+#define lua_getglobal(L,s) lua_getfield(L, LUA_GLOBALSINDEX, (s)) -+ -+#define lua_tostring(L,i) lua_tolstring(L, (i), NULL) -+ -+ -+ -+/* -+** compatibility macros and functions -+*/ -+ -+#define lua_open() luaL_newstate() -+ -+#define lua_getregistry(L) lua_pushvalue(L, LUA_REGISTRYINDEX) -+ -+#define lua_getgccount(L) lua_gc(L, LUA_GCCOUNT, 0) -+ -+#define lua_Chunkreader lua_Reader -+#define lua_Chunkwriter lua_Writer -+ -+ -+/* hack */ -+LUA_API void lua_setlevel (lua_State *from, lua_State *to); -+ -+ -+/* -+** {====================================================================== -+** Debug API -+** ======================================================================= -+*/ -+ -+ -+/* -+** Event codes -+*/ -+#define LUA_HOOKCALL 0 -+#define LUA_HOOKRET 1 -+#define LUA_HOOKLINE 2 -+#define LUA_HOOKCOUNT 3 -+#define LUA_HOOKTAILRET 4 -+ -+ -+/* -+** Event masks -+*/ -+#define LUA_MASKCALL (1 << LUA_HOOKCALL) -+#define LUA_MASKRET (1 << LUA_HOOKRET) -+#define LUA_MASKLINE (1 << LUA_HOOKLINE) -+#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT) -+ -+typedef struct lua_Debug lua_Debug; /* activation record */ -+ -+ -+/* Functions to be called by the debuger in specific events */ -+typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); -+ -+ -+LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar); -+LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar); -+LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n); -+LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n); -+LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n); -+LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n); -+ -+LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count); -+LUA_API lua_Hook lua_gethook (lua_State *L); -+LUA_API int lua_gethookmask (lua_State *L); -+LUA_API int lua_gethookcount (lua_State *L); -+ -+ -+struct lua_Debug { -+ int event; -+ const char *name; /* (n) */ -+ const char *namewhat; /* (n) `global', `local', `field', `method' */ -+ const char *what; /* (S) `Lua', `C', `main', `tail' */ -+ const char *source; /* (S) */ -+ int currentline; /* (l) */ -+ int nups; /* (u) number of upvalues */ -+ int linedefined; /* (S) */ -+ int lastlinedefined; /* (S) */ -+ char short_src[LUA_IDSIZE]; /* (S) */ -+ /* private part */ -+ int i_ci; /* active function */ -+}; -+ -+/* }====================================================================== */ -+ -+ -+/****************************************************************************** -+* Copyright (C) 1994-2008 Lua.org, PUC-Rio. All rights reserved. -+* -+* Permission is hereby granted, free of charge, to any person obtaining -+* a copy of this software and associated documentation files (the -+* "Software"), to deal in the Software without restriction, including -+* without limitation the rights to use, copy, modify, merge, publish, -+* distribute, sublicense, and/or sell copies of the Software, and to -+* permit persons to whom the Software is furnished to do so, subject to -+* the following conditions: -+* -+* The above copyright notice and this permission notice shall be -+* included in all copies or substantial portions of the Software. -+* -+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -+* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -+* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -+* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -+* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -+******************************************************************************/ -+ -+ -+#endif ---- /dev/null -+++ b/extensions/LUA/lua/lualib.h -@@ -0,0 +1,55 @@ -+/* -+** $Id: lualib.h,v 1.36.1.1 2007/12/27 13:02:25 roberto Exp $ -+** Lua standard libraries -+** See Copyright Notice in lua.h -+*/ -+ -+ -+#ifndef lualib_h -+#define lualib_h -+ -+#include "lua.h" -+ -+ -+/* Key to file-handle type */ -+#define LUA_FILEHANDLE "FILE*" -+ -+ -+#define LUA_COLIBNAME "coroutine" -+LUALIB_API int (luaopen_base) (lua_State *L); -+ -+#define LUA_TABLIBNAME "table" -+LUALIB_API int (luaopen_table) (lua_State *L); -+/* -+#define LUA_IOLIBNAME "io" -+LUALIB_API int (luaopen_io) (lua_State *L); -+ -+#define LUA_OSLIBNAME "os" -+LUALIB_API int (luaopen_os) (lua_State *L); -+*/ -+ -+#define LUA_STRLIBNAME "string" -+LUALIB_API int (luaopen_string) (lua_State *L); -+ -+/* -+#define LUA_MATHLIBNAME "math" -+LUALIB_API int (luaopen_math) (lua_State *L); -+ -+#define LUA_DBLIBNAME "debug" -+LUALIB_API int (luaopen_debug) (lua_State *L); -+ -+#define LUA_LOADLIBNAME "package" -+LUALIB_API int (luaopen_package) (lua_State *L); -+*/ -+ -+/* open all previous libraries */ -+LUALIB_API void (luaL_openlibs) (lua_State *L); -+ -+ -+ -+#ifndef lua_assert -+#define lua_assert(x) ((void)0) -+#endif -+ -+ -+#endif ---- /dev/null -+++ b/extensions/LUA/lua/lundump.c -@@ -0,0 +1,227 @@ -+/* -+** $Id: lundump.c,v 2.7.1.4 2008/04/04 19:51:41 roberto Exp $ -+** load precompiled Lua chunks -+** See Copyright Notice in lua.h -+*/ -+ -+#include -+ -+#define lundump_c -+#define LUA_CORE -+ -+#include "lua.h" -+ -+#include "ldebug.h" -+#include "ldo.h" -+#include "lfunc.h" -+#include "lmem.h" -+#include "lobject.h" -+#include "lstring.h" -+#include "lundump.h" -+#include "lzio.h" -+ -+typedef struct { -+ lua_State* L; -+ ZIO* Z; -+ Mbuffer* b; -+ const char* name; -+} LoadState; -+ -+#ifdef LUAC_TRUST_BINARIES -+#define IF(c,s) -+#define error(S,s) -+#else -+#define IF(c,s) if (c) error(S,s) -+ -+static void error(LoadState* S, const char* why) -+{ -+ luaO_pushfstring(S->L,"%s: %s in precompiled chunk",S->name,why); -+ luaD_throw(S->L,LUA_ERRSYNTAX); -+} -+#endif -+ -+#define LoadMem(S,b,n,size) LoadBlock(S,b,(n)*(size)) -+#define LoadByte(S) (lu_byte)LoadChar(S) -+#define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x)) -+#define LoadVector(S,b,n,size) LoadMem(S,b,n,size) -+ -+static void LoadBlock(LoadState* S, void* b, size_t size) -+{ -+ size_t r=luaZ_read(S->Z,b,size); -+ IF (r!=0, "unexpected end"); -+} -+ -+static int LoadChar(LoadState* S) -+{ -+ char x; -+ LoadVar(S,x); -+ return x; -+} -+ -+static int LoadInt(LoadState* S) -+{ -+ int x; -+ LoadVar(S,x); -+ IF (x<0, "bad integer"); -+ return x; -+} -+ -+static lua_Number LoadNumber(LoadState* S) -+{ -+ lua_Number x; -+ LoadVar(S,x); -+ return x; -+} -+ -+static TString* LoadString(LoadState* S) -+{ -+ size_t size; -+ LoadVar(S,size); -+ if (size==0) -+ return NULL; -+ else -+ { -+ char* s=luaZ_openspace(S->L,S->b,size); -+ LoadBlock(S,s,size); -+ return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */ -+ } -+} -+ -+static void LoadCode(LoadState* S, Proto* f) -+{ -+ int n=LoadInt(S); -+ f->code=luaM_newvector(S->L,n,Instruction); -+ f->sizecode=n; -+ LoadVector(S,f->code,n,sizeof(Instruction)); -+} -+ -+static Proto* LoadFunction(LoadState* S, TString* p); -+ -+static void LoadConstants(LoadState* S, Proto* f) -+{ -+ int i,n; -+ n=LoadInt(S); -+ f->k=luaM_newvector(S->L,n,TValue); -+ f->sizek=n; -+ for (i=0; ik[i]); -+ for (i=0; ik[i]; -+ int t=LoadChar(S); -+ switch (t) -+ { -+ case LUA_TNIL: -+ setnilvalue(o); -+ break; -+ case LUA_TBOOLEAN: -+ setbvalue(o,LoadChar(S)!=0); -+ break; -+ case LUA_TNUMBER: -+ setnvalue(o,LoadNumber(S)); -+ break; -+ case LUA_TSTRING: -+ setsvalue2n(S->L,o,LoadString(S)); -+ break; -+ default: -+ error(S,"bad constant"); -+ break; -+ } -+ } -+ n=LoadInt(S); -+ f->p=luaM_newvector(S->L,n,Proto*); -+ f->sizep=n; -+ for (i=0; ip[i]=NULL; -+ for (i=0; ip[i]=LoadFunction(S,f->source); -+} -+ -+static void LoadDebug(LoadState* S, Proto* f) -+{ -+ int i,n; -+ n=LoadInt(S); -+ f->lineinfo=luaM_newvector(S->L,n,int); -+ f->sizelineinfo=n; -+ LoadVector(S,f->lineinfo,n,sizeof(int)); -+ n=LoadInt(S); -+ f->locvars=luaM_newvector(S->L,n,LocVar); -+ f->sizelocvars=n; -+ for (i=0; ilocvars[i].varname=NULL; -+ for (i=0; ilocvars[i].varname=LoadString(S); -+ f->locvars[i].startpc=LoadInt(S); -+ f->locvars[i].endpc=LoadInt(S); -+ } -+ n=LoadInt(S); -+ f->upvalues=luaM_newvector(S->L,n,TString*); -+ f->sizeupvalues=n; -+ for (i=0; iupvalues[i]=NULL; -+ for (i=0; iupvalues[i]=LoadString(S); -+} -+ -+static Proto* LoadFunction(LoadState* S, TString* p) -+{ -+ Proto* f; -+ if (++S->L->nCcalls > LUAI_MAXCCALLS) error(S,"code too deep"); -+ f=luaF_newproto(S->L); -+ setptvalue2s(S->L,S->L->top,f); incr_top(S->L); -+ f->source=LoadString(S); if (f->source==NULL) f->source=p; -+ f->linedefined=LoadInt(S); -+ f->lastlinedefined=LoadInt(S); -+ f->nups=LoadByte(S); -+ f->numparams=LoadByte(S); -+ f->is_vararg=LoadByte(S); -+ f->maxstacksize=LoadByte(S); -+ LoadCode(S,f); -+ LoadConstants(S,f); -+ LoadDebug(S,f); -+ IF (!luaG_checkcode(f), "bad code"); -+ S->L->top--; -+ S->L->nCcalls--; -+ return f; -+} -+ -+static void LoadHeader(LoadState* S) -+{ -+ char h[LUAC_HEADERSIZE]; -+ char s[LUAC_HEADERSIZE]; -+ luaU_header(h); -+ LoadBlock(S,s,LUAC_HEADERSIZE); -+ IF (memcmp(h,s,LUAC_HEADERSIZE)!=0, "bad header"); -+} -+ -+/* -+** load precompiled chunk -+*/ -+Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name) -+{ -+ LoadState S; -+ if (*name=='@' || *name=='=') -+ S.name=name+1; -+ else if (*name==LUA_SIGNATURE[0]) -+ S.name="binary string"; -+ else -+ S.name=name; -+ S.L=L; -+ S.Z=Z; -+ S.b=buff; -+ LoadHeader(&S); -+ return LoadFunction(&S,luaS_newliteral(L,"=?")); -+} -+ -+/* -+* make header -+*/ -+void luaU_header (char* h) -+{ -+ int x=1; -+ memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-1); -+ h+=sizeof(LUA_SIGNATURE)-1; -+ *h++=(char)LUAC_VERSION; -+ *h++=(char)LUAC_FORMAT; -+ *h++=(char)*(char*)&x; /* endianness */ -+ *h++=(char)sizeof(int); -+ *h++=(char)sizeof(size_t); -+ *h++=(char)sizeof(Instruction); -+ *h++=(char)sizeof(lua_Number); -+ *h++=(char)(((lua_Number)0.5)==0); /* is lua_Number integral? */ -+} ---- /dev/null -+++ b/extensions/LUA/lua/lundump.h -@@ -0,0 +1,36 @@ -+/* -+** $Id: lundump.h,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $ -+** load precompiled Lua chunks -+** See Copyright Notice in lua.h -+*/ -+ -+#ifndef lundump_h -+#define lundump_h -+ -+#include "lobject.h" -+#include "lzio.h" -+ -+/* load one chunk; from lundump.c */ -+LUAI_FUNC Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name); -+ -+/* make header; from lundump.c */ -+LUAI_FUNC void luaU_header (char* h); -+ -+/* dump one chunk; from ldump.c */ -+LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip); -+ -+#ifdef luac_c -+/* print one chunk; from print.c */ -+LUAI_FUNC void luaU_print (const Proto* f, int full); -+#endif -+ -+/* for header of binary files -- this is Lua 5.1 */ -+#define LUAC_VERSION 0x51 -+ -+/* for header of binary files -- this is the official format */ -+#define LUAC_FORMAT 0 -+ -+/* size of header of binary files */ -+#define LUAC_HEADERSIZE 12 -+ -+#endif ---- /dev/null -+++ b/extensions/LUA/lua/lvm.c -@@ -0,0 +1,762 @@ -+/* -+** $Id: lvm.c,v 2.63.1.3 2007/12/28 15:32:23 roberto Exp $ -+** Lua virtual machine -+** See Copyright Notice in lua.h -+*/ -+ -+#include -+#include -+#include -+ -+#define lvm_c -+#define LUA_CORE -+ -+#include "lua.h" -+ -+#include "ldebug.h" -+#include "ldo.h" -+#include "lfunc.h" -+#include "lgc.h" -+#include "lobject.h" -+#include "lopcodes.h" -+#include "lstate.h" -+#include "lstring.h" -+#include "ltable.h" -+#include "ltm.h" -+#include "lvm.h" -+ -+ -+ -+/* limit for table tag-method chains (to avoid loops) */ -+#define MAXTAGLOOP 100 -+ -+ -+const TValue *luaV_tonumber (const TValue *obj, TValue *n) { -+ lua_Number num; -+ if (ttisnumber(obj)) return obj; -+ if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) { -+ setnvalue(n, num); -+ return n; -+ } -+ else -+ return NULL; -+} -+ -+ -+int luaV_tostring (lua_State *L, StkId obj) { -+ if (!ttisnumber(obj)) -+ return 0; -+ else { -+ char s[LUAI_MAXNUMBER2STR]; -+ lua_Number n = nvalue(obj); -+ lua_number2str(s, n); -+ setsvalue2s(L, obj, luaS_new(L, s)); -+ return 1; -+ } -+} -+ -+ -+static void traceexec (lua_State *L, const Instruction *pc) { -+ lu_byte mask = L->hookmask; -+ const Instruction *oldpc = L->savedpc; -+ L->savedpc = pc; -+ if ((mask & LUA_MASKCOUNT) && L->hookcount == 0) { -+ resethookcount(L); -+ luaD_callhook(L, LUA_HOOKCOUNT, -1); -+ } -+ if (mask & LUA_MASKLINE) { -+ Proto *p = ci_func(L->ci)->l.p; -+ int npc = pcRel(pc, p); -+ int newline = getline(p, npc); -+ /* call linehook when enter a new function, when jump back (loop), -+ or when enter a new line */ -+ if (npc == 0 || pc <= oldpc || newline != getline(p, pcRel(oldpc, p))) -+ luaD_callhook(L, LUA_HOOKLINE, newline); -+ } -+} -+ -+ -+static void callTMres (lua_State *L, StkId res, const TValue *f, -+ const TValue *p1, const TValue *p2) { -+ ptrdiff_t result = savestack(L, res); -+ setobj2s(L, L->top, f); /* push function */ -+ setobj2s(L, L->top+1, p1); /* 1st argument */ -+ setobj2s(L, L->top+2, p2); /* 2nd argument */ -+ luaD_checkstack(L, 3); -+ L->top += 3; -+ luaD_call(L, L->top - 3, 1); -+ res = restorestack(L, result); -+ L->top--; -+ setobjs2s(L, res, L->top); -+} -+ -+ -+ -+static void callTM (lua_State *L, const TValue *f, const TValue *p1, -+ const TValue *p2, const TValue *p3) { -+ setobj2s(L, L->top, f); /* push function */ -+ setobj2s(L, L->top+1, p1); /* 1st argument */ -+ setobj2s(L, L->top+2, p2); /* 2nd argument */ -+ setobj2s(L, L->top+3, p3); /* 3th argument */ -+ luaD_checkstack(L, 4); -+ L->top += 4; -+ luaD_call(L, L->top - 4, 0); -+} -+ -+ -+void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { -+ int loop; -+ for (loop = 0; loop < MAXTAGLOOP; loop++) { -+ const TValue *tm; -+ if (ttistable(t)) { /* `t' is a table? */ -+ Table *h = hvalue(t); -+ const TValue *res = luaH_get(h, key); /* do a primitive get */ -+ if (!ttisnil(res) || /* result is no nil? */ -+ (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */ -+ setobj2s(L, val, res); -+ return; -+ } -+ /* else will try the tag method */ -+ } -+ else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) -+ luaG_typeerror(L, t, "index"); -+ if (ttisfunction(tm)) { -+ callTMres(L, val, tm, t, key); -+ return; -+ } -+ t = tm; /* else repeat with `tm' */ -+ } -+ luaG_runerror(L, "loop in gettable"); -+} -+ -+ -+void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { -+ int loop; -+ for (loop = 0; loop < MAXTAGLOOP; loop++) { -+ const TValue *tm; -+ if (ttistable(t)) { /* `t' is a table? */ -+ Table *h = hvalue(t); -+ TValue *oldval = luaH_set(L, h, key); /* do a primitive set */ -+ if (!ttisnil(oldval) || /* result is no nil? */ -+ (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */ -+ setobj2t(L, oldval, val); -+ luaC_barriert(L, h, val); -+ return; -+ } -+ /* else will try the tag method */ -+ } -+ else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) -+ luaG_typeerror(L, t, "index"); -+ if (ttisfunction(tm)) { -+ callTM(L, tm, t, key, val); -+ return; -+ } -+ t = tm; /* else repeat with `tm' */ -+ } -+ luaG_runerror(L, "loop in settable"); -+} -+ -+ -+static int call_binTM (lua_State *L, const TValue *p1, const TValue *p2, -+ StkId res, TMS event) { -+ const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */ -+ if (ttisnil(tm)) -+ tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ -+ if (ttisnil(tm)) return 0; -+ callTMres(L, res, tm, p1, p2); -+ return 1; -+} -+ -+ -+static const TValue *get_compTM (lua_State *L, Table *mt1, Table *mt2, -+ TMS event) { -+ const TValue *tm1 = fasttm(L, mt1, event); -+ const TValue *tm2; -+ if (tm1 == NULL) return NULL; /* no metamethod */ -+ if (mt1 == mt2) return tm1; /* same metatables => same metamethods */ -+ tm2 = fasttm(L, mt2, event); -+ if (tm2 == NULL) return NULL; /* no metamethod */ -+ if (luaO_rawequalObj(tm1, tm2)) /* same metamethods? */ -+ return tm1; -+ return NULL; -+} -+ -+ -+static int call_orderTM (lua_State *L, const TValue *p1, const TValue *p2, -+ TMS event) { -+ const TValue *tm1 = luaT_gettmbyobj(L, p1, event); -+ const TValue *tm2; -+ if (ttisnil(tm1)) return -1; /* no metamethod? */ -+ tm2 = luaT_gettmbyobj(L, p2, event); -+ if (!luaO_rawequalObj(tm1, tm2)) /* different metamethods? */ -+ return -1; -+ callTMres(L, L->top, tm1, p1, p2); -+ return !l_isfalse(L->top); -+} -+ -+ -+static int l_strcmp (const TString *ls, const TString *rs) { -+ const char *l = getstr(ls); -+ size_t ll = ls->tsv.len; -+ const char *r = getstr(rs); -+ size_t lr = rs->tsv.len; -+ for (;;) { -+ int temp = strcoll(l, r); -+ if (temp != 0) return temp; -+ else { /* strings are equal up to a `\0' */ -+ size_t len = strlen(l); /* index of first `\0' in both strings */ -+ if (len == lr) /* r is finished? */ -+ return (len == ll) ? 0 : 1; -+ else if (len == ll) /* l is finished? */ -+ return -1; /* l is smaller than r (because r is not finished) */ -+ /* both strings longer than `len'; go on comparing (after the `\0') */ -+ len++; -+ l += len; ll -= len; r += len; lr -= len; -+ } -+ } -+} -+ -+ -+int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { -+ int res; -+ if (ttype(l) != ttype(r)) -+ return luaG_ordererror(L, l, r); -+ else if (ttisnumber(l)) -+ return luai_numlt(nvalue(l), nvalue(r)); -+ else if (ttisstring(l)) -+ return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0; -+ else if ((res = call_orderTM(L, l, r, TM_LT)) != -1) -+ return res; -+ return luaG_ordererror(L, l, r); -+} -+ -+ -+static int lessequal (lua_State *L, const TValue *l, const TValue *r) { -+ int res; -+ if (ttype(l) != ttype(r)) -+ return luaG_ordererror(L, l, r); -+ else if (ttisnumber(l)) -+ return luai_numle(nvalue(l), nvalue(r)); -+ else if (ttisstring(l)) -+ return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0; -+ else if ((res = call_orderTM(L, l, r, TM_LE)) != -1) /* first try `le' */ -+ return res; -+ else if ((res = call_orderTM(L, r, l, TM_LT)) != -1) /* else try `lt' */ -+ return !res; -+ return luaG_ordererror(L, l, r); -+} -+ -+ -+int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2) { -+ const TValue *tm; -+ lua_assert(ttype(t1) == ttype(t2)); -+ switch (ttype(t1)) { -+ case LUA_TNIL: return 1; -+ case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2)); -+ case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */ -+ case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2); -+ case LUA_TUSERDATA: { -+ if (uvalue(t1) == uvalue(t2)) return 1; -+ tm = get_compTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable, -+ TM_EQ); -+ break; /* will try TM */ -+ } -+ case LUA_TTABLE: { -+ if (hvalue(t1) == hvalue(t2)) return 1; -+ tm = get_compTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ); -+ break; /* will try TM */ -+ } -+ default: return gcvalue(t1) == gcvalue(t2); -+ } -+ if (tm == NULL) return 0; /* no TM? */ -+ callTMres(L, L->top, tm, t1, t2); /* call TM */ -+ return !l_isfalse(L->top); -+} -+ -+ -+void luaV_concat (lua_State *L, int total, int last) { -+ do { -+ StkId top = L->base + last + 1; -+ int n = 2; /* number of elements handled in this pass (at least 2) */ -+ if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) { -+ if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT)) -+ luaG_concaterror(L, top-2, top-1); -+ } else if (tsvalue(top-1)->len == 0) /* second op is empty? */ -+ (void)tostring(L, top - 2); /* result is first op (as string) */ -+ else { -+ /* at least two string values; get as many as possible */ -+ size_t tl = tsvalue(top-1)->len; -+ char *buffer; -+ int i; -+ /* collect total length */ -+ for (n = 1; n < total && tostring(L, top-n-1); n++) { -+ size_t l = tsvalue(top-n-1)->len; -+ if (l >= MAX_SIZET - tl) luaG_runerror(L, "string length overflow"); -+ tl += l; -+ } -+ buffer = luaZ_openspace(L, &G(L)->buff, tl); -+ tl = 0; -+ for (i=n; i>0; i--) { /* concat all strings */ -+ size_t l = tsvalue(top-i)->len; -+ memcpy(buffer+tl, svalue(top-i), l); -+ tl += l; -+ } -+ setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); -+ } -+ total -= n-1; /* got `n' strings to create 1 new */ -+ last -= n-1; -+ } while (total > 1); /* repeat until only 1 result left */ -+} -+ -+ -+static void Arith (lua_State *L, StkId ra, const TValue *rb, -+ const TValue *rc, TMS op) { -+ TValue tempb, tempc; -+ const TValue *b, *c; -+ if ((b = luaV_tonumber(rb, &tempb)) != NULL && -+ (c = luaV_tonumber(rc, &tempc)) != NULL) { -+ lua_Number nb = nvalue(b), nc = nvalue(c); -+ switch (op) { -+ case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); break; -+ case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); break; -+ case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); break; -+ case TM_DIV: setnvalue(ra, luai_numdiv(nb, nc)); break; -+ case TM_MOD: setnvalue(ra, luai_nummod(nb, nc)); break; -+ case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); break; -+ case TM_UNM: setnvalue(ra, luai_numunm(nb)); break; -+ default: lua_assert(0); break; -+ } -+ } -+ else if (!call_binTM(L, rb, rc, ra, op)) -+ luaG_aritherror(L, rb, rc); -+} -+ -+ -+ -+/* -+** some macros for common tasks in `luaV_execute' -+*/ -+ -+#define runtime_check(L, c) { if (!(c)) break; } -+ -+#define RA(i) (base+GETARG_A(i)) -+/* to be used after possible stack reallocation */ -+#define RB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i)) -+#define RC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i)) -+#define RKB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \ -+ ISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i)) -+#define RKC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \ -+ ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i)) -+#define KBx(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, k+GETARG_Bx(i)) -+ -+ -+#define dojump(L,pc,i) {(pc) += (i); luai_threadyield(L);} -+ -+ -+#define Protect(x) { L->savedpc = pc; {x;}; base = L->base; } -+ -+ -+#define arith_op(op,tm) { \ -+ TValue *rb = RKB(i); \ -+ TValue *rc = RKC(i); \ -+ if (ttisnumber(rb) && ttisnumber(rc)) { \ -+ lua_Number nb = nvalue(rb), nc = nvalue(rc); \ -+ setnvalue(ra, op(nb, nc)); \ -+ } \ -+ else \ -+ Protect(Arith(L, ra, rb, rc, tm)); \ -+ } -+ -+ -+ -+void luaV_execute (lua_State *L, int nexeccalls) { -+ LClosure *cl; -+ StkId base; -+ TValue *k; -+ const Instruction *pc; -+ reentry: /* entry point */ -+ lua_assert(isLua(L->ci)); -+ pc = L->savedpc; -+ cl = &clvalue(L->ci->func)->l; -+ base = L->base; -+ k = cl->p->k; -+ /* main loop of interpreter */ -+ for (;;) { -+ const Instruction i = *pc++; -+ StkId ra; -+ if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) && -+ (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) { -+ traceexec(L, pc); -+ if (L->status == LUA_YIELD) { /* did hook yield? */ -+ L->savedpc = pc - 1; -+ return; -+ } -+ base = L->base; -+ } -+ /* warning!! several calls may realloc the stack and invalidate `ra' */ -+ ra = RA(i); -+ lua_assert(base == L->base && L->base == L->ci->base); -+ lua_assert(base <= L->top && L->top <= L->stack + L->stacksize); -+ lua_assert(L->top == L->ci->top || luaG_checkopenop(i)); -+ switch (GET_OPCODE(i)) { -+ case OP_MOVE: { -+ setobjs2s(L, ra, RB(i)); -+ continue; -+ } -+ case OP_LOADK: { -+ setobj2s(L, ra, KBx(i)); -+ continue; -+ } -+ case OP_LOADBOOL: { -+ setbvalue(ra, GETARG_B(i)); -+ if (GETARG_C(i)) pc++; /* skip next instruction (if C) */ -+ continue; -+ } -+ case OP_LOADNIL: { -+ TValue *rb = RB(i); -+ do { -+ setnilvalue(rb--); -+ } while (rb >= ra); -+ continue; -+ } -+ case OP_GETUPVAL: { -+ int b = GETARG_B(i); -+ setobj2s(L, ra, cl->upvals[b]->v); -+ continue; -+ } -+ case OP_GETGLOBAL: { -+ TValue g; -+ TValue *rb = KBx(i); -+ sethvalue(L, &g, cl->env); -+ lua_assert(ttisstring(rb)); -+ Protect(luaV_gettable(L, &g, rb, ra)); -+ continue; -+ } -+ case OP_GETTABLE: { -+ Protect(luaV_gettable(L, RB(i), RKC(i), ra)); -+ continue; -+ } -+ case OP_SETGLOBAL: { -+ TValue g; -+ sethvalue(L, &g, cl->env); -+ lua_assert(ttisstring(KBx(i))); -+ Protect(luaV_settable(L, &g, KBx(i), ra)); -+ continue; -+ } -+ case OP_SETUPVAL: { -+ UpVal *uv = cl->upvals[GETARG_B(i)]; -+ setobj(L, uv->v, ra); -+ luaC_barrier(L, uv, ra); -+ continue; -+ } -+ case OP_SETTABLE: { -+ Protect(luaV_settable(L, ra, RKB(i), RKC(i))); -+ continue; -+ } -+ case OP_NEWTABLE: { -+ int b = GETARG_B(i); -+ int c = GETARG_C(i); -+ sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c))); -+ Protect(luaC_checkGC(L)); -+ continue; -+ } -+ case OP_SELF: { -+ StkId rb = RB(i); -+ setobjs2s(L, ra+1, rb); -+ Protect(luaV_gettable(L, rb, RKC(i), ra)); -+ continue; -+ } -+ case OP_ADD: { -+ arith_op(luai_numadd, TM_ADD); -+ continue; -+ } -+ case OP_SUB: { -+ arith_op(luai_numsub, TM_SUB); -+ continue; -+ } -+ case OP_MUL: { -+ arith_op(luai_nummul, TM_MUL); -+ continue; -+ } -+ case OP_DIV: { -+ arith_op(luai_numdiv, TM_DIV); -+ continue; -+ } -+ case OP_MOD: { -+ arith_op(luai_nummod, TM_MOD); -+ continue; -+ } -+ case OP_POW: { -+ arith_op(luai_numpow, TM_POW); -+ continue; -+ } -+ case OP_UNM: { -+ TValue *rb = RB(i); -+ if (ttisnumber(rb)) { -+ lua_Number nb = nvalue(rb); -+ setnvalue(ra, luai_numunm(nb)); -+ } -+ else { -+ Protect(Arith(L, ra, rb, rb, TM_UNM)); -+ } -+ continue; -+ } -+ case OP_NOT: { -+ int res = l_isfalse(RB(i)); /* next assignment may change this value */ -+ setbvalue(ra, res); -+ continue; -+ } -+ case OP_LEN: { -+ const TValue *rb = RB(i); -+ switch (ttype(rb)) { -+ case LUA_TTABLE: { -+ setnvalue(ra, cast_num(luaH_getn(hvalue(rb)))); -+ break; -+ } -+ case LUA_TSTRING: { -+ setnvalue(ra, cast_num(tsvalue(rb)->len)); -+ break; -+ } -+ default: { /* try metamethod */ -+ Protect( -+ if (!call_binTM(L, rb, luaO_nilobject, ra, TM_LEN)) -+ luaG_typeerror(L, rb, "get length of"); -+ ) -+ } -+ } -+ continue; -+ } -+ case OP_CONCAT: { -+ int b = GETARG_B(i); -+ int c = GETARG_C(i); -+ Protect(luaV_concat(L, c-b+1, c); luaC_checkGC(L)); -+ setobjs2s(L, RA(i), base+b); -+ continue; -+ } -+ case OP_JMP: { -+ dojump(L, pc, GETARG_sBx(i)); -+ continue; -+ } -+ case OP_EQ: { -+ TValue *rb = RKB(i); -+ TValue *rc = RKC(i); -+ Protect( -+ if (equalobj(L, rb, rc) == GETARG_A(i)) -+ dojump(L, pc, GETARG_sBx(*pc)); -+ ) -+ pc++; -+ continue; -+ } -+ case OP_LT: { -+ Protect( -+ if (luaV_lessthan(L, RKB(i), RKC(i)) == GETARG_A(i)) -+ dojump(L, pc, GETARG_sBx(*pc)); -+ ) -+ pc++; -+ continue; -+ } -+ case OP_LE: { -+ Protect( -+ if (lessequal(L, RKB(i), RKC(i)) == GETARG_A(i)) -+ dojump(L, pc, GETARG_sBx(*pc)); -+ ) -+ pc++; -+ continue; -+ } -+ case OP_TEST: { -+ if (l_isfalse(ra) != GETARG_C(i)) -+ dojump(L, pc, GETARG_sBx(*pc)); -+ pc++; -+ continue; -+ } -+ case OP_TESTSET: { -+ TValue *rb = RB(i); -+ if (l_isfalse(rb) != GETARG_C(i)) { -+ setobjs2s(L, ra, rb); -+ dojump(L, pc, GETARG_sBx(*pc)); -+ } -+ pc++; -+ continue; -+ } -+ case OP_CALL: { -+ int b = GETARG_B(i); -+ int nresults = GETARG_C(i) - 1; -+ if (b != 0) L->top = ra+b; /* else previous instruction set top */ -+ L->savedpc = pc; -+ switch (luaD_precall(L, ra, nresults)) { -+ case PCRLUA: { -+ nexeccalls++; -+ goto reentry; /* restart luaV_execute over new Lua function */ -+ } -+ case PCRC: { -+ /* it was a C function (`precall' called it); adjust results */ -+ if (nresults >= 0) L->top = L->ci->top; -+ base = L->base; -+ continue; -+ } -+ default: { -+ return; /* yield */ -+ } -+ } -+ } -+ case OP_TAILCALL: { -+ int b = GETARG_B(i); -+ if (b != 0) L->top = ra+b; /* else previous instruction set top */ -+ L->savedpc = pc; -+ lua_assert(GETARG_C(i) - 1 == LUA_MULTRET); -+ switch (luaD_precall(L, ra, LUA_MULTRET)) { -+ case PCRLUA: { -+ /* tail call: put new frame in place of previous one */ -+ CallInfo *ci = L->ci - 1; /* previous frame */ -+ int aux; -+ StkId func = ci->func; -+ StkId pfunc = (ci+1)->func; /* previous function index */ -+ if (L->openupval) luaF_close(L, ci->base); -+ L->base = ci->base = ci->func + ((ci+1)->base - pfunc); -+ for (aux = 0; pfunc+aux < L->top; aux++) /* move frame down */ -+ setobjs2s(L, func+aux, pfunc+aux); -+ ci->top = L->top = func+aux; /* correct top */ -+ lua_assert(L->top == L->base + clvalue(func)->l.p->maxstacksize); -+ ci->savedpc = L->savedpc; -+ ci->tailcalls++; /* one more call lost */ -+ L->ci--; /* remove new frame */ -+ goto reentry; -+ } -+ case PCRC: { /* it was a C function (`precall' called it) */ -+ base = L->base; -+ continue; -+ } -+ default: { -+ return; /* yield */ -+ } -+ } -+ } -+ case OP_RETURN: { -+ int b = GETARG_B(i); -+ if (b != 0) L->top = ra+b-1; -+ if (L->openupval) luaF_close(L, base); -+ L->savedpc = pc; -+ b = luaD_poscall(L, ra); -+ if (--nexeccalls == 0) /* was previous function running `here'? */ -+ return; /* no: return */ -+ else { /* yes: continue its execution */ -+ if (b) L->top = L->ci->top; -+ lua_assert(isLua(L->ci)); -+ lua_assert(GET_OPCODE(*((L->ci)->savedpc - 1)) == OP_CALL); -+ goto reentry; -+ } -+ } -+ case OP_FORLOOP: { -+ lua_Number step = nvalue(ra+2); -+ lua_Number idx = luai_numadd(nvalue(ra), step); /* increment index */ -+ lua_Number limit = nvalue(ra+1); -+ if (luai_numlt(0, step) ? luai_numle(idx, limit) -+ : luai_numle(limit, idx)) { -+ dojump(L, pc, GETARG_sBx(i)); /* jump back */ -+ setnvalue(ra, idx); /* update internal index... */ -+ setnvalue(ra+3, idx); /* ...and external index */ -+ } -+ continue; -+ } -+ case OP_FORPREP: { -+ const TValue *init = ra; -+ const TValue *plimit = ra+1; -+ const TValue *pstep = ra+2; -+ L->savedpc = pc; /* next steps may throw errors */ -+ if (!tonumber(init, ra)) -+ luaG_runerror(L, LUA_QL("for") " initial value must be a number"); -+ else if (!tonumber(plimit, ra+1)) -+ luaG_runerror(L, LUA_QL("for") " limit must be a number"); -+ else if (!tonumber(pstep, ra+2)) -+ luaG_runerror(L, LUA_QL("for") " step must be a number"); -+ setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep))); -+ dojump(L, pc, GETARG_sBx(i)); -+ continue; -+ } -+ case OP_TFORLOOP: { -+ StkId cb = ra + 3; /* call base */ -+ setobjs2s(L, cb+2, ra+2); -+ setobjs2s(L, cb+1, ra+1); -+ setobjs2s(L, cb, ra); -+ L->top = cb+3; /* func. + 2 args (state and index) */ -+ Protect(luaD_call(L, cb, GETARG_C(i))); -+ L->top = L->ci->top; -+ cb = RA(i) + 3; /* previous call may change the stack */ -+ if (!ttisnil(cb)) { /* continue loop? */ -+ setobjs2s(L, cb-1, cb); /* save control variable */ -+ dojump(L, pc, GETARG_sBx(*pc)); /* jump back */ -+ } -+ pc++; -+ continue; -+ } -+ case OP_SETLIST: { -+ int n = GETARG_B(i); -+ int c = GETARG_C(i); -+ int last; -+ Table *h; -+ if (n == 0) { -+ n = cast_int(L->top - ra) - 1; -+ L->top = L->ci->top; -+ } -+ if (c == 0) c = cast_int(*pc++); -+ runtime_check(L, ttistable(ra)); -+ h = hvalue(ra); -+ last = ((c-1)*LFIELDS_PER_FLUSH) + n; -+ if (last > h->sizearray) /* needs more space? */ -+ luaH_resizearray(L, h, last); /* pre-alloc it at once */ -+ for (; n > 0; n--) { -+ TValue *val = ra+n; -+ setobj2t(L, luaH_setnum(L, h, last--), val); -+ luaC_barriert(L, h, val); -+ } -+ continue; -+ } -+ case OP_CLOSE: { -+ luaF_close(L, ra); -+ continue; -+ } -+ case OP_CLOSURE: { -+ Proto *p; -+ Closure *ncl; -+ int nup, j; -+ p = cl->p->p[GETARG_Bx(i)]; -+ nup = p->nups; -+ ncl = luaF_newLclosure(L, nup, cl->env); -+ ncl->l.p = p; -+ for (j=0; jl.upvals[j] = cl->upvals[GETARG_B(*pc)]; -+ else { -+ lua_assert(GET_OPCODE(*pc) == OP_MOVE); -+ ncl->l.upvals[j] = luaF_findupval(L, base + GETARG_B(*pc)); -+ } -+ } -+ setclvalue(L, ra, ncl); -+ Protect(luaC_checkGC(L)); -+ continue; -+ } -+ case OP_VARARG: { -+ int b = GETARG_B(i) - 1; -+ int j; -+ CallInfo *ci = L->ci; -+ int n = cast_int(ci->base - ci->func) - cl->p->numparams - 1; -+ if (b == LUA_MULTRET) { -+ Protect(luaD_checkstack(L, n)); -+ ra = RA(i); /* previous call may change the stack */ -+ b = n; -+ L->top = ra + n; -+ } -+ for (j = 0; j < b; j++) { -+ if (j < n) { -+ setobjs2s(L, ra + j, ci->base - n + j); -+ } -+ else { -+ setnilvalue(ra + j); -+ } -+ } -+ continue; -+ } -+ } -+ } -+} -+ ---- /dev/null -+++ b/extensions/LUA/lua/lvm.h -@@ -0,0 +1,36 @@ -+/* -+** $Id: lvm.h,v 2.5.1.1 2007/12/27 13:02:25 roberto Exp $ -+** Lua virtual machine -+** See Copyright Notice in lua.h -+*/ -+ -+#ifndef lvm_h -+#define lvm_h -+ -+ -+#include "ldo.h" -+#include "lobject.h" -+#include "ltm.h" -+ -+ -+#define tostring(L,o) ((ttype(o) == LUA_TSTRING) || (luaV_tostring(L, o))) -+ -+#define tonumber(o,n) (ttype(o) == LUA_TNUMBER || \ -+ (((o) = luaV_tonumber(o,n)) != NULL)) -+ -+#define equalobj(L,o1,o2) \ -+ (ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2)) -+ -+ -+LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); -+LUAI_FUNC int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2); -+LUAI_FUNC const TValue *luaV_tonumber (const TValue *obj, TValue *n); -+LUAI_FUNC int luaV_tostring (lua_State *L, StkId obj); -+LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key, -+ StkId val); -+LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key, -+ StkId val); -+LUAI_FUNC void luaV_execute (lua_State *L, int nexeccalls); -+LUAI_FUNC void luaV_concat (lua_State *L, int total, int last); -+ -+#endif ---- /dev/null -+++ b/extensions/LUA/lua/lzio.c -@@ -0,0 +1,81 @@ -+/* -+** $Id: lzio.c,v 1.31.1.1 2007/12/27 13:02:25 roberto Exp $ -+** a generic input stream interface -+** See Copyright Notice in lua.h -+*/ -+ -+#include -+ -+#define lzio_c -+#define LUA_CORE -+ -+#include "lua.h" -+ -+#include "llimits.h" -+#include "lmem.h" -+#include "lstate.h" -+#include "lzio.h" -+ -+ -+int luaZ_fill (ZIO *z) { -+ size_t size; -+ lua_State *L = z->L; -+ const char *buff; -+ lua_unlock(L); -+ buff = z->reader(L, z->data, &size); -+ lua_lock(L); -+ if (buff == NULL || size == 0) return EOZ; -+ z->n = size - 1; -+ z->p = buff; -+ return char2int(*(z->p++)); -+} -+ -+ -+int luaZ_lookahead (ZIO *z) { -+ if (z->n == 0) { -+ if (luaZ_fill(z) == EOZ) -+ return EOZ; -+ else { -+ z->n++; /* luaZ_fill removed first byte; put back it */ -+ z->p--; -+ } -+ } -+ return char2int(*z->p); -+} -+ -+ -+void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data) { -+ z->L = L; -+ z->reader = reader; -+ z->data = data; -+ z->n = 0; -+ z->p = NULL; -+} -+ -+ -+/* --------------------------------------------------------------- read --- */ -+size_t luaZ_read (ZIO *z, void *b, size_t n) { -+ while (n) { -+ size_t m; -+ if (luaZ_lookahead(z) == EOZ) -+ return n; /* return number of missing bytes */ -+ m = (n <= z->n) ? n : z->n; /* min. between n and z->n */ -+ memcpy(b, z->p, m); -+ z->n -= m; -+ z->p += m; -+ b = (char *)b + m; -+ n -= m; -+ } -+ return 0; -+} -+ -+/* ------------------------------------------------------------------------ */ -+char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n) { -+ if (n > buff->buffsize) { -+ if (n < LUA_MINBUFFER) n = LUA_MINBUFFER; -+ luaZ_resizebuffer(L, buff, n); -+ } -+ return buff->buffer; -+} -+ -+ ---- /dev/null -+++ b/extensions/LUA/lua/lzio.h -@@ -0,0 +1,67 @@ -+/* -+** $Id: lzio.h,v 1.21.1.1 2007/12/27 13:02:25 roberto Exp $ -+** Buffered streams -+** See Copyright Notice in lua.h -+*/ -+ -+ -+#ifndef lzio_h -+#define lzio_h -+ -+#include "lua.h" -+ -+#include "lmem.h" -+ -+ -+#define EOZ (-1) /* end of stream */ -+ -+typedef struct Zio ZIO; -+ -+#define char2int(c) cast(int, cast(unsigned char, (c))) -+ -+#define zgetc(z) (((z)->n--)>0 ? char2int(*(z)->p++) : luaZ_fill(z)) -+ -+typedef struct Mbuffer { -+ char *buffer; -+ size_t n; -+ size_t buffsize; -+} Mbuffer; -+ -+#define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0) -+ -+#define luaZ_buffer(buff) ((buff)->buffer) -+#define luaZ_sizebuffer(buff) ((buff)->buffsize) -+#define luaZ_bufflen(buff) ((buff)->n) -+ -+#define luaZ_resetbuffer(buff) ((buff)->n = 0) -+ -+ -+#define luaZ_resizebuffer(L, buff, size) \ -+ (luaM_reallocvector(L, (buff)->buffer, (buff)->buffsize, size, char), \ -+ (buff)->buffsize = size) -+ -+#define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0) -+ -+ -+LUAI_FUNC char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n); -+LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, -+ void *data); -+LUAI_FUNC size_t luaZ_read (ZIO* z, void* b, size_t n); /* read next n bytes */ -+LUAI_FUNC int luaZ_lookahead (ZIO *z); -+ -+ -+ -+/* --------- Private Part ------------------ */ -+ -+struct Zio { -+ size_t n; /* bytes still unread */ -+ const char *p; /* current position in buffer */ -+ lua_Reader reader; -+ void* data; /* additional data */ -+ lua_State *L; /* Lua state (for reader) */ -+}; -+ -+ -+LUAI_FUNC int luaZ_fill (ZIO *z); -+ -+#endif ---- /dev/null -+++ b/extensions/LUA/Makefile -@@ -0,0 +1,389 @@ -+# Makefile.in generated by automake 1.11.1 from Makefile.am. -+# extensions/LUA/Makefile. Generated from Makefile.in by configure. -+ -+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, -+# Inc. -+# This Makefile.in is free software; the Free Software Foundation -+# gives unlimited permission to copy and/or distribute it, -+# with or without modifications, as long as this notice is preserved. -+ -+# This program is distributed in the hope that it will be useful, -+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -+# PARTICULAR PURPOSE. -+ -+ -+ -+# -*- Makefile -*- -+# AUTOMAKE -+ -+pkgdatadir = $(datadir)/xtables-addons -+pkgincludedir = $(includedir)/xtables-addons -+pkglibdir = $(libdir)/xtables-addons -+pkglibexecdir = $(libexecdir)/xtables-addons -+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -+install_sh_DATA = $(install_sh) -c -m 644 -+install_sh_PROGRAM = $(install_sh) -c -+install_sh_SCRIPT = $(install_sh) -c -+INSTALL_HEADER = $(INSTALL_DATA) -+transform = $(program_transform_name) -+NORMAL_INSTALL = : -+PRE_INSTALL = : -+POST_INSTALL = : -+NORMAL_UNINSTALL = : -+PRE_UNINSTALL = : -+POST_UNINSTALL = : -+build_triplet = i686-pc-linux-gnu -+host_triplet = i686-pc-linux-gnu -+DIST_COMMON = $(srcdir)/../../Makefile.extra $(srcdir)/Makefile.am \ -+ $(srcdir)/Makefile.in -+subdir = extensions/LUA -+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -+am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ -+ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ -+ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ -+ $(top_srcdir)/configure.ac -+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ -+ $(ACLOCAL_M4) -+mkinstalldirs = $(install_sh) -d -+CONFIG_HEADER = $(top_builddir)/config.h -+CONFIG_CLEAN_FILES = -+CONFIG_CLEAN_VPATH_FILES = -+SOURCES = -+DIST_SOURCES = -+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -+ACLOCAL = ${SHELL} /home/andre/Dropbox/xtables-addons/missing --run aclocal-1.11 -+AMTAR = ${SHELL} /home/andre/Dropbox/xtables-addons/missing --run tar -+AR = ar -+AUTOCONF = ${SHELL} /home/andre/Dropbox/xtables-addons/missing --run autoconf -+AUTOHEADER = ${SHELL} /home/andre/Dropbox/xtables-addons/missing --run autoheader -+AUTOMAKE = ${SHELL} /home/andre/Dropbox/xtables-addons/missing --run automake-1.11 -+AWK = mawk -+CC = gcc -+CCDEPMODE = depmode=gcc3 -+CFLAGS = -g -O2 -+CPP = gcc -E -+CPPFLAGS = -+CYGPATH_W = echo -+DEFS = -DHAVE_CONFIG_H -+DEPDIR = .deps -+DSYMUTIL = -+DUMPBIN = -+ECHO_C = -+ECHO_N = -n -+ECHO_T = -+EGREP = /bin/grep -E -+EXEEXT = -+FGREP = /bin/grep -F -+GREP = /bin/grep -+INSTALL = /usr/bin/install -c -+INSTALL_DATA = ${INSTALL} -m 644 -+INSTALL_PROGRAM = ${INSTALL} -+INSTALL_SCRIPT = ${INSTALL} -+INSTALL_STRIP_PROGRAM = $(install_sh) -c -s -+LD = /usr/bin/ld -+LDFLAGS = -+LIBOBJS = -+LIBS = -+LIBTOOL = $(SHELL) $(top_builddir)/libtool -+LIPO = -+LN_S = ln -s -+LTLIBOBJS = -+MAKEINFO = ${SHELL} /home/andre/Dropbox/xtables-addons/missing --run makeinfo -+MKDIR_P = /bin/mkdir -p -+NM = /usr/bin/nm -B -+NMEDIT = -+OBJDUMP = objdump -+OBJEXT = o -+OTOOL = -+OTOOL64 = -+PACKAGE = xtables-addons -+PACKAGE_BUGREPORT = -+PACKAGE_NAME = xtables-addons -+PACKAGE_STRING = xtables-addons 1.21 -+PACKAGE_TARNAME = xtables-addons -+PACKAGE_URL = -+PACKAGE_VERSION = 1.21 -+PATH_SEPARATOR = : -+PKG_CONFIG = /usr/bin/pkg-config -+RANLIB = ranlib -+SED = /bin/sed -+SET_MAKE = -+SHELL = /bin/bash -+STRIP = strip -+VERSION = 1.21 -+abs_builddir = /home/andre/Dropbox/xtables-addons/extensions/LUA -+abs_srcdir = /home/andre/Dropbox/xtables-addons/extensions/LUA -+abs_top_builddir = /home/andre/Dropbox/xtables-addons -+abs_top_srcdir = /home/andre/Dropbox/xtables-addons -+ac_ct_CC = gcc -+ac_ct_DUMPBIN = -+am__include = include -+am__leading_dot = . -+am__quote = -+am__tar = ${AMTAR} chof - "$$tardir" -+am__untar = ${AMTAR} xf - -+bindir = ${exec_prefix}/bin -+build = i686-pc-linux-gnu -+build_alias = -+build_cpu = i686 -+build_os = linux-gnu -+build_vendor = pc -+builddir = . -+datadir = ${datarootdir} -+datarootdir = ${prefix}/share -+docdir = ${datarootdir}/doc/${PACKAGE_TARNAME} -+dvidir = ${docdir} -+exec_prefix = ${prefix} -+host = i686-pc-linux-gnu -+host_alias = -+host_cpu = i686 -+host_os = linux-gnu -+host_vendor = pc -+htmldir = ${docdir} -+includedir = ${prefix}/include -+infodir = ${datarootdir}/info -+install_sh = ${SHELL} /home/andre/Dropbox/xtables-addons/install-sh -+kbuilddir = /lib/modules/2.6.33-020633-generic/build -+kinclude_CFLAGS = -I /lib/modules/2.6.33-020633-generic/build/include -+ksourcedir = -+libdir = ${exec_prefix}/lib -+libexecdir = ${exec_prefix}/libexec -+libxtables_CFLAGS = -+libxtables_LIBS = -L/lib -lxtables -+localedir = ${datarootdir}/locale -+localstatedir = ${prefix}/var -+lt_ECHO = echo -+mandir = ${datarootdir}/man -+mkdir_p = /bin/mkdir -p -+oldincludedir = /usr/include -+pdfdir = ${docdir} -+prefix = /usr/local -+program_transform_name = s,x,x, -+psdir = ${docdir} -+regular_CFLAGS = -D_LARGEFILE_SOURCE=1 -D_LARGE_FILES -D_FILE_OFFSET_BITS=64 -D_REENTRANT -Wall -Waggregate-return -Wmissing-declarations -Wmissing-prototypes -Wredundant-decls -Wshadow -Wstrict-prototypes -Winline -pipe -DXTABLES_LIBDIR=\"${xtlibdir}\" -+sbindir = ${exec_prefix}/sbin -+sharedstatedir = ${prefix}/com -+srcdir = . -+sysconfdir = ${prefix}/etc -+target_alias = -+top_build_prefix = ../../ -+top_builddir = ../.. -+top_srcdir = ../.. -+xtlibdir = ${libexecdir}/xtables -+XA_SRCDIR = ${srcdir} -+XA_TOPSRCDIR = ${top_srcdir} -+XA_ABSTOPSRCDIR = ${abs_top_srcdir} -+_mcall = -f ${top_builddir}/Makefile.iptrules -+all: all-am -+ -+.SUFFIXES: -+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(srcdir)/../../Makefile.extra $(am__configure_deps) -+ @for dep in $?; do \ -+ case '$(am__configure_deps)' in \ -+ *$$dep*) \ -+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ -+ && { if test -f $@; then exit 0; else break; fi; }; \ -+ exit 1;; \ -+ esac; \ -+ done; \ -+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign extensions/LUA/Makefile'; \ -+ $(am__cd) $(top_srcdir) && \ -+ $(AUTOMAKE) --foreign extensions/LUA/Makefile -+.PRECIOUS: Makefile -+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status -+ @case '$?' in \ -+ *config.status*) \ -+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ -+ *) \ -+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ -+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ -+ esac; -+ -+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) -+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -+ -+$(top_srcdir)/configure: $(am__configure_deps) -+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -+$(ACLOCAL_M4): $(am__aclocal_m4_deps) -+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -+$(am__aclocal_m4_deps): -+ -+mostlyclean-libtool: -+ -rm -f *.lo -+ -+clean-libtool: -+ -rm -rf .libs _libs -+tags: TAGS -+TAGS: -+ -+ctags: CTAGS -+CTAGS: -+ -+ -+distdir: $(DISTFILES) -+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ -+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ -+ list='$(DISTFILES)'; \ -+ dist_files=`for file in $$list; do echo $$file; done | \ -+ sed -e "s|^$$srcdirstrip/||;t" \ -+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ -+ case $$dist_files in \ -+ */*) $(MKDIR_P) `echo "$$dist_files" | \ -+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ -+ sort -u` ;; \ -+ esac; \ -+ for file in $$dist_files; do \ -+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ -+ if test -d $$d/$$file; then \ -+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ -+ if test -d "$(distdir)/$$file"; then \ -+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ -+ fi; \ -+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ -+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ -+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ -+ fi; \ -+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ -+ else \ -+ test -f "$(distdir)/$$file" \ -+ || cp -p $$d/$$file "$(distdir)/$$file" \ -+ || exit 1; \ -+ fi; \ -+ done -+check-am: all-am -+check: check-am -+all-am: Makefile all-local -+installdirs: -+install: install-am -+install-exec: install-exec-am -+install-data: install-data-am -+uninstall: uninstall-am -+ -+install-am: all-am -+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am -+ -+installcheck: installcheck-am -+install-strip: -+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ -+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ -+ `test -z '$(STRIP)' || \ -+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install -+mostlyclean-generic: -+ -+clean-generic: -+ -+distclean-generic: -+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) -+ -+maintainer-clean-generic: -+ @echo "This command is intended for maintainers to use" -+ @echo "it deletes files that may require special tools to rebuild." -+clean: clean-am -+ -+clean-am: clean-generic clean-libtool clean-local mostlyclean-am -+ -+distclean: distclean-am -+ -rm -f Makefile -+distclean-am: clean-am distclean-generic -+ -+dvi: dvi-am -+ -+dvi-am: -+ -+html: html-am -+ -+html-am: -+ -+info: info-am -+ -+info-am: -+ -+install-data-am: -+ -+install-dvi: install-dvi-am -+ -+install-dvi-am: -+ -+install-exec-am: install-exec-local -+ -+install-html: install-html-am -+ -+install-html-am: -+ -+install-info: install-info-am -+ -+install-info-am: -+ -+install-man: -+ -+install-pdf: install-pdf-am -+ -+install-pdf-am: -+ -+install-ps: install-ps-am -+ -+install-ps-am: -+ -+installcheck-am: -+ -+maintainer-clean: maintainer-clean-am -+ -rm -f Makefile -+maintainer-clean-am: distclean-am maintainer-clean-generic -+ -+mostlyclean: mostlyclean-am -+ -+mostlyclean-am: mostlyclean-generic mostlyclean-libtool -+ -+pdf: pdf-am -+ -+pdf-am: -+ -+ps: ps-am -+ -+ps-am: -+ -+uninstall-am: -+ -+.MAKE: install-am install-strip -+ -+.PHONY: all all-am all-local check check-am clean clean-generic \ -+ clean-libtool clean-local distclean distclean-generic \ -+ distclean-libtool distdir dvi dvi-am html html-am info info-am \ -+ install install-am install-data install-data-am install-dvi \ -+ install-dvi-am install-exec install-exec-am install-exec-local \ -+ install-html install-html-am install-info install-info-am \ -+ install-man install-pdf install-pdf-am install-ps \ -+ install-ps-am install-strip installcheck installcheck-am \ -+ installdirs maintainer-clean maintainer-clean-generic \ -+ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ -+ ps ps-am uninstall uninstall-am -+ -+export XA_SRCDIR -+export XA_TOPSRCDIR -+export XA_ABSTOPSRCDIR -+ -+all-local: user-all-local -+ -+install-exec-local: user-install-local -+ -+clean-local: user-clean-local -+ -+user-all-local: -+ ${MAKE} ${_mcall} all; -+ -+# Have no user-install-data-local ATM -+user-install-local: user-install-exec-local -+ -+user-install-exec-local: -+ ${MAKE} ${_mcall} install; -+ -+user-clean-local: -+ ${MAKE} ${_mcall} clean; -+ -+# Tell versions [3.59,3.63) of GNU make to not export all variables. -+# Otherwise a system limit (for SysV at least) may be exceeded. -+.NOEXPORT: -+ ---- /dev/null -+++ b/extensions/LUA/Makefile.am -@@ -0,0 +1 @@ -+include ../../Makefile.extra ---- /dev/null -+++ b/extensions/LUA/Makefile.in -@@ -0,0 +1,389 @@ -+# Makefile.in generated by automake 1.11.1 from Makefile.am. -+# @configure_input@ -+ -+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, -+# Inc. -+# This Makefile.in is free software; the Free Software Foundation -+# gives unlimited permission to copy and/or distribute it, -+# with or without modifications, as long as this notice is preserved. -+ -+# This program is distributed in the hope that it will be useful, -+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -+# PARTICULAR PURPOSE. -+ -+@SET_MAKE@ -+ -+# -*- Makefile -*- -+# AUTOMAKE -+VPATH = @srcdir@ -+pkgdatadir = $(datadir)/@PACKAGE@ -+pkgincludedir = $(includedir)/@PACKAGE@ -+pkglibdir = $(libdir)/@PACKAGE@ -+pkglibexecdir = $(libexecdir)/@PACKAGE@ -+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -+install_sh_DATA = $(install_sh) -c -m 644 -+install_sh_PROGRAM = $(install_sh) -c -+install_sh_SCRIPT = $(install_sh) -c -+INSTALL_HEADER = $(INSTALL_DATA) -+transform = $(program_transform_name) -+NORMAL_INSTALL = : -+PRE_INSTALL = : -+POST_INSTALL = : -+NORMAL_UNINSTALL = : -+PRE_UNINSTALL = : -+POST_UNINSTALL = : -+build_triplet = @build@ -+host_triplet = @host@ -+DIST_COMMON = $(srcdir)/../../Makefile.extra $(srcdir)/Makefile.am \ -+ $(srcdir)/Makefile.in -+subdir = extensions/LUA -+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -+am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ -+ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ -+ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ -+ $(top_srcdir)/configure.ac -+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ -+ $(ACLOCAL_M4) -+mkinstalldirs = $(install_sh) -d -+CONFIG_HEADER = $(top_builddir)/config.h -+CONFIG_CLEAN_FILES = -+CONFIG_CLEAN_VPATH_FILES = -+SOURCES = -+DIST_SOURCES = -+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -+ACLOCAL = @ACLOCAL@ -+AMTAR = @AMTAR@ -+AR = @AR@ -+AUTOCONF = @AUTOCONF@ -+AUTOHEADER = @AUTOHEADER@ -+AUTOMAKE = @AUTOMAKE@ -+AWK = @AWK@ -+CC = @CC@ -+CCDEPMODE = @CCDEPMODE@ -+CFLAGS = @CFLAGS@ -+CPP = @CPP@ -+CPPFLAGS = @CPPFLAGS@ -+CYGPATH_W = @CYGPATH_W@ -+DEFS = @DEFS@ -+DEPDIR = @DEPDIR@ -+DSYMUTIL = @DSYMUTIL@ -+DUMPBIN = @DUMPBIN@ -+ECHO_C = @ECHO_C@ -+ECHO_N = @ECHO_N@ -+ECHO_T = @ECHO_T@ -+EGREP = @EGREP@ -+EXEEXT = @EXEEXT@ -+FGREP = @FGREP@ -+GREP = @GREP@ -+INSTALL = @INSTALL@ -+INSTALL_DATA = @INSTALL_DATA@ -+INSTALL_PROGRAM = @INSTALL_PROGRAM@ -+INSTALL_SCRIPT = @INSTALL_SCRIPT@ -+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -+LD = @LD@ -+LDFLAGS = @LDFLAGS@ -+LIBOBJS = @LIBOBJS@ -+LIBS = @LIBS@ -+LIBTOOL = @LIBTOOL@ -+LIPO = @LIPO@ -+LN_S = @LN_S@ -+LTLIBOBJS = @LTLIBOBJS@ -+MAKEINFO = @MAKEINFO@ -+MKDIR_P = @MKDIR_P@ -+NM = @NM@ -+NMEDIT = @NMEDIT@ -+OBJDUMP = @OBJDUMP@ -+OBJEXT = @OBJEXT@ -+OTOOL = @OTOOL@ -+OTOOL64 = @OTOOL64@ -+PACKAGE = @PACKAGE@ -+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -+PACKAGE_NAME = @PACKAGE_NAME@ -+PACKAGE_STRING = @PACKAGE_STRING@ -+PACKAGE_TARNAME = @PACKAGE_TARNAME@ -+PACKAGE_URL = @PACKAGE_URL@ -+PACKAGE_VERSION = @PACKAGE_VERSION@ -+PATH_SEPARATOR = @PATH_SEPARATOR@ -+PKG_CONFIG = @PKG_CONFIG@ -+RANLIB = @RANLIB@ -+SED = @SED@ -+SET_MAKE = @SET_MAKE@ -+SHELL = @SHELL@ -+STRIP = @STRIP@ -+VERSION = @VERSION@ -+abs_builddir = @abs_builddir@ -+abs_srcdir = @abs_srcdir@ -+abs_top_builddir = @abs_top_builddir@ -+abs_top_srcdir = @abs_top_srcdir@ -+ac_ct_CC = @ac_ct_CC@ -+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ -+am__include = @am__include@ -+am__leading_dot = @am__leading_dot@ -+am__quote = @am__quote@ -+am__tar = @am__tar@ -+am__untar = @am__untar@ -+bindir = @bindir@ -+build = @build@ -+build_alias = @build_alias@ -+build_cpu = @build_cpu@ -+build_os = @build_os@ -+build_vendor = @build_vendor@ -+builddir = @builddir@ -+datadir = @datadir@ -+datarootdir = @datarootdir@ -+docdir = @docdir@ -+dvidir = @dvidir@ -+exec_prefix = @exec_prefix@ -+host = @host@ -+host_alias = @host_alias@ -+host_cpu = @host_cpu@ -+host_os = @host_os@ -+host_vendor = @host_vendor@ -+htmldir = @htmldir@ -+includedir = @includedir@ -+infodir = @infodir@ -+install_sh = @install_sh@ -+kbuilddir = @kbuilddir@ -+kinclude_CFLAGS = @kinclude_CFLAGS@ -+ksourcedir = @ksourcedir@ -+libdir = @libdir@ -+libexecdir = @libexecdir@ -+libxtables_CFLAGS = @libxtables_CFLAGS@ -+libxtables_LIBS = @libxtables_LIBS@ -+localedir = @localedir@ -+localstatedir = @localstatedir@ -+lt_ECHO = @lt_ECHO@ -+mandir = @mandir@ -+mkdir_p = @mkdir_p@ -+oldincludedir = @oldincludedir@ -+pdfdir = @pdfdir@ -+prefix = @prefix@ -+program_transform_name = @program_transform_name@ -+psdir = @psdir@ -+regular_CFLAGS = @regular_CFLAGS@ -+sbindir = @sbindir@ -+sharedstatedir = @sharedstatedir@ -+srcdir = @srcdir@ -+sysconfdir = @sysconfdir@ -+target_alias = @target_alias@ -+top_build_prefix = @top_build_prefix@ -+top_builddir = @top_builddir@ -+top_srcdir = @top_srcdir@ -+xtlibdir = @xtlibdir@ -+XA_SRCDIR = ${srcdir} -+XA_TOPSRCDIR = ${top_srcdir} -+XA_ABSTOPSRCDIR = ${abs_top_srcdir} -+_mcall = -f ${top_builddir}/Makefile.iptrules -+all: all-am -+ -+.SUFFIXES: -+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(srcdir)/../../Makefile.extra $(am__configure_deps) -+ @for dep in $?; do \ -+ case '$(am__configure_deps)' in \ -+ *$$dep*) \ -+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ -+ && { if test -f $@; then exit 0; else break; fi; }; \ -+ exit 1;; \ -+ esac; \ -+ done; \ -+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign extensions/LUA/Makefile'; \ -+ $(am__cd) $(top_srcdir) && \ -+ $(AUTOMAKE) --foreign extensions/LUA/Makefile -+.PRECIOUS: Makefile -+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status -+ @case '$?' in \ -+ *config.status*) \ -+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ -+ *) \ -+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ -+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ -+ esac; -+ -+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) -+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -+ -+$(top_srcdir)/configure: $(am__configure_deps) -+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -+$(ACLOCAL_M4): $(am__aclocal_m4_deps) -+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -+$(am__aclocal_m4_deps): -+ -+mostlyclean-libtool: -+ -rm -f *.lo -+ -+clean-libtool: -+ -rm -rf .libs _libs -+tags: TAGS -+TAGS: -+ -+ctags: CTAGS -+CTAGS: -+ -+ -+distdir: $(DISTFILES) -+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ -+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ -+ list='$(DISTFILES)'; \ -+ dist_files=`for file in $$list; do echo $$file; done | \ -+ sed -e "s|^$$srcdirstrip/||;t" \ -+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ -+ case $$dist_files in \ -+ */*) $(MKDIR_P) `echo "$$dist_files" | \ -+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ -+ sort -u` ;; \ -+ esac; \ -+ for file in $$dist_files; do \ -+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ -+ if test -d $$d/$$file; then \ -+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ -+ if test -d "$(distdir)/$$file"; then \ -+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ -+ fi; \ -+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ -+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ -+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ -+ fi; \ -+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ -+ else \ -+ test -f "$(distdir)/$$file" \ -+ || cp -p $$d/$$file "$(distdir)/$$file" \ -+ || exit 1; \ -+ fi; \ -+ done -+check-am: all-am -+check: check-am -+all-am: Makefile all-local -+installdirs: -+install: install-am -+install-exec: install-exec-am -+install-data: install-data-am -+uninstall: uninstall-am -+ -+install-am: all-am -+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am -+ -+installcheck: installcheck-am -+install-strip: -+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ -+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ -+ `test -z '$(STRIP)' || \ -+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install -+mostlyclean-generic: -+ -+clean-generic: -+ -+distclean-generic: -+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) -+ -+maintainer-clean-generic: -+ @echo "This command is intended for maintainers to use" -+ @echo "it deletes files that may require special tools to rebuild." -+clean: clean-am -+ -+clean-am: clean-generic clean-libtool clean-local mostlyclean-am -+ -+distclean: distclean-am -+ -rm -f Makefile -+distclean-am: clean-am distclean-generic -+ -+dvi: dvi-am -+ -+dvi-am: -+ -+html: html-am -+ -+html-am: -+ -+info: info-am -+ -+info-am: -+ -+install-data-am: -+ -+install-dvi: install-dvi-am -+ -+install-dvi-am: -+ -+install-exec-am: install-exec-local -+ -+install-html: install-html-am -+ -+install-html-am: -+ -+install-info: install-info-am -+ -+install-info-am: -+ -+install-man: -+ -+install-pdf: install-pdf-am -+ -+install-pdf-am: -+ -+install-ps: install-ps-am -+ -+install-ps-am: -+ -+installcheck-am: -+ -+maintainer-clean: maintainer-clean-am -+ -rm -f Makefile -+maintainer-clean-am: distclean-am maintainer-clean-generic -+ -+mostlyclean: mostlyclean-am -+ -+mostlyclean-am: mostlyclean-generic mostlyclean-libtool -+ -+pdf: pdf-am -+ -+pdf-am: -+ -+ps: ps-am -+ -+ps-am: -+ -+uninstall-am: -+ -+.MAKE: install-am install-strip -+ -+.PHONY: all all-am all-local check check-am clean clean-generic \ -+ clean-libtool clean-local distclean distclean-generic \ -+ distclean-libtool distdir dvi dvi-am html html-am info info-am \ -+ install install-am install-data install-data-am install-dvi \ -+ install-dvi-am install-exec install-exec-am install-exec-local \ -+ install-html install-html-am install-info install-info-am \ -+ install-man install-pdf install-pdf-am install-ps \ -+ install-ps-am install-strip installcheck installcheck-am \ -+ installdirs maintainer-clean maintainer-clean-generic \ -+ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ -+ ps ps-am uninstall uninstall-am -+ -+export XA_SRCDIR -+export XA_TOPSRCDIR -+export XA_ABSTOPSRCDIR -+ -+all-local: user-all-local -+ -+install-exec-local: user-install-local -+ -+clean-local: user-clean-local -+ -+user-all-local: -+ ${MAKE} ${_mcall} all; -+ -+# Have no user-install-data-local ATM -+user-install-local: user-install-exec-local -+ -+user-install-exec-local: -+ ${MAKE} ${_mcall} install; -+ -+user-clean-local: -+ ${MAKE} ${_mcall} clean; -+ -+# Tell versions [3.59,3.63) of GNU make to not export all variables. -+# Otherwise a system limit (for SysV at least) may be exceeded. -+.NOEXPORT: -+ ---- /dev/null -+++ b/extensions/LUA/Mbuild -@@ -0,0 +1,3 @@ -+# -*- Makefile -*- -+ -+obj-${build_LUA} += libxt_LUA.so ---- /dev/null -+++ b/extensions/LUA/nf_lua.c -@@ -0,0 +1,64 @@ -+#if defined(__KERNEL__) -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#endif -+ -+#include "lua.h" -+#include "lobject.h" /*sizeof(udata) */ -+#include "lauxlib.h" -+#include "controller.h" -+ -+#if defined(__KERNEL__) /* reachs until luaopen_nflib */ -+ -+ -+static int32_t nf_get_random(lua_State *L) -+{ -+ uint32_t rand = 0; -+ -+ get_random_bytes(&rand, sizeof(uint32_t )); -+ lua_pushnumber(L, rand); -+ return 1; -+} -+ -+static int32_t nf_get_time(lua_State *L) -+{ -+ lua_pushnumber(L, jiffies_to_msecs(jiffies_64)); -+ return 1; -+} -+ -+static const struct luaL_Reg nf_lua_lib_f [] = { -+ { "get_random", nf_get_random }, -+ { "get_time", nf_get_time }, -+ { NULL, NULL } -+}; -+ -+void luaopen_nflib(lua_State *L) -+{ -+ int32_t top; -+ -+ luaL_register(L, NETFILTER_LIB, nf_lua_lib_f); -+ lua_pop(L, 1); -+ -+ /* registering verdicts inside the _G */ -+ lua_getglobal(L, "_G"); -+ top = lua_gettop(L); -+ -+ lua_pushinteger(L, XT_CONTINUE); -+ lua_setfield(L, top, "XT_CONTINUE"); /* continiue with next rule */ -+ -+ lua_pushinteger(L, NF_DROP); -+ lua_setfield(L, top, "NF_DROP"); /* stop traversal in the current table hook and drop packet */ -+ -+ lua_pushinteger(L, NF_ACCEPT); -+ lua_setfield(L, top, "NF_ACCEPT"); /* stop traversal in the current table hook and accept packet */ -+ -+ lua_pop(L, 1); /* pop _G */ -+} -+ -+#endif ---- /dev/null -+++ b/extensions/LUA/prot_buf_dynamic.c -@@ -0,0 +1,486 @@ -+/* -+ * Copyright (C) 2010 University of Basel -+ * by Andre Graf -+ * -+ * This program 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. -+ * -+ * 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. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, see . -+ */ -+ -+#include "controller.h" -+ -+ -+ -+struct protocol_buf * dyn_prot_buf_array[MAX_NR_OF_DYN_PROT_BUFS] = { NULL }; -+ -+ -+/* LUA_API: the function 'field_dynamic_setter' acts as a wrapper around -+ * a given Lua field setter function of a dynamic protocol buffer. The -+ * string containing the lua function name was piggybacked in the 'set' -+ * member of the protocol_field. We call this function passing the actual -+ * segment as byte array and the set value. -+ * -+ * Paramters: -+ * 1. lua_packet_segment (implicit) -+ * 2. some lua value -+ * -+ * Upvalues: -+ * 1. pointer to the protocol buffer -+ * 2. field index -+ * -+ * Returns: -+ * 1. true or false if the 'set' was successful -+ */ -+int32_t field_dynamic_setter(lua_State *L) -+{ -+ size_t nbytes; -+ lua_packet_segment * array; -+ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); -+ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); -+ -+ int32_t field_index = lua_tointeger(L, lua_upvalueindex(2)); -+ -+ /* the function name is piggybacked as a string */ -+ lua_getglobal(L, (char *)prot_buf->protocol_fields[field_index].set); -+ if (!lua_isfunction(L, -1)) { -+ lua_pushboolean(L, 0); -+ return 1; -+ } -+ -+ nbytes = sizeof(lua_packet_segment) + seg->length * sizeof(uint8_t); -+ array = (lua_packet_segment *)lua_newuserdata(L, nbytes); -+ array->length = seg->length; -+ array->start = seg->start + seg->offset; -+ array->changes = NULL; -+ -+ luaL_getmetatable(L, LUA_BYTE_ARRAY); -+ lua_setmetatable(L, -2); -+ lua_pushvalue(L, 2); /* push value to set */ -+ if (lua_pcall(L, 2, 1, 0) != 0) { -+ pr_debug("Error: %s \n", lua_tostring(L, -1)); -+ lua_pop(L, 1); -+ lua_pushboolean(L, 0); -+ } -+ return 1; -+} -+ -+/* LUA_API: the function 'field_dynamic_getter' acts as a wrapper around -+ * a given Lua field getter function of a dynamic protocol buffer. The -+ * string containing the lua function name was piggybacked in the 'get' -+ * member of the protocol_field. We call this function passing the actual -+ * segment as byte array. -+ * -+ * Paramters: -+ * 1. lua_packet_segment (implicit) -+ * -+ * Upvalues: -+ * 1. pointer to the protocol buffer -+ * 2. field index -+ * -+ * Returns: -+ * 1. true or false if the 'get' was successful -+ */ -+int32_t field_dynamic_getter(lua_State *L) -+{ -+ size_t nbytes; -+ lua_packet_segment * array; -+ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); -+ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); -+ -+ int32_t field_index = lua_tointeger(L, lua_upvalueindex(2)); -+ -+ /* the function name is piggybacked as a string */ -+ lua_getglobal(L, (char *)prot_buf->protocol_fields[field_index].get); -+ if (!lua_isfunction(L, -1)) { -+ lua_pushboolean(L, 0); -+ return 1; -+ } -+ -+ nbytes = sizeof(lua_packet_segment) + seg->length * sizeof(uint8_t); -+ array = (lua_packet_segment *)lua_newuserdata(L, nbytes); -+ array->length = seg->length; -+ array->start = seg->start + seg->offset; -+ array->changes = NULL; -+ -+ luaL_getmetatable(L, LUA_BYTE_ARRAY); -+ lua_setmetatable(L, -2); -+ if (lua_pcall(L, 1, 1, 0) != 0) { -+ pr_debug("Error: %s \n", luaL_checkstring(L, -1)); -+ lua_pop(L, 1); -+ lua_pushboolean(L, 0); -+ } -+ return 1; -+} -+ -+/* LUA_API: the function 'has_protocol_dynamic' acts as a wrapper around -+ * a given lua has_protocol function of a dynamic protocol buffer. The -+ * string containing the lua function name was piggybacked in the 'has_protocol' -+ * member of the protocol_buffer. We call this function passing the actual -+ * segment. -+ * -+ * Paramters: -+ * 1. lua_packet_segment -+ * 2. protocol type -+ * -+ * Returns: -+ * 1. true or false if the payload field contains the given protocol -+ */ -+int32_t has_protocol_dynamic(lua_State *L, struct protocol_buf * prot_buf, lua_packet_segment * seg, int32_t type) -+{ -+ lua_packet_segment *seg_new; -+ int32_t res = 0; -+ -+ /* the function name is piggybacked as a string */ -+ lua_getglobal(L, (char *)prot_buf->has_protocol); -+ seg_new = (lua_packet_segment *)lua_newuserdata(L, sizeof(lua_packet_segment)); -+ seg_new->start = seg->start; -+ seg_new->offset = seg->offset; -+ seg_new->length = seg->length; -+ seg_new->changes = NULL; -+ luaL_getmetatable(L, prot_buf->name); -+ lua_setmetatable(L, -2); -+ lua_pushinteger(L, type); /* push the protocol type */ -+ if (lua_pcall(L, 2, 1, 0) != 0) { -+ pr_debug("Error: %s \n", luaL_checkstring(L, -1)); -+ lua_pop(L, 1); -+ return 0; -+ } -+ res = lua_toboolean(L, -1); -+ lua_pop(L, 1); -+ -+ return res; -+} -+ -+/* LUA_API: the function 'get_field_changes_dynamic' acts as a wrapper around -+ * a given lua get_field_changes function of a dynamic protocol buffer. The -+ * string containing the lua function name was piggybacked in the 'get_field_changes' -+ * member of the protocol_buffer. We call this function passing the actual -+ * segment. The lua function must return two lua table containing the offset -+ * and length changes (in bits). -+ * -+ * Paramters: -+ * 1. lua_packet_segment -+ * -+ * Returns: -+ * 1. new allocated field_changes struct -+ */ -+struct field_changes * get_field_changes_dynamic(lua_State *L, struct protocol_buf *prot_buf, lua_packet_segment * seg) -+{ -+ lua_packet_segment *seg_new; -+ struct field_changes * changes; -+ int32_t nr_of_changes, i; -+ -+ lua_getglobal(L, (char *)prot_buf->get_field_changes); -+ -+ seg_new = (lua_packet_segment *)lua_newuserdata(L, sizeof(lua_packet_segment)); -+ seg_new->start = seg->start; -+ seg_new->offset = seg->offset; -+ seg_new->length = seg->length; -+ seg_new->changes = NULL; -+ luaL_getmetatable(L, prot_buf->name); -+ lua_setmetatable(L, -2); -+ -+ if (lua_pcall(L, 1, 2, 0) != 0) -+ luaL_error(L, "inside get_field_changes_dynamic. %s\n", lua_tostring(L, -1)); -+ -+ /* the function call must return a table containing length changes */ -+ luaL_checktype(L, -1, LUA_TTABLE); -+ /* the function call must return a table containing offset changes */ -+ luaL_checktype(L, -2, LUA_TTABLE); -+ /* both tables have to be of same size */ -+ if (lua_objlen(L, -1) != lua_objlen(L, -2)) -+ luaL_error(L, "the provided tables are not of equal size"); -+ -+ nr_of_changes = lua_objlen(L, -1); -+ changes = get_allocated_field_changes(L, nr_of_changes); -+ -+ /* loop over the tables */ -+ for (i = 1; i < nr_of_changes; i++) { -+ lua_rawgeti(L, -1, i); /* push length value of field at index i */ -+ changes->field_length_changes[i - 1] = luaL_checkinteger(L, -1); -+ lua_pop(L, 1); /* pop offset value */ -+ -+ lua_rawgeti(L, -2, i); /* push offset value of field at index i */ -+ changes->field_offset_changes[i - 1] = luaL_checkinteger(L, -1); -+ lua_pop(L, 1); /* pop length value */ -+ } -+ -+ /* pop both tables */ -+ lua_pop(L, 2); -+ -+ return changes; -+} -+ -+/* C_INT: 'get_free_protocol_index' is only used internally. This function -+ * gets a free slot inside the array holding all the protocol buffers. -+ * There are several ways to get to this information. In this case I take -+ * the way over the reflected array SUPPORTED_PROTOCOL_TABLE inside the -+ * Lua state. Since this function is called at laodtime, we do not have -+ * to care about performance. -+ */ -+static int32_t get_free_protocol_index(lua_State *L) -+{ -+ int32_t protocol_index; -+ -+ lua_getglobal(L, SUPPORTED_PROTOCOL_TABLE); -+ protocol_index = lua_objlen(L, -1) + 1; -+ lua_pop(L, 1); -+ return protocol_index; -+} -+ -+/* C_API: 'free_dynamic_prot_buf' frees the allocated memory of a given -+ * dynamic protocol buffer. this function is normally called inside a -+ * cleanup routine. Be aware, before running this function you must be -+ * sure that no references to the dynamic protocol buffers were available. -+ * It's recomended to close the Lua state before calling the function. */ -+void free_dynamic_prot_buf(struct protocol_buf * prot_buf) -+{ -+ struct protocol_field * field = prot_buf->protocol_fields; -+ -+ for (; field->name != NULL; field++) { -+ if (field->get) kfree(field->get); -+ if (field->set) kfree(field->set); -+ if (field->name) kfree((char *)field->name); -+ } -+ -+ if (prot_buf->payload_field) kfree(prot_buf->payload_field); -+ if (prot_buf->has_protocol) kfree(prot_buf->has_protocol); -+ -+ if (prot_buf->get_field_changes) kfree(prot_buf->get_field_changes); -+ kfree((char *)prot_buf->name); -+ kfree(prot_buf); -+ return; -+} -+ -+void cleanup_dynamic_prot_bufs(void) -+{ -+ int32_t i; -+ -+ for (i = 0; i < MAX_NR_OF_DYN_PROT_BUFS; i++) { -+ if (dyn_prot_buf_array[i]) { -+ free_dynamic_prot_buf(dyn_prot_buf_array[i]); -+ dyn_prot_buf_array[i] = NULL; -+ } -+ } -+ return; -+} -+ -+ -+/* C_INT: 'free_protocol_fields' is used internally as a helper function for -+ * 'register_dynamic_protbuf'. It is used when durin registration an error -+ * occurs and the afore allocated fields needed to be freed. */ -+static inline void free_protocol_fields(struct protocol_field * prot_fields, int32_t i) -+{ -+ struct protocol_field * f; -+ -+ while (i >= 0) { -+ f = &prot_fields[i]; -+ if (f->name) kfree((void *)f->name); -+ if (f->get) kfree((void *)f->get); -+ if (f->set) kfree((void *)f->set); -+ kfree((void *)f); -+ i--; -+ } -+} -+ -+/* LUA_API: 'register_dynamic_protbuf' is called from within the Lua script. -+ * it takes a Lua table representing the dynamic protocol buffer as parameter. -+ * e.g.: -+ * eth_prot_buf = { -+ * name = "packet_eth_dyn", -+ * payload_field = "data", -+ * protocol_fields = { -+ * {"dmac", 0, 48, nil, nil }, -+ * {"smac", 48, 48, nil, nil }, -+ * {"type", 96, 16, nil, nil }, -+ * {"data", 112, 0, nil, nil }, -+ * }, -+ * has_protocol = "eth_dyn_has_protocol", -+ * get_field_changes = "eth_dyn_get_field_changes" -+ * } -+ * register_dynamic_protbuf(eth_prot_buf) -+ * -+ * the table gets parsed and a new protocol_buf struct is allocated and -+ * initialized using 'register_protbuf', which is also used for the static -+ * protocol buffers. This enables an identical behavior like the static -+ * protocol buffers. The dynamic protocol buffers are not garbage collected, -+ * use 'free_dynamic_protbuf' to free them after closing the Lua state. -+ */ -+static int32_t register_dynamic_protbuf(lua_State *L) -+{ -+ struct protocol_buf *prot_buf; -+ struct protocol_field *field, sentinel = PROT_FIELD_SENTINEL; -+ int32_t nr_of_fields, i; -+ -+ prot_buf = (struct protocol_buf *)kmalloc(sizeof(struct protocol_buf), GFP_KERNEL); -+ prot_buf->is_dynamic = 1; -+ -+ /* check if parameter is a table */ -+ luaL_checktype(L, 1, LUA_TTABLE); -+ -+ /* initialize prot_buf.name */ -+ lua_getfield(L, 1, "name"); -+ prot_buf->name = kmalloc(lua_objlen(L, -1), GFP_KERNEL); -+ strcpy((char *)prot_buf->name, luaL_checkstring(L, -1)); -+ lua_pop(L, 1); /* pop res from lua_getfield */ -+ -+ /* check if protocol buffer is already registered */ -+ lua_getglobal(L, prot_buf->name); -+ if (!lua_isnil(L, -1)) { -+ lua_pop(L, 1); /* pop res from lua_getglobal */ -+ pr_debug("protocol_buf '%s' already registered.\n", prot_buf->name); -+ goto free_prot_buf; -+ } -+ lua_pop(L, 1); /* pop res from lua_getglobal */ -+ -+ /* initialize payload field */ -+ lua_getfield(L, 1, "payload_field"); -+ if (lua_isstring(L, -1)) { -+ prot_buf->payload_field = kmalloc(lua_objlen(L, -1), GFP_KERNEL); -+ strcpy(prot_buf->payload_field, lua_tostring(L, -1)); -+ }else -+ prot_buf->payload_field = NULL; -+ lua_pop(L, 1); /* pop res from lua_getfield */ -+ -+ /* initialize protocol_fields field*/ -+ lua_getfield(L, 1, "protocol_fields"); -+ if (!lua_istable(L, -1)) { -+ pr_debug("invalid protocol_fields table.\n"); -+ goto err2; -+ -+ } -+ -+ nr_of_fields = lua_objlen(L, -1); -+ prot_buf->protocol_fields = (struct protocol_field *)kmalloc((nr_of_fields + 1) * sizeof(struct protocol_field), GFP_KERNEL); -+ -+ for (i = 1; i <= nr_of_fields; i++) { -+ field = &prot_buf->protocol_fields[i - 1]; -+ /* initialize protocol field */ -+ lua_rawgeti(L, -1, i); /* push field-table */ -+ if (!lua_istable(L, -1)) { -+ free_protocol_fields(prot_buf->protocol_fields, i); -+ pr_debug("invalid protocol_field at %i.\n", i); -+ goto err; -+ } -+ -+ /* initialize protocol field name */ -+ lua_rawgeti(L, -1, 1); -+ if (!lua_isstring(L, -1)) { -+ free_protocol_fields(prot_buf->protocol_fields, i); -+ pr_debug("invalid protocol_field name at %i.\n", i); -+ goto err; -+ } -+ -+ field->name = kmalloc(lua_objlen(L, -1), GFP_KERNEL); -+ strcpy((char*)field->name, lua_tostring(L, -1)); -+ lua_pop(L, 1); /* pop field name */ -+ -+ /* initialize protocol field offset */ -+ lua_rawgeti(L, -1, 2); -+ if (!lua_isnumber(L, -1)) { -+ free_protocol_fields(prot_buf->protocol_fields, i); -+ pr_debug("invalid protocol_field offset at %i.\n", i); -+ goto err; -+ } -+ field->offset = lua_tointeger(L, -1); -+ lua_pop(L, 1); /* pop field offset */ -+ -+ /* initialize protocol field length */ -+ lua_rawgeti(L, -1, 3); -+ if (!lua_isnumber(L, -1)) { -+ free_protocol_fields(prot_buf->protocol_fields, i); -+ pr_debug("invalid protocol_field length at %i.\n", i); -+ goto err; -+ } -+ field->length = lua_tointeger(L, -1); -+ lua_pop(L, 1); /* pop field length */ -+ -+ /* initialize protocol field getter */ -+ lua_rawgeti(L, -1, 4); -+ if (lua_isstring(L, -1)) { -+ field->get = kmalloc(lua_objlen(L, -1), GFP_KERNEL); -+ strcpy((char *)field->get, lua_tostring(L, -1)); /* the get-wrapper knows about the piggybacked string */ -+ }else -+ field->get = NULL; -+ lua_pop(L, 1); /* pop field getter */ -+ -+ /* initialize protocol field setter */ -+ lua_rawgeti(L, -1, 5); -+ if (lua_isstring(L, -1)) { -+ field->set = kmalloc(lua_objlen(L, -1), GFP_KERNEL); -+ strcpy((char *)field->set, lua_tostring(L, -1)); /* the set-wrapper knows about the piggybacked string */ -+ }else -+ field->set = NULL; -+ lua_pop(L, 1); /* pop field setter */ -+ -+ /* field initialization completed */ -+ lua_pop(L, 1); /* pop field-table */ -+ } -+ -+ /* put sentinel at the end of protocol_fields */ -+ memcpy(&prot_buf->protocol_fields[nr_of_fields], &sentinel, sizeof(sentinel)); -+ lua_pop(L, 1); /* pop protocol-fields-table */ -+ -+ /* initialize has_protocol field */ -+ lua_getfield(L, 1, "has_protocol"); -+ if (lua_isstring(L, -1)) { -+ prot_buf->has_protocol = kmalloc(lua_objlen(L, -1), GFP_KERNEL); -+ strcpy((char *)prot_buf->has_protocol, lua_tostring(L, -1)); /* the has_protocol-wrapper knows about the piggybacked string */ -+ }else -+ prot_buf->has_protocol = NULL; -+ lua_pop(L, 1); /* pop has_protocol */ -+ -+ /* initialize get_field_changes field */ -+ lua_getfield(L, 1, "get_field_changes"); -+ if (lua_isstring(L, -1)) { -+ prot_buf->get_field_changes = kmalloc(lua_objlen(L, -1), GFP_KERNEL); -+ strcpy((char *)prot_buf->get_field_changes, lua_tostring(L, -1)); /* the get_field_changes-wrapper knows about the piggybacked string */ -+ }else -+ prot_buf->get_field_changes = NULL; -+ lua_pop(L, 1); /* pop get_field_changes */ -+ -+ /* Storing the pointer to the DYNAMIC protbuf within dyn_prot_buf_array, in order to free it at cleanup */ -+ for (i = 0; i < MAX_NR_OF_DYN_PROT_BUFS; i++) { -+ if (!dyn_prot_buf_array[i]) { -+ dyn_prot_buf_array[i] = prot_buf; -+ break; -+ }else -+ goto err; -+ } -+ -+ /* call the "common" register_protbuf */ -+ register_protbuf(L, prot_buf, get_free_protocol_index(L)); /* register prot_buf as it is done with the static ones */ -+ -+ return 0; -+ -+err: -+ kfree(prot_buf->protocol_fields); -+err2: -+ if (prot_buf->payload_field) kfree(prot_buf->payload_field); -+free_prot_buf: -+ kfree((void *)prot_buf->name); -+ kfree(prot_buf); -+ -+ luaL_error(L, "one or more error happend while registering a dynamic protocol buffer, please consult the debug log"); -+ -+ return 0; -+ -+} -+ -+void luaopen_protbuf_dynamic(lua_State *L) -+{ -+ lua_getglobal(L, "_G"); -+ lua_pushcclosure(L, register_dynamic_protbuf, 0); -+ lua_setfield(L, -2, "register_dynamic_protbuf"); -+ lua_pop(L, 1); /* pop _G */ -+ return; -+} ---- /dev/null -+++ b/extensions/LUA/prot_buf_ethernet.c -@@ -0,0 +1,60 @@ -+/* -+ * Copyright (C) 2010 University of Basel -+ * by Andre Graf -+ * -+ * This program 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. -+ * -+ * 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. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, see . -+ */ -+ -+#include "controller.h" -+ -+ -+static int32_t eth_has_protocol(lua_State *L, struct protocol_buf * prot_buf, lua_packet_segment * seg, int32_t protocol_type) -+{ -+ uint8_t *embedded_protocol = seg->start + seg->offset + 12 /*bytes*/; -+ unsigned short res = (unsigned short)((embedded_protocol[1] << CHAR_BIT) | (embedded_protocol[0] << CHAR_BIT)); -+ -+ switch (res) { -+ case 0x0800: /* 1: Internet Protocol (IP) */ -+ if (protocol_type == PACKET_IP) return 1; -+ break; -+ default: -+ return 0; -+ } -+ -+ return 0; -+} -+ -+static const struct protocol_field eth_protocol_fields[] = { -+ /* field name offset length getter setter */ -+ { "dmac", 0, 48, NULL, NULL }, -+ { "smac", 48, 48, NULL, NULL }, -+ { "type", 96, 16, NULL, NULL }, -+ { "data", 112, 0, NULL, NULL }, -+ PROT_FIELD_SENTINEL, -+}; -+ -+static const struct protocol_buf eth_protocol_buf = { -+ .is_dynamic = 0, -+ .name = LUA_PACKET_SEG_ETH, -+ .payload_field = "data", -+ .protocol_fields = (struct protocol_field *)ð_protocol_fields, -+ .has_protocol = ð_has_protocol, -+ .get_field_changes = NULL, -+}; -+ -+ -+void luaopen_protbuf_eth(lua_State *L) -+{ -+ register_protbuf(L, (struct protocol_buf *)ð_protocol_buf, PACKET_ETH); -+} ---- /dev/null -+++ b/extensions/LUA/prot_buf_helpers.c -@@ -0,0 +1,216 @@ -+/* -+ * Copyright (C) 2010 University of Basel -+ * by Andre Graf -+ * -+ * This program 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. -+ * -+ * 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. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, see . -+ */ -+ -+#if defined(__KERNEL__) -+#include -+#include /* kmalloc */ -+#endif -+ -+#include "controller.h" -+ -+int32_t get_header_size(struct protocol_buf * prot_buf) -+{ -+ int32_t bit_counter = 0; -+ struct protocol_field * field = prot_buf->protocol_fields; -+ -+ for (; field->name; field++) -+ bit_counter += field->length; -+ -+ return bit_counter >> 3; -+} -+ -+ -+int32_t set_32_bit_generic(lua_State *L) -+{ -+ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); -+ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); -+ -+ *(uint32_t *)(seg->start + seg->offset) = (uint32_t )htonl(luaL_checkinteger(L, 2)); -+ return 0; -+} -+int32_t get_32_bit_generic(lua_State *L) -+{ -+ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); -+ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); -+ -+ lua_pushinteger(L, ntohl(*((uint32_t *)(seg->start + seg->offset)))); -+ return 1; -+} -+ -+int32_t set_16_bit_generic(lua_State *L) -+{ -+ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); -+ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); -+ -+ *(uint16_t *)(seg->start + seg->offset) = (uint16_t)htons(luaL_checkinteger(L, 2)); -+ return 0; -+} -+int32_t get_16_bit_generic(lua_State *L) -+{ -+ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); -+ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); -+ -+ lua_pushinteger(L, ntohs(*((uint16_t *)(seg->start + seg->offset)))); -+ return 1; -+} -+ -+int32_t set_lower_4_bit_generic(lua_State *L) -+{ -+ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); -+ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); -+ uint8_t b = (uint8_t)luaL_checkinteger(L, 2) << 4; -+ uint8_t * pos = (uint8_t *)(seg->start + seg->offset); -+ -+ *pos &= 0x0F; /* reset lower 4 bits*/ -+ *pos |= b; -+ -+ return 0; -+} -+ -+int32_t get_lower_4_bit_generic(lua_State *L) -+{ -+ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); -+ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); -+ -+ lua_pushinteger(L, (*(uint8_t *)(seg->start + seg->offset)) >> 4); -+ return 1; -+} -+ -+int32_t set_upper_4_bit_generic(lua_State *L) -+{ -+ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); -+ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); -+ uint8_t b = (uint8_t)luaL_checkinteger(L, 2) << 4; -+ uint8_t * pos = (uint8_t *)(seg->start + seg->offset); -+ -+ *pos &= 0xF0; /* reset upper 4 bits*/ -+ *pos |= (b >> 4); -+ -+ return 0; -+} -+ -+int32_t get_upper_4_bit_generic(lua_State *L) -+{ -+ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); -+ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); -+ -+ lua_pushinteger(L, (*(uint8_t *)(seg->start + seg->offset)) & 0x0F); -+ return 1; -+} -+ -+ -+int32_t set_8_bit_generic(lua_State *L) -+{ -+ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); -+ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); -+ -+ *(uint8_t *)(seg->start + seg->offset) = (uint8_t)luaL_checkinteger(L, 2); -+ return 0; -+} -+ -+int32_t get_8_bit_generic(lua_State *L) -+{ -+ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); -+ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); -+ -+ lua_pushinteger(L, *(uint8_t *)(seg->start + seg->offset)); -+ return 1; -+} -+ -+int32_t set_1_bit_generic(lua_State *L) -+{ -+ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); -+ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); -+ unsigned long l = 0; -+ -+ memcpy(&l, (seg->start + seg->offset), seg->length); -+ l |= (1 << ((CHAR_BIT * seg->length) - luaL_checkinteger(L, 2))); -+ memcpy((seg->start + seg->offset), &l, seg->length); -+ -+ return 0; -+} -+ -+int32_t get_1_bit_generic(lua_State *L) -+{ -+ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); -+ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); -+ unsigned long l = 0; -+ uint32_t bit = 0; -+ -+ memcpy(&l, (seg->start + seg->offset), seg->length); -+ bit = l & (1 << ((CHAR_BIT * seg->length) - luaL_checkinteger(L, 2))); -+ -+ lua_pushboolean(L, bit); -+ return 1; -+} -+ -+int32_t get_string_generic(lua_State *L) -+{ -+ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); -+ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); -+ -+ /* Warning we cast from uchar to char */ -+ lua_pushlstring(L, (char *)seg->start + seg->offset, seg->length); -+ return 1; -+} -+ -+int32_t set_data_generic(lua_State *L) -+{ -+ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); -+ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); -+ lua_packet_segment * data = checkbytearray(L, 2); -+ -+ pr_debug("seg->length %u, data->length %u\n", seg->length, data->length); -+ -+ if (seg->length >= data->length) -+ memcpy((seg->start + seg->offset), data->start, data->length); -+ else -+ luaL_error(L, "provided byte array too big for given packet segment"); -+ return 0; -+} -+ -+struct field_changes * get_allocated_field_changes(lua_State *L, int32_t nr_of_fields) -+{ -+ struct field_changes * changes; -+ -+ changes = kmalloc(sizeof(struct field_changes), GFP_ATOMIC); -+ -+ if (!changes) -+ goto failure; -+ -+ changes->field_length_changes = kmalloc(nr_of_fields * sizeof(int), GFP_ATOMIC); -+ if (!changes->field_length_changes) -+ goto free1; -+ -+ changes->field_offset_changes = kmalloc(nr_of_fields * sizeof(int), GFP_ATOMIC); -+ if (!changes->field_offset_changes) -+ goto free2; -+ -+ memset(changes->field_length_changes, 0, nr_of_fields * sizeof(int)); -+ memset(changes->field_offset_changes, 0, nr_of_fields * sizeof(int)); -+ -+ changes->ref_count = 1; -+ -+ return changes; -+ -+free2: kfree(changes->field_length_changes); -+free1: kfree(changes); -+failure: -+ if (!changes) luaL_error(L, "couldnt allocate memory inside 'get_allocated_field_changes'"); -+ return NULL; /* only to omit warnings */ -+} -\ No newline at end of file ---- /dev/null -+++ b/extensions/LUA/prot_buf_icmp.c -@@ -0,0 +1,49 @@ -+/* -+ * Copyright (C) 2010 University of Basel -+ * by Andre Graf -+ * -+ * This program 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. -+ * -+ * 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. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, see . -+ */ -+ -+#include "controller.h" -+ -+static int32_t icmp_has_protocol(lua_State *L, struct protocol_buf * prot_buf, lua_packet_segment * seg, int32_t protocol_type) -+{ -+ return 0; -+} -+ -+static const struct protocol_field icmp_protocol_fields[] = { -+ /* field name offset length getter setter */ -+ { "type", 0, 8, NULL, NULL }, -+ { "code", 8, 8, NULL, NULL }, -+ { "checksum", 16, 16, NULL, NULL }, -+ { "id", 32, 16, NULL, NULL }, -+ { "sequence", 48, 16, NULL, NULL }, -+ PROT_FIELD_SENTINEL, -+}; -+ -+static const struct protocol_buf icmp_protocol_buf = { -+ .is_dynamic = 0, -+ .name = LUA_PACKET_SEG_ICMP, -+ .payload_field = NULL, -+ .protocol_fields = (struct protocol_field *)&icmp_protocol_fields, -+ .has_protocol = &icmp_has_protocol, -+ .get_field_changes = NULL, -+}; -+ -+void luaopen_protbuf_icmp(lua_State *L) -+{ -+ register_protbuf(L, (struct protocol_buf *)&icmp_protocol_buf, PACKET_ICMP); -+} -+ ---- /dev/null -+++ b/extensions/LUA/prot_buf_ip.c -@@ -0,0 +1,209 @@ -+/* -+ * Copyright (C) 2010 University of Basel -+ * by Andre Graf -+ * -+ * This program 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. -+ * -+ * 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. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, see . -+ */ -+ -+#if defined(__KERNEL__) -+ #include -+ #include -+#endif -+ -+#include "controller.h" -+ -+ -+#define IP_FMT "%u.%u.%u.%u" -+#define IP_ACC(buf) buf[0], buf[1], buf[2], buf[3] -+ -+ -+static int32_t ip_version_set(lua_State *L) -+{ -+ uint8_t version_checked; -+ lua_packet_segment * seg = checkpacketseg(L, 1, LUA_PACKET_SEG_IP); -+ uint8_t *version_seg = seg->start + seg->offset; -+ int32_t version = luaL_checkinteger(L, 2); -+ -+ luaL_argcheck(L, version >= 0 && version <= 15, 1, "version number invalid"); -+ -+ version_checked = (uint8_t)version; -+ -+ version_seg[0] &= (uint8_t)0x0F; /* reset version bits */ -+ version_seg[0] |= version_checked << 4; -+ -+ return 0; -+} -+static int32_t ip_version_get(lua_State *L) -+{ -+ lua_packet_segment * seg = checkpacketseg(L, 1, LUA_PACKET_SEG_IP); -+ uint8_t *version_seg = seg->start + seg->offset; -+ uint8_t v = version_seg[0] & 0xF0; -+ -+ v >>= 4; -+ -+ lua_pushinteger(L, v); -+ return 1; -+} -+ -+static int32_t ip_ihl_set(lua_State *L) -+{ -+ uint8_t ihl_checked; -+ lua_packet_segment * seg = checkpacketseg(L, 1, LUA_PACKET_SEG_IP); -+ uint8_t *ihl_seg = seg->start + seg->offset; -+ int32_t ihl = luaL_checkinteger(L, 2); -+ -+ luaL_argcheck(L, ihl >= 5 && ihl <= 15, 1, "ip header length invalid"); // RFC 791 5x32 = 160 bits -+ -+ ihl_checked = (uint8_t)ihl; -+ -+ ihl_seg[0] &= (uint8_t)0xF0; /* reset ihl bits */ -+ ihl_seg[0] |= ihl_checked; -+ -+ return 0; -+} -+static int32_t ip_ihl_get(lua_State *L) -+{ -+ lua_packet_segment * seg = checkpacketseg(L, 1, LUA_PACKET_SEG_IP); -+ uint8_t *ihl_seg = seg->start + seg->offset; -+ uint8_t v = ihl_seg[0] & 0x0F; -+ -+ lua_pushinteger(L, v); -+ return 1; -+} -+ -+static int32_t ip_addr_set(lua_State *L) -+{ -+ int32_t field_id = lua_tointeger(L, lua_upvalueindex(2)); -+ lua_packet_segment * seg = checkpacketseg(L, 1, LUA_PACKET_SEG_IP); -+ uint8_t *addr_seg = seg->start + seg->offset; -+ uint32_t old_addr; -+ char *ip = (char *)luaL_checkstring(L, 2); -+ uint32_t a, b, c, d; -+ struct sk_buff * skb = (struct sk_buff *)lua_touserdata(L, 3); -+ -+ /* for tcp / udp checksumming*/ -+ uint32_t prot_offset; -+ uint8_t *check, *protocol_seg; -+ -+ /* end */ -+ -+ sscanf(ip, IP_FMT, &a, &b, &c, &d); -+ -+ luaL_argcheck(L, a < 256 && b < 256 && c < 256 && d < 256, 1, "invalid ip addr"); -+ -+ old_addr = *((uint32_t *)addr_seg); -+ addr_seg[0] = (uint8_t)a; -+ addr_seg[1] = (uint8_t)b; -+ addr_seg[2] = (uint8_t)c; -+ addr_seg[3] = (uint8_t)d; -+ -+#if defined(__KERNEL__) -+ if (old_addr != *(uint32_t *)addr_seg) { -+ int32_t offset = (field_id == 10) ? -2 : -6; /* offset from saddr or daddr */ -+ -+ csum_replace4((uint16_t *)(addr_seg + offset), old_addr, *(uint32_t *)addr_seg); -+ -+ prot_offset = (field_id == 10) ? -3 : -7; /* offset from saddr or daddr */ -+ protocol_seg = seg->start + seg->offset + prot_offset; -+ -+ if (skb && (protocol_seg[0] == 0x06 || protocol_seg[0] == 0x11)) { /* is payload TCP or UDP ? */ -+ -+ check = seg->start + seg->offset; /* tmp res */ -+ check += (field_id == 10) ? 8 : 16; /* the start of the payload, depending saddr or daddr */ -+ check += (protocol_seg[0] == 0x06) ? 16 : 6; /* the start of the checksum, depending on TCP or UDP */ -+ -+ inet_proto_csum_replace4((__sum16 *)check, skb, old_addr, *(uint32_t *)addr_seg, 1); -+ -+ lua_pop(L, 1); -+ } -+ } -+#endif -+ return 0; -+} -+ -+ -+ -+ -+ -+static int32_t ip_addr_get(lua_State *L) -+{ -+ lua_packet_segment * seg = checkpacketseg(L, 1, LUA_PACKET_SEG_IP); -+ uint8_t *addr_seg = seg->start + seg->offset; -+ -+ char buf[16]; /*max: 255.255.255.255\0 --> 16 chars */ -+ -+ sprintf(buf, IP_FMT, IP_ACC(addr_seg)); -+ lua_pushstring(L, buf); -+ return 1; -+} -+ -+static int32_t ip_has_protocol(lua_State *L, struct protocol_buf * prot_buf, lua_packet_segment * seg, int32_t protocol_type) -+{ -+ uint8_t * embedded_protocol = seg->start + seg->offset + 9 /*bytes*/; -+ -+ switch (embedded_protocol[0]) { -+ case 0x01: /* 1: Internet Control Message Protocol (ICMP) */ -+ if (protocol_type == PACKET_ICMP) return 1; -+ break; -+ case 0x02: /* 2: Internet Group Management Protocol (IGMP) */ -+ break; -+ case 0x06: /* 6: Transmission Control Protocol (TCP) */ -+ if (protocol_type == PACKET_TCP) return 1; -+ break; -+ case 0x11: /* 17: User Datagram Protocol (UDP) */ -+ if (protocol_type == PACKET_UDP) return 1; -+ break; -+ case 0x59: /* 89: Open Shortest Path First (OSPF) */ -+ break; -+ case 0x84: /* 132: Stream Control Transmission Protocol (SCTP) */ -+ break; -+ default: -+ break; -+ } -+ -+ return 0; -+} -+ -+static const struct protocol_field ip_protocol_fields[] = { -+ /* field name offset length getter setter */ -+ { "version", 0, 4, ip_version_get, ip_version_set }, -+ { "ihl", 4, 4, ip_ihl_get, ip_ihl_set }, -+ { "tos", 8, 8, get_8_bit_generic, set_8_bit_generic }, -+ { "tot_len", 16, 16, get_16_bit_generic, set_16_bit_generic }, -+ { "id", 32, 16, get_16_bit_generic, set_16_bit_generic }, -+ { "flags", 48, 3, get_1_bit_generic, set_1_bit_generic }, -+ { "frag_off", 51, 13, NULL, NULL }, -+ { "ttl", 64, 8, get_8_bit_generic, set_8_bit_generic }, -+ { "protocol", 72, 8, get_8_bit_generic, set_8_bit_generic }, -+ { "check", 80, 16, get_16_bit_generic, set_16_bit_generic }, -+ { "saddr", 96, 32, ip_addr_get, ip_addr_set }, -+ { "daddr", 128, 32, ip_addr_get, ip_addr_set }, -+ { "data", 160, 0, NULL, set_data_generic }, -+ PROT_FIELD_SENTINEL, -+}; -+ -+static const struct protocol_buf ip_protocol_buf = { -+ .is_dynamic = 0, -+ .name = LUA_PACKET_SEG_IP, -+ .payload_field = "data", -+ .protocol_fields = (struct protocol_field *)&ip_protocol_fields, -+ .has_protocol = &ip_has_protocol, -+ .get_field_changes = NULL, -+}; -+ -+void luaopen_protbuf_ip(lua_State *L) -+{ -+ register_protbuf(L, (struct protocol_buf *)&ip_protocol_buf, PACKET_IP); -+} -+ ---- /dev/null -+++ b/extensions/LUA/prot_buf_raw.c -@@ -0,0 +1,43 @@ -+/* -+ * Copyright (C) 2010 University of Basel -+ * by Andre Graf -+ * -+ * This program 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. -+ * -+ * 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. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, see . -+ */ -+ -+#include "controller.h" -+static int32_t raw_has_protocol(lua_State *L, struct protocol_buf * prot_buf, lua_packet_segment * seg, int32_t protocol_type) -+{ -+ return 1; -+} -+ -+static const struct protocol_field raw_protocol_fields[] = { -+ /* field name offset length getter setter */ -+ { "data", 0, 0, NULL, NULL }, -+ PROT_FIELD_SENTINEL, -+}; -+ -+static const struct protocol_buf raw_protocol_buf = { -+ .is_dynamic = 0, -+ .name = LUA_PACKET_SEG_RAW, -+ .payload_field = "data", -+ .protocol_fields = (struct protocol_field *)&raw_protocol_fields, -+ .has_protocol = &raw_has_protocol, -+ .get_field_changes = NULL, -+}; -+ -+void luaopen_protbuf_raw(lua_State *L) -+{ -+ register_protbuf(L, (struct protocol_buf *)&raw_protocol_buf, PACKET_RAW); -+} ---- /dev/null -+++ b/extensions/LUA/prot_buf_tcp.c -@@ -0,0 +1,188 @@ -+/* -+ * Copyright (C) 2010 University of Basel -+ * by Andre Graf -+ * -+ * This program 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. -+ * -+ * 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. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, see . -+ */ -+ -+#if defined(__KERNEL__) -+ #include -+ #include -+#endif -+#include "controller.h" -+ -+ -+static int32_t tcp_has_protocol(lua_State *L, struct protocol_buf * prot_buf, lua_packet_segment * seg, int32_t protocol_type) -+{ -+ return 1; -+} -+ -+static int32_t tcp_set_checksum(lua_State *L) -+{ -+ struct protocol_buf * prot_buf = (struct protocol_buf *)lua_topointer(L, lua_upvalueindex(1)); -+ lua_packet_segment * seg = checkpacketseg(L, 1, prot_buf->name); -+ -+#if defined(__KERNEL__) -+ uint8_t * check_seg = seg->start + seg->offset; -+ uint8_t * tcp_hdr = check_seg - 16; -+ uint8_t * saddr = tcp_hdr - 8; -+ uint8_t * daddr = saddr + 4; -+ uint32_t len = 20 + (seg->changes->field_length_changes[11] / 8) + (seg->changes->field_length_changes[10] / 8); -+ unsigned short checksum = tcp_v4_check(len, *(uint32_t *)saddr, *(uint32_t *)daddr, -+ csum_partial(tcp_hdr, len, 0)); -+ -+ memcpy(check_seg, &checksum, sizeof(unsigned short)); -+#endif -+ return 0; -+} -+ -+ -+static const struct protocol_field tcp_protocol_fields[] = { -+ /* field name offset length getter setter */ -+ { "sport", 0, 16, get_16_bit_generic, set_16_bit_generic }, -+ { "dport", 16, 16, get_16_bit_generic, set_16_bit_generic }, -+ { "seq", 32, 32, get_32_bit_generic, set_32_bit_generic }, -+ { "ack", 64, 32, get_32_bit_generic, set_32_bit_generic }, -+ { "data_off", 96, 4, get_lower_4_bit_generic, set_lower_4_bit_generic }, -+ { "reserved", 100, 4, get_upper_4_bit_generic, set_upper_4_bit_generic }, -+ { "flags", 104, 8, get_1_bit_generic, set_1_bit_generic }, -+ { "window_size", 112, 16, get_16_bit_generic, set_16_bit_generic }, -+ { "check", 128, 16, get_16_bit_generic, tcp_set_checksum }, -+ { "urgent", 144, 16, NULL, NULL }, -+ { "options", 160, 0, NULL, set_data_generic }, -+ { "data", 160, 0, NULL, set_data_generic }, /* begin of data depends on options */ -+ PROT_FIELD_SENTINEL, -+}; -+ -+ -+static const struct protocol_field tcp_options_and_data[] = { -+ /* field name offset length getter setter */ -+ { "MSS", 0, 16, get_16_bit_generic, set_16_bit_generic }, -+ { "WS", 0, 8, get_8_bit_generic, set_8_bit_generic }, -+ { "SACK", 0, 16, get_16_bit_generic, set_16_bit_generic }, -+ { "TSVAL", 0, 32, get_32_bit_generic, set_32_bit_generic }, -+ { "TSER", 0, 32, get_32_bit_generic, set_32_bit_generic }, -+ PROT_FIELD_SENTINEL, -+}; -+ -+ -+static struct field_changes * tcp_get_field_changes(lua_State *L, lua_packet_segment * seg); -+ -+static const struct protocol_buf tcp_protocol_buf = { -+ .is_dynamic = 0, -+ .name = LUA_PACKET_SEG_TCP, -+ .payload_field = "data", -+ .protocol_fields = (struct protocol_field *)&tcp_protocol_fields, -+ .has_protocol = &tcp_has_protocol, -+ .get_field_changes = &tcp_get_field_changes, -+}; -+ -+ -+static struct field_changes * tcp_options_get_field_changes(lua_State *L, lua_packet_segment * seg); -+ -+static const struct protocol_buf tcp_options_and_data_buf = { -+ .is_dynamic = 0, -+ .name = LUA_PACKET_SEG_TCP_OPT, -+ .payload_field = NULL, -+ .protocol_fields = (struct protocol_field *)&tcp_options_and_data, -+ .has_protocol = NULL, -+ .get_field_changes = &tcp_options_get_field_changes, -+}; -+ -+struct field_changes * tcp_get_field_changes(lua_State *L, lua_packet_segment * seg) -+{ -+ /* depending on the value stored inside the 'data_off'-field, the length of -+ * the 'options' field has to be changed, as well as the length and offset -+ * of the 'data' field */ -+ uint8_t *tcp_hdr = seg->start + seg->offset; -+ -+ /* get the pointer to the 'data_off' field */ -+ uint8_t * data_off_field = tcp_hdr + 12; /* 12 bytes offset */ -+ /* extract the stored header length in bits */ -+ uint32_t tcp_hdr_len = ((*(uint8_t *)data_off_field) >> 4) * 32; -+ -+ /* get an allocated 'field_changes' structure */ -+ struct field_changes * changes = get_allocated_field_changes(L, 12); -+ -+ /* depending on the tcp header length, change the length of the options*/ -+ changes->field_length_changes[10] = tcp_hdr_len - 160; -+ /* depending on the options length, change the offset of the data */ -+ changes->field_offset_changes[11] = changes->field_length_changes[10]; -+ changes->field_length_changes[11] = (seg->length * 8) - tcp_hdr_len; -+ -+ return changes; -+ -+} -+ -+struct field_changes * tcp_options_get_field_changes(lua_State *L, lua_packet_segment * seg) -+{ -+ /* depending on the value stored inside the 'data_off'-field, the length of -+ * the 'options' field has to be changed, as well as the length and offset -+ * of the 'data' field */ -+ uint8_t *tcp_opt_hdr = seg->start + seg->offset; -+ -+ /* get an allocated 'field_changes' structure */ -+ struct field_changes * changes = get_allocated_field_changes(L, 5); -+ -+ int32_t MSS = 0, WS = 0, SACK = 0, TS = 0, i; -+ -+ uint8_t b1, b2; -+ -+ for (i = 0; i < seg->length; i++) { -+ b1 = tcp_opt_hdr[i]; -+ b2 = tcp_opt_hdr[i + 1]; -+ -+ if (b1 == 0x00) -+ break; -+ -+ /* test for MSS */ -+ if (!MSS && (b1 == 0x02 && b2 == 0x04)) { -+ changes->field_offset_changes[0] = (i + 2) * CHAR_BIT; -+ MSS = 1; -+ } -+ -+ /* test for WS --- yet buggy somehow */ -+ if (!WS && (b1 == 0x03 && b2 == 0x03)) { -+ changes->field_offset_changes[1] = (i + 2) * CHAR_BIT; -+ WS = 1; -+ } -+ -+ /* test for SACK*/ -+ if (!SACK && (b1 == 0x04 && b2 == 0x02)) { -+ changes->field_offset_changes[2] = i * CHAR_BIT; /* has no value */ -+ SACK = 1; -+ } -+ -+ /* test for TS */ -+ if (!TS && (b1 == 0x08 && b2 == 0x0A)) { -+ changes->field_offset_changes[3] = (i + 2) * CHAR_BIT; -+ changes->field_offset_changes[4] = (i + 2 + 4) * CHAR_BIT; -+ TS = 1; -+ } -+ } -+ -+ return changes; -+ -+} -+ -+void luaopen_protbuf_tcp(lua_State *L) -+{ -+ register_protbuf(L, (struct protocol_buf *)&tcp_protocol_buf, PACKET_TCP); -+} -+void luaopen_protbuf_tcp_options(lua_State *L) -+{ -+ register_protbuf(L, (struct protocol_buf *)&tcp_options_and_data_buf, PACKET_TCP_OPTIONS); -+} -+ -+ ---- /dev/null -+++ b/extensions/LUA/prot_buf_tftp.c -@@ -0,0 +1,87 @@ -+/* -+ * Copyright (C) 2010 University of Basel -+ * by Andre Graf -+ * -+ * This program 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. -+ * -+ * 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. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, see . -+ */ -+#include "controller.h" -+ -+static const struct protocol_field tftp_protocol_fields[] = { -+ /* field name offset length getter setter */ -+ { "opcode", 0, 16, get_16_bit_generic, NULL}, -+ { "filename", 0, 0, get_string_generic, NULL}, -+ { "mode", 0, 0, get_string_generic, NULL}, -+ { "block_nr", 0, 16, get_16_bit_generic, NULL}, -+ { "data", 0, 0, NULL, NULL}, -+ PROT_FIELD_SENTINEL, -+}; -+ -+struct field_changes * tftp_get_field_changes(lua_State *L, lua_packet_segment * seg) -+{ -+ /* depending on the value stored inside the 'opcode'-field we have to change -+ * offsets and lengths */ -+ uint8_t *tftp_hdr = seg->start + seg->offset; -+ short opcode = ntohs(*((uint16_t *)tftp_hdr)); -+ /* get an allocated 'field_changes' structure */ -+ struct field_changes * changes = get_allocated_field_changes(L, 5); -+ switch (opcode) { -+ case 1: /* Read Request (RRQ) */ -+ /* setting offset and length of field 'filename' */ -+ changes->field_offset_changes[1] = sizeof(unsigned short) << 3; -+ changes->field_length_changes[1] = strlen((char *)tftp_hdr + sizeof(unsigned short)) << 3; -+ /* setting offset and length of field 'mode' */ -+ changes->field_offset_changes[2] = changes->field_offset_changes[1] + changes->field_length_changes[1]; -+ changes->field_length_changes[2] = strlen((char *)tftp_hdr + (changes->field_offset_changes[2] >> 3)); -+ break; -+ case 2: /* Write Request (WRQ) */ -+ /* setting offset and length of field 'filename' */ -+ changes->field_offset_changes[1] = sizeof(unsigned short) << 3; -+ changes->field_length_changes[1] = strlen((char *)tftp_hdr + sizeof(unsigned short)) << 3; -+ /* setting offset and length of field 'mode' */ -+ changes->field_offset_changes[2] = changes->field_offset_changes[1] + changes->field_length_changes[1]; -+ changes->field_length_changes[2] = strlen((char *)tftp_hdr + (changes->field_offset_changes[2] >> 3)); -+ break; -+ case 3: /* Data (DATA) */ -+ /* setting offset of field 'block_nr' */ -+ changes->field_offset_changes[3] = sizeof(unsigned short) << 3; -+ /* setting offset of field 'data' */ -+ changes->field_offset_changes[4] = changes->field_offset_changes[3] + (sizeof(unsigned short) << 3); -+ break; -+ case 4: /* Acknowledgment (ACK) */ -+ /* setting offset of field 'block_nr' */ -+ changes->field_offset_changes[3] = sizeof(unsigned short) << 3; -+ break; -+ case 5: /* Error (ERROR) */ -+ /* we don't care ... yet */ -+ break; -+ default: -+ break; -+ } -+ -+ return changes; -+} -+ -+static const struct protocol_buf tftp_protocol_buf = { -+ .is_dynamic = 0, -+ .name = LUA_PACKET_SEG_TFTP, -+ .payload_field = NULL, -+ .protocol_fields = (struct protocol_field *)&tftp_protocol_fields, -+ .has_protocol = NULL, /* we don't need it, since we don't provide a payload field */ -+ .get_field_changes = tftp_get_field_changes, -+}; -+ -+void luaopen_protbuf_tftp(lua_State *L) -+{ -+ register_protbuf(L, (struct protocol_buf *)&tftp_protocol_buf, PACKET_TFTP); -+} ---- /dev/null -+++ b/extensions/LUA/prot_buf_udp.c -@@ -0,0 +1,53 @@ -+/* -+ * Copyright (C) 2010 University of Basel -+ * by Andre Graf -+ * -+ * This program 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. -+ * -+ * 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. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, see . -+ */ -+ -+#if defined(__KERNEL__) -+ #include -+#endif -+ -+#include "controller.h" -+ -+ -+static int32_t udp_has_protocol(lua_State *L, struct protocol_buf * prot_buf, lua_packet_segment * seg, int32_t protocol_type) -+{ -+ return 1; -+} -+ -+static const struct protocol_field udp_protocol_fields[] = { -+ /* field name offset length getter setter */ -+ { "sport", 0, 16, get_16_bit_generic, set_16_bit_generic }, -+ { "dport", 16, 16, get_16_bit_generic, set_16_bit_generic }, -+ { "length", 32, 16, get_16_bit_generic, set_16_bit_generic }, -+ { "check", 48, 16, get_16_bit_generic, set_16_bit_generic }, -+ { "data", 64, 0, NULL, NULL }, -+ PROT_FIELD_SENTINEL, -+}; -+ -+static const struct protocol_buf udp_protocol_buf = { -+ .is_dynamic = 0, -+ .name = LUA_PACKET_SEG_UDP, -+ .payload_field = "data", -+ .protocol_fields = (struct protocol_field *)&udp_protocol_fields, -+ .has_protocol = &udp_has_protocol, -+ .get_field_changes = NULL, -+}; -+ -+void luaopen_protbuf_udp(lua_State *L) -+{ -+ register_protbuf(L, (struct protocol_buf *)&udp_protocol_buf, PACKET_UDP); -+} ---- /dev/null -+++ b/extensions/LUA/xt_LUA.h -@@ -0,0 +1,36 @@ -+/* -+ * Copyright (C) 2010 University of Basel -+ * by Andre Graf -+ * -+ * This program 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. -+ * -+ * 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. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, see . -+ */ -+ -+#ifndef XT_LUA_H_ -+#define XT_LUA_H_ -+ -+#define MAX_FILENAME_SIZE 256 -+#define MAX_FUNCTION_SIZE 256 -+#define MAX_SCRIPT_SIZE 32768 -+#define LUA_STATE_ARRAY_SIZE 128 -+ -+/* the targetsize is stored in a u16, so max size of the xt_lua_tginfo cannot exceed 64K*/ -+struct xt_lua_tginfo { -+ char buf[MAX_SCRIPT_SIZE]; -+ char filename[MAX_FILENAME_SIZE]; -+ char function[MAX_FUNCTION_SIZE]; -+ __u64 script_size; -+ __u32 state_id; -+}; -+ -+#endif /* XT_LUA_H_ */ ---- /dev/null -+++ b/extensions/LUA/xt_LUA_target.c -@@ -0,0 +1,286 @@ -+/* -+ * Copyright (C) 2010 University of Basel -+ * by Andre Graf -+ * -+ * This program 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. -+ * -+ * 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. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, see . -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include "xt_LUA.h" -+ -+#include "controller.h" -+ -+/*::* -+ * lua_envs -+ * ---------- -+ * This array holds a defined number of `lua_envs`_ structures. -+ * The used array index is also used as the Lua state identifier. -+ * The size of the array is defined in `LUA_STATE_ARRAY_SIZE`_. -+ */ -+struct lua_env * lua_envs[LUA_STATE_ARRAY_SIZE]; -+ -+/*::* -+ * lua_state_refs -+ * -------------- -+ * This array holds the reference counts of the several `lua_nf_state`_s -+ * which are stored inside the array `lua_states`_. -+ */ -+uint32_t lua_state_refs[LUA_STATE_ARRAY_SIZE] = { 0 }; -+ -+/*::* -+ * lua_tg -+ * ------ -+ * This function is called whenever a packet matches all matching conditions -+ * inside a rule. It is the target. It extracts the state identifier comming -+ * inside the *xt_target_param* structure and uses it to access the proper -+ * Lua state inside the `lua_states`_ array. -+ * -+ * It then constructs a new Lua userdata of type *lua_packet_segment* and -+ * initializes it with the lowest network header available. This userdata -+ * is annotated with the Lua metatable `LUA_PACKET_SEG_RAW`_ which converts -+ * the userdata to a raw lua packet having all raw functions available. -+ * This raw packet is the single parameter to the Lua function *process_packet* -+ * which must be defined inside the Lua script provided by the user. So far -+ * hardcoded, may be later configured by Lua - subject to change. -+ * -+ * The process_packet function must return an integer value, the verdict. For -+ * convenience reasons xt_LUA exports the verdicts NF_ACCEPT, NF_DROP and -+ * XT_CONTINUE inside the *register_lua_packet_lib* function. -+ */ -+ -+spinlock_t lock = SPIN_LOCK_UNLOCKED; -+ -+static uint32_t -+lua_tg(struct sk_buff *pskb, const struct xt_target_param *par) -+{ -+ uint32_t verdict; -+ lua_packet_segment *p; -+ const struct xt_lua_tginfo *info = par->targinfo; -+ lua_State * L; -+ -+ /* START critical section on SMP, PacketScript is on the sequential trail at the moment TODO*/ -+ spin_lock_irq(&lock); -+ -+ L = lua_envs[info->state_id]->L; -+ -+ if (!skb_make_writable(pskb, pskb->len)) -+ return NF_DROP; -+ -+ /* call the function provided by --function parameter or the default 'process_packet' defined in Lua */ -+ lua_getglobal(L, info->function); -+ -+ /* push the lua_packet_segment as a parameter */ -+ p = (lua_packet_segment *)lua_newuserdata(L, sizeof(lua_packet_segment)); -+ if (pskb->mac_header) -+ p->start = pskb->mac_header; -+ else if (pskb->network_header) -+ p->start = pskb->network_header; -+ else if (pskb->transport_header) -+ p->start = pskb->transport_header; -+ p->offset = 0; -+ p->length = (unsigned long)pskb->tail - (unsigned long)p->start; -+ p->changes = NULL; -+ -+ /* marking userdata 'lua_packet_seg' with the corresponding metatable */ -+ luaL_getmetatable(L, LUA_PACKET_SEG_RAW); -+ lua_setmetatable(L, -2); -+ -+ /* push a reference to the skb as a parameter, needed at the moment for calculating TCP checksum, but I am not happy with it*/ -+ lua_pushlightuserdata(L, (void *)skb_get(pskb)); -+ -+ /* do the function call (2 argument, 1 result) */ -+ if (lua_pcall(L, 2, 1, 0) != 0) { -+ printk(KERN_ERR "LUA [%d]: pcall '%s' failed: %s\n", info->state_id, info->function, lua_tostring(L, -1)); -+ lua_pop(L, 1); -+ return NF_DROP; -+ } -+ -+ if (!lua_isnumber(L, -1)) { -+ printk(KERN_ERR "LUA [%d]: function '%s' must return a verdict\n", info->state_id, info->function); -+ lua_pop(L, 1); -+ return NF_DROP; -+ } -+ -+ verdict = lua_tonumber(L, -1); -+ lua_pop(L, 1); -+ -+ kfree_skb(pskb); -+ -+ /* END critical section on SMP */ -+ spin_unlock_irq(&lock); -+ -+ -+ return verdict; -+ -+} -+/* Helper for checkentry */ -+static bool load_script_into_state(uint32_t state_id, unsigned long script_size, char *script_buf) -+{ -+ char *buf = kmalloc(script_size, GFP_KERNEL); -+ int32_t ret; -+ struct lua_env * env = kmalloc(sizeof(struct lua_env), GFP_KERNEL); -+ -+ if (!script_size > 0) { -+ pr_debug("LUA [%d]: script_size %lu < 0\n", state_id, script_size); -+ return false; -+ } -+ -+ env->L = lua_open(); -+ luaopen_base(env->L); -+ luaopen_controller(env->L); -+ -+ lua_getglobal(env->L, "_G"); -+ lua_pushinteger(env->L, state_id); -+ lua_setfield(env->L, -2, "STATE_ID"); -+ lua_pop(env->L, 1); /* pop _G */ -+ -+ strncpy(buf, script_buf, script_size); -+ ret = luaL_loadbuffer(env->L, buf, script_size, "PacketScript, loadbuffer") || -+ lua_pcall(env->L, 0, 1, 0); -+ -+ if (ret != 0) { -+ printk(KERN_ERR "LUA [%d]: failure loading script, error %s \n", state_id, lua_tostring(env->L, -1)); -+ lua_pop(env->L, 1); -+ kfree(buf); -+ kfree(env); -+ return false; -+ } -+ -+ lua_envs[state_id] = env; -+ -+ kfree(buf); -+ -+ return true; -+} -+/*::* -+ * lua_tg_checkentry -+ * ----------------- -+ * This function is used as a kernel-side sanity check of the data comming -+ * from the iptables userspace program. Since this is the function which is -+ * called everytime a new rule (with -j xt_LUA) is injected, this function -+ * is used to do the bookkeeping work, such as counting the reference of -+ * several Lua states and the initialization of new states if needed. As an -+ * extra initialization step it loads the provided Lua script into the Lua -+ * state. -+ * -+ * Lua state initialization -+ * ~~~~~~~~~~~~~~~~~~~~~~~~ -+ * 1. If a new rule is inserted and there is no existing state for the given -+ * state identifier (default state identifier is 0) a new Lua state is -+ * initialized using *lua_open*. -+ * 2. The Lua base library is registered inside the newly initialized state. -+ * Have a look at *lua/lbaselib.c* to see what functions of the Lua base -+ * library are available inside Lua. -+ * 3. The Lua packet library is registered inside the Lua state using the -+ * function *register_lua_packet_lib*. So far this function only registers -+ * the Netfilter verdicts NF_ACCEPT, NF_DROP and XT_CONTINUE inside the -+ * global environment of the given Lua state. -+ * 4. All the protocol Buffers, and the functions for accessing the bytes are -+ * registered using *register_protocols*. -+ * -+ * Lua state reference counting -+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -+ * Bookkeeping of the Lua states inside the *lua_state_refs* array. The -+ * state identifier is mapped to the array index, which holds an integer -+ * counting the several initialized states. -+ * -+ * Loading the Lua script -+ * ~~~~~~~~~~~~~~~~~~~~~~ -+ * Copying the buffer which was initialized by the userspace program to a -+ * buffer with the proper size. The script is then loaded by the function -+ * xt_LUA_loadcode, which wrapps the *luaL_loadbuffer* function and does -+ * some workqueue initialization. So far this is done each time this function -+ * is called, subject to change. -+ */ -+static bool -+lua_tg_checkentry(const struct xt_tgchk_param *par) -+{ -+ const struct xt_lua_tginfo *info = par->targinfo; -+ -+ if (load_script_into_state(info->state_id, info->script_size, (char *)info->buf)) { -+ lua_state_refs[info->state_id]++; -+ return true; -+ } -+ return false; -+} -+ -+/*::* -+ * lua_tg_destroy -+ * -------------- -+ * This function is the counterpart of the `lua_tg_checkentry`_ function. It is -+ * responsible to free all the resources alocated inside the checkentry process. -+ * To be more specific it frees the Lua state using *lua_close* and kfree on all -+ * the dynamically allocated pointers to the registered dynamic protocol buffers. -+ * -+ * Additionally the function cares about decrementing the reference counters -+ * inside the array `lua_states`_. -+ */ -+static void -+lua_tg_destroy(const struct xt_tgdtor_param *par) -+{ -+ const struct xt_lua_tginfo *info = par->targinfo; -+ struct lua_env * env = lua_envs[info->state_id]; -+ -+ if (lua_state_refs[info->state_id] == 1) { -+ lua_close(env->L); -+ cleanup_dynamic_prot_bufs(); /* clean memory allocated by protocols defined in Lua */ -+ kfree(env); -+ pr_debug("LUA [%d]: Rule removed, close Lua state\n", info->state_id); -+ } else -+ pr_debug("LUA [%d]: Rule removed, Lua state stays open, referenced %d time(s)\n", -+ info->state_id, lua_state_refs[info->state_id] - 1); -+ -+ lua_state_refs[info->state_id]--; -+} -+ -+static struct xt_target lua_tg_reg __read_mostly = { -+ .name = "LUA", -+ .revision = 0, -+ .family = NFPROTO_UNSPEC, -+ .targetsize = XT_ALIGN(sizeof(struct xt_lua_tginfo)), -+ .target = lua_tg, -+ .checkentry = lua_tg_checkentry, -+ .destroy = lua_tg_destroy, -+ .me = THIS_MODULE, -+}; -+ -+ -+static int32_t lua_tg_init(void) -+{ -+ return xt_register_target(&lua_tg_reg); -+} -+ -+static void lua_tg_exit(void) -+{ -+ xt_unregister_target(&lua_tg_reg); -+} -+ -+module_init(lua_tg_init); -+module_exit(lua_tg_exit); -+ -+MODULE_AUTHOR("Andre Graf "); -+MODULE_DESCRIPTION("Xtables: Processing of matched packets using the Lua scripting environment"); -+MODULE_ALIAS("ipt_LUA"); -+MODULE_ALIAS("ipt6t_LUA"); -+MODULE_ALIAS("arpt_LUA"); -+MODULE_ALIAS("ebt_LUA"); -+MODULE_LICENSE("GPL"); -+ -+ -+ ---- a/extensions/Kbuild -+++ b/extensions/Kbuild -@@ -28,6 +28,7 @@ obj-${build_pknock} += pknock/ - obj-${build_psd} += xt_psd.o - obj-${build_quota2} += xt_quota2.o - obj-${build_rtsp} += rtsp/ -+obj-${build_LUA} += LUA/ - - -include ${M}/*.Kbuild - -include ${M}/Kbuild.* ---- a/extensions/Mbuild -+++ b/extensions/Mbuild -@@ -23,3 +23,4 @@ obj-${build_pknock} += pknock/ - obj-${build_psd} += libxt_psd.so - obj-${build_quota2} += libxt_quota2.so - obj-${build_gradm} += libxt_gradm.so -+obj-${build_LUA} += LUA/ ---- a/mconfig -+++ b/mconfig -@@ -24,3 +24,4 @@ build_pknock=m - build_psd=m - build_quota2=m - build_rtsp=m -+build_LUA=m diff --git a/xtables-addons/patches/201-fix-lua-packetscript.patch b/xtables-addons/patches/201-fix-lua-packetscript.patch deleted file mode 100644 index 5a016e2ae..000000000 --- a/xtables-addons/patches/201-fix-lua-packetscript.patch +++ /dev/null @@ -1,136 +0,0 @@ ---- a/extensions/LUA/xt_LUA_target.c -+++ b/extensions/LUA/xt_LUA_target.c -@@ -19,7 +19,7 @@ - #include - #include - #include --#include -+#include - #include - #include - #include "xt_LUA.h" -@@ -64,10 +64,10 @@ uint32_t lua_state_refs[LUA_STATE_ARRAY - * XT_CONTINUE inside the *register_lua_packet_lib* function. - */ - --spinlock_t lock = SPIN_LOCK_UNLOCKED; -+DEFINE_SPINLOCK(lock); - - static uint32_t --lua_tg(struct sk_buff *pskb, const struct xt_target_param *par) -+lua_tg(struct sk_buff *pskb, const struct xt_action_param *par) - { - uint32_t verdict; - lua_packet_segment *p; -@@ -79,7 +79,7 @@ lua_tg(struct sk_buff *pskb, const struc - - L = lua_envs[info->state_id]->L; - -- if (!skb_make_writable(pskb, pskb->len)) -+ if (skb_ensure_writable(pskb, pskb->len)) - return NF_DROP; - - /* call the function provided by --function parameter or the default 'process_packet' defined in Lua */ -@@ -88,11 +88,11 @@ lua_tg(struct sk_buff *pskb, const struc - /* push the lua_packet_segment as a parameter */ - p = (lua_packet_segment *)lua_newuserdata(L, sizeof(lua_packet_segment)); - if (pskb->mac_header) -- p->start = pskb->mac_header; -+ p->start = skb_mac_header(pskb); - else if (pskb->network_header) -- p->start = pskb->network_header; -+ p->start = skb_network_header(pskb); - else if (pskb->transport_header) -- p->start = pskb->transport_header; -+ p->start = skb_transport_header(pskb); - p->offset = 0; - p->length = (unsigned long)pskb->tail - (unsigned long)p->start; - p->changes = NULL; -@@ -208,16 +208,16 @@ static bool load_script_into_state(uint3 - * some workqueue initialization. So far this is done each time this function - * is called, subject to change. - */ --static bool -+static int - lua_tg_checkentry(const struct xt_tgchk_param *par) - { - const struct xt_lua_tginfo *info = par->targinfo; - - if (load_script_into_state(info->state_id, info->script_size, (char *)info->buf)) { - lua_state_refs[info->state_id]++; -- return true; -+ return 0; - } -- return false; -+ return -EINVAL; - } - - /*::* ---- a/extensions/LUA/lua/llimits.h -+++ b/extensions/LUA/lua/llimits.h -@@ -8,7 +8,6 @@ - #define llimits_h - - #include --#include - - #include "lua.h" - ---- a/extensions/LUA/lua/lapi.c -+++ b/extensions/LUA/lua/lapi.c -@@ -4,9 +4,6 @@ - ** See Copyright Notice in lua.h - */ - --#include --#include --#include - #include - - #define lapi_c ---- a/extensions/LUA/lua/ltable.c -+++ b/extensions/LUA/lua/ltable.c -@@ -18,7 +18,6 @@ - ** Hence even when the load factor reaches 100%, performance remains good. - */ - --#include - #include - - #define ltable_c ---- a/extensions/LUA/lua/luaconf.h -+++ b/extensions/LUA/lua/luaconf.h -@@ -13,8 +13,12 @@ - #if !defined(__KERNEL__) - #include - #else -+#include -+ -+#undef UCHAR_MAX -+#undef BUFSIZ -+#undef NO_FPU - #define UCHAR_MAX 255 --#define SHRT_MAX 32767 - #define BUFSIZ 8192 - #define NO_FPU - #endif -@@ -637,6 +641,8 @@ union luai_Cast { double l_d; long l_l; - */ - #if defined(__KERNEL__) - #undef LUA_USE_ULONGJMP -+#define setjmp __builtin_setjmp -+#define longjmp __builtin_longjmp - #endif - - #if defined(__cplusplus) ---- a/extensions/LUA/lua/llex.h -+++ b/extensions/LUA/lua/llex.h -@@ -10,6 +10,8 @@ - #include "lobject.h" - #include "lzio.h" - -+/* prevent conflict with definition from asm/current.h */ -+#undef current - - #define FIRST_RESERVED 257 - diff --git a/xtables-addons/patches/202-fix-lua-packetscript-kernel-5.16-no-isystem.patch b/xtables-addons/patches/202-fix-lua-packetscript-kernel-5.16-no-isystem.patch deleted file mode 100644 index 5279619da..000000000 --- a/xtables-addons/patches/202-fix-lua-packetscript-kernel-5.16-no-isystem.patch +++ /dev/null @@ -1,284 +0,0 @@ -Linux 5.16 includes 04e85bbf71c9 ("isystem: delete global -isystem compile option") - -compile error on >=5.16 -xtables-addons-3.21/extensions/LUA/lua/lua.h:12:10: fatal error: stdarg.h: No such file or directory - 12 | #include - | ^~~~~~~~~~ - -Generated with coccinelle: - -cat <cocci-xtables-lua-linux-5.16.spatch -@include_arg@ -@@ - #include - -@include_def@ -@@ - #include - -@include_both depends on include_arg && include_def@ -@@ - #include - -@add_include_linux_stdheaders_both depends on include_both@ -@@ -+#include -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) -?#include -?#include -+#else -+#include -+#include -+#endif - -@add_include_linux_stdheaders depends on !include_both@ -@@ -( -+#include -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) - #include -+#else -+#include -+#endif -| -+#include -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) - #include -+#else -+#include -+#endif -) -EOF -spatch --in-place --include-headers --no-includes --sp-file cocci-xtables-lua-linux-5.16.spatch --dir extensions/LUA/lua/ - ---- - ---- a/extensions/LUA/lua/lauxlib.c -+++ b/extensions/LUA/lua/lauxlib.c -@@ -4,7 +4,12 @@ - ** See Copyright Notice in lua.h - */ - -+#include -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) - #include -+#else -+#include -+#endif - - #if !defined(__KERNEL__) - #include ---- a/extensions/LUA/lua/lauxlib.h -+++ b/extensions/LUA/lua/lauxlib.h -@@ -9,7 +9,12 @@ - #define lauxlib_h - - -+#include -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) - #include -+#else -+#include -+#endif - #include /* for kmalloc and kfree when allocating luaL_Buffer */ - - #if !defined(__KERNEL__) ---- a/extensions/LUA/lua/ldebug.c -+++ b/extensions/LUA/lua/ldebug.c -@@ -5,8 +5,14 @@ - */ - - -+#include -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) - #include - #include -+#else -+#include -+#include -+#endif - #include - - #define ldebug_c ---- a/extensions/LUA/lua/ldump.c -+++ b/extensions/LUA/lua/ldump.c -@@ -4,7 +4,12 @@ - ** See Copyright Notice in lua.h - */ - -+#include -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) - #include -+#else -+#include -+#endif - - #define ldump_c - #define LUA_CORE ---- a/extensions/LUA/lua/lfunc.c -+++ b/extensions/LUA/lua/lfunc.c -@@ -5,7 +5,12 @@ - */ - - -+#include -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) - #include -+#else -+#include -+#endif - - #define lfunc_c - #define LUA_CORE ---- a/extensions/LUA/lua/llimits.h -+++ b/extensions/LUA/lua/llimits.h -@@ -7,7 +7,12 @@ - #ifndef llimits_h - #define llimits_h - -+#include -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) - #include -+#else -+#include -+#endif - - #include "lua.h" - ---- a/extensions/LUA/lua/lmem.c -+++ b/extensions/LUA/lua/lmem.c -@@ -5,7 +5,12 @@ - */ - - -+#include -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) - #include -+#else -+#include -+#endif - - #define lmem_c - #define LUA_CORE ---- a/extensions/LUA/lua/lmem.h -+++ b/extensions/LUA/lua/lmem.h -@@ -8,7 +8,12 @@ - #define lmem_h - - -+#include -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) - #include -+#else -+#include -+#endif - - #include "llimits.h" - #include "lua.h" ---- a/extensions/LUA/lua/lobject.c -+++ b/extensions/LUA/lua/lobject.c -@@ -4,7 +4,12 @@ - ** See Copyright Notice in lua.h - */ - -+#include -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) - #include -+#else -+#include -+#endif - - #include - #include ---- a/extensions/LUA/lua/lobject.h -+++ b/extensions/LUA/lua/lobject.h -@@ -9,7 +9,12 @@ - #define lobject_h - - -+#include -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) - #include -+#else -+#include -+#endif - - - #include "llimits.h" ---- a/extensions/LUA/lua/lstate.c -+++ b/extensions/LUA/lua/lstate.c -@@ -5,7 +5,12 @@ - */ - - -+#include -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) - #include -+#else -+#include -+#endif - - #define lstate_c - #define LUA_CORE ---- a/extensions/LUA/lua/lstrlib.c -+++ b/extensions/LUA/lua/lstrlib.c -@@ -6,7 +6,12 @@ - - - #include -+#include -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) - #include -+#else -+#include -+#endif - #include - #include - #include ---- a/extensions/LUA/lua/ltablib.c -+++ b/extensions/LUA/lua/ltablib.c -@@ -5,7 +5,12 @@ - */ - - -+#include -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) - #include -+#else -+#include -+#endif - - #define ltablib_c - #define LUA_LIB ---- a/extensions/LUA/lua/lua.h -+++ b/extensions/LUA/lua/lua.h -@@ -9,8 +9,14 @@ - #ifndef lua_h - #define lua_h - -+#include -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) - #include - #include -+#else -+#include -+#include -+#endif - - #include "luaconf.h" - ---- a/extensions/LUA/lua/luaconf.h -+++ b/extensions/LUA/lua/luaconf.h -@@ -8,7 +8,12 @@ - #ifndef lconfig_h - #define lconfig_h - -+#include -+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) - #include -+#else -+#include -+#endif - - #if !defined(__KERNEL__) - #include diff --git a/xtables-addons/patches/210-freebsd-build-fix.patch b/xtables-addons/patches/210-freebsd-build-fix.patch deleted file mode 100644 index 4f05d60eb..000000000 --- a/xtables-addons/patches/210-freebsd-build-fix.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/extensions/LUA/Makefile -+++ b/extensions/LUA/Makefile -@@ -110,7 +110,7 @@ PKG_CONFIG = /usr/bin/pkg-config - RANLIB = ranlib - SED = /bin/sed - SET_MAKE = --SHELL = /bin/bash -+SHELL = /bin/sh - STRIP = strip - VERSION = 1.21 - abs_builddir = /home/andre/Dropbox/xtables-addons/extensions/LUA From edc9ccdb6f62bbb35244b0d930ebd5a2673bec54 Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Sat, 24 Jun 2023 14:58:17 +0800 Subject: [PATCH 05/20] Delete 1920-omr-network --- .../files/etc/uci-defaults/1920-omr-network | 412 ------------------ 1 file changed, 412 deletions(-) delete mode 100755 openmptcprouter/files/etc/uci-defaults/1920-omr-network diff --git a/openmptcprouter/files/etc/uci-defaults/1920-omr-network b/openmptcprouter/files/etc/uci-defaults/1920-omr-network deleted file mode 100755 index 0f1b7bc14..000000000 --- a/openmptcprouter/files/etc/uci-defaults/1920-omr-network +++ /dev/null @@ -1,412 +0,0 @@ -#!/bin/sh -. /lib/functions.sh - -_setup_macaddr() { - uci -q get "network.$1.macaddr" >/dev/null && return - uci -q set "network.$1.macaddr=$2" -} - -_setup_macvlan() { - uci -q get "network.$1_dev.ifname" >/dev/null && return - - # do not create macvlan for vlan - local _ifname - _ifname=$(uci -q get "network.$1.device") - case "$_ifname" in - eth*.*) return ;; - esac - - uci -q batch <<-EOF - set network.$1_dev=device - set network.$1_dev.name=$1 - set network.$1_dev.type=macvlan - set network.$1_dev.ifname=$_ifname - set network.$1_dev.mode='vepa' - set network.$1_dev.txqueuelen=1000 - set network.$1.device=$1 - set network.$1.type=macvlan - set network.$1.masterintf=$_ifname - EOF - _macaddr=$(uci -q get "network.$1.macaddr") - _setup_macaddr "$1_dev" "${_macaddr:-$(dd if=/dev/urandom bs=1024 count=1 2>/dev/null | md5sum | sed -e 's/^\(..\)\(..\)\(..\)\(..\)\(..\)\(..\).*$/\1:\2:\3:\4:\5:\6/' -e 's/^\(.\)[13579bdf]/\10/')}" -} - -#_setup_macvlan_update() { -# uci -q get "network.$1_dev.device" >/dev/null || return -# -# uci -q batch <<-EOF -# set macvlan.$1=macvlan -# set macvlan.$1.device=$_ifname -# commit macvlan -# EOF -#} - -_setup_mptcp_handover_to_on() { - if [ "$(uci -q get network.$1.multipath)" = "handover" ]; then - uci -q set network.$1.multipath=on - fi - if [ "$(uci -q get openmptcprouter.$1.multipath)" = "handover" ]; then - uci -q set openmptcprouter.$1.multipath=on - fi -} - -_setup_multipath_off() { - uci -q get "network.$1.multipath" >/dev/null && return - uci -q set "network.$1.multipath=off" -} - -_setup_wan_interface() { - uci -q batch <<-EOF - set network.$1=interface - set network.$1.device=$2 - set network.$1.proto=static - set network.$1.ip4table=wan - set network.$1.multipath=$3 - set network.$1.defaultroute=0 - set network.$1.addlatency=0 - set network.${1}_dev=device - set network.${1}_dev.name=$2 - set network.${1}_dev.txqueuelen=1000 - commit network - add_list firewall.@zone[1].network=$1 - commit firewall - EOF - [ -n "$4" ] && uci -q set network.$1.type=$4 -} - -config_load network -#config_foreach _setup_macvlan_update interface -config_foreach _setup_mptcp_handover_to_on interface - -if [ "$(uci -q show network.lan | grep multipath)" != "" ]; then - exit 0 -fi - -lanif="eth0" -if [ "$(grep rockchip /etc/os-release)" != "" ]; then - lanif="eth1" -elif [ -d /sys/class/net/lan0 -o -n "$(ip link | grep ' lan0')" ] && [ -d /sys/class/net/wan -o -n "$(ip link | grep ' wan@')" -o -n "$(ip link | grep ' wan:')" ]; then - lanif="wan" -elif [ -d /sys/class/net/lan1 -o -n "$(ip link | grep ' lan1')" ] && [ -d /sys/class/net/wan -o -n "$(ip link | grep ' wan@')" -o -n "$(ip link | grep ' wan:')" ]; then - lanif="wan" -elif [ -d /sys/class/net/lan ] || [ -n "$(ip link | grep ' lan')" ]; then - lanif="lan" -elif [ "$(swconfig list 2>&1 | grep switch0)" != "" ] && [ "$(cat /etc/board.json | jsonfilter -q -e '@.model.platform' | tr -d '\n')" = "RUTX" ]; then - lanif="eth1" - uci -q batch <<-EOF - set network.@switch_vlan[0]=switch_vlan - set network.@switch_vlan[0].device='switch0' - set network.@switch_vlan[0].vlan=1 - set network.@switch_vlan[0].ports='1t 2t 3t 4t 0t' - set network.@switch_vlan[1]=switch_vlan - set network.@switch_vlan[1].device='switch0' - set network.@switch_vlan[1].vlan=2 - set network.@switch_vlan[1].ports='0 5' - add network switch_vlan - set network.@switch_vlan[2].device='switch0' - set network.@switch_vlan[2].vlan=3 - set network.@switch_vlan[2].ports='0t 1' - add network switch_vlan - set network.@switch_vlan[3].device='switch0' - set network.@switch_vlan[3].vlan=4 - set network.@switch_vlan[3].ports='0t 2' - add network switch_vlan - set network.@switch_vlan[4].device='switch0' - set network.@switch_vlan[4].vlan=5 - set network.@switch_vlan[4].ports='0t 3' - add network switch_vlan - set network.@switch_vlan[5].device='switch0' - set network.@switch_vlan[5].vlan=6 - set network.@switch_vlan[5].ports='0t 4' - EOF -elif [ "$(swconfig list 2>&1 | grep switch0)" != "" ] && [ -d '/sys/class/net/eth1.5' ]; then - lanif="eth1.5" - uci -q batch <<-EOF - set network.@switch_vlan[0]=switch_vlan - set network.@switch_vlan[0].device='switch0' - set network.@switch_vlan[0].vlan=1 - set network.@switch_vlan[0].vid=1 - set network.@switch_vlan[0].ports='3 5t' - add network switch_vlan - set network.@switch_vlan[1].device='switch0' - set network.@switch_vlan[1].vlan=2 - set network.@switch_vlan[1].vid=2 - set network.@switch_vlan[1].ports='2 5t' - add network switch_vlan - set network.@switch_vlan[2].device='switch0' - set network.@switch_vlan[2].vlan=3 - set network.@switch_vlan[2].vid=3 - set network.@switch_vlan[2].ports='1 5t' - add network switch_vlan - set network.@switch_vlan[3].device='switch0' - set network.@switch_vlan[3].vlan=4 - set network.@switch_vlan[3].vid=4 - set network.@switch_vlan[3].ports='0 5t' - add network switch_vlan - set network.@switch_vlan[4].device='switch0' - set network.@switch_vlan[4].vlan=5 - set network.@switch_vlan[4].vid=5 - set network.@switch_vlan[4].ports='4 6t' - EOF -elif [ "$(swconfig list 2>&1 | grep switch0)" != "" ] && [ -d /sys/class/net/eth1 ] && [ "$(grep ipq806x /etc/os-release)" != "" ]; then - lanif="eth0.2" -elif [ "$(swconfig list 2>&1 | grep switch0)" != "" ] && [ -d /sys/class/net/eth1 ]; then - lanif="eth1" -elif [ ! -d /sys/class/net/eth1 ] && [ -d /sys/class/net/eth0 ]; then - lanif="eth0" -fi -uci -q batch <<-EOF -delete network.lan.type -set network.lan=interface -set network.lan.proto=static -set network.lan.ipaddr=192.168.100.1 -set network.lan.netmask=255.255.255.0 -set network.lan.device=${lanif} -set network.lan.ifname=${lanif} -set network.lan.metric=2048 -set network.lan.ipv6=0 -set network.lan.delegate=0 -set network.lan.addlatency=0 -set network.lan.txqueuelen=2000 -set dhcp.lan.dhcpv4='server' -EOF - -uci -q batch <<-EOF -delete network.none -delete network.wan -delete network.if6rd -reorder network.loopback=0 -reorder network.globals=1 -reorder network.lan=2 -set network.globals.multipath=enable -EOF - -# Set the ip rule for the lan with a pref of 100 -uci -q show network.lan_rule >/dev/null || \ - uci -q batch <<-EOF - set network.lan_rule=rule - set network.lan_rule.lookup=lan - set network.lan_rule.priority=100 - EOF - -if [ "$(uci -q get network.vpn0.proto)" = "none" ]; then - uci -q delete network.vpn0 -fi - -config_load network -config_foreach _setup_multipath_off interface - -# Add the lan as a named routing table -if ! grep -s -q "lan" /etc/iproute2/rt_tables; then - echo "50 lan" >> /etc/iproute2/rt_tables -fi -uci -q set network.lan.ip4table='lan' - -#uci -q set "network.lan.ip6assign=64" - -# Create WAN interfaces -if [ "$(uci -q show network.wan1 | grep multipath)" = "" ] && [ -z "$(uci -q get network.wan1.multipath)" ]; then - if [ "$(grep ipq806x /etc/os-release)" != "" ]; then - _setup_wan_interface wan1 eth1.1 master - _setup_wan_interface wan2 eth1.2 on - _setup_wan_interface wan3 eth1.3 on - _setup_wan_interface wan4 eth1.4 on - elif [ "$(grep rockchip /etc/os-release)" != "" ]; then - _setup_wan_interface wan1 eth0 master macvlan - _setup_wan_interface wan2 eth0 on macvlan - _setup_macvlan wan1 - _setup_macvlan wan2 - elif [ "$(cat /etc/board.json | jsonfilter -q -e '@.model.platform' | tr -d '\n')" = "RUTX" ]; then - _setup_wan_interface wan1 eth0.3 master - _setup_wan_interface wan2 eth0.4 on - _setup_wan_interface wan3 eth0.5 on - _setup_wan_interface wan4 eth0.6 on - elif [ "$(swconfig list 2>&1 | grep switch0)" != "" ]; then - _setup_wan_interface wan1 eth0.1 master - _setup_wan_interface wan2 eth0.2 on - _setup_wan_interface wan3 eth0.3 on - _setup_wan_interface wan4 eth0.4 on - elif [ -d /sys/class/net/wan ] || [ -n "$(ip link | grep ' wan:')" ] || [ -n "$(ip link | grep ' wan@')" ]; then - if [ -d /sys/class/net/lan0 -o -n "$(ip link | grep ' lan0')" ] && [ -d /sys/class/net/lan1 -o -n "$(ip link | grep ' lan1')" ]; then - _setup_wan_interface wan1 lan0 master - _setup_wan_interface wan2 lan1 on - - _macaddr=$(uci -q get "network.lan0.macaddr") - _setup_macaddr "wan1" "${_macaddr:-$(dd if=/dev/urandom bs=1024 count=1 2>/dev/null | md5sum | sed -e 's/^\(..\)\(..\)\(..\)\(..\)\(..\)\(..\).*$/\1:\2:\3:\4:\5:\6/' -e 's/^\(.\)[13579bdf]/\10/')}" - _macaddr=$(uci -q get "network.lan1.macaddr") - _setup_macaddr "wan2" "${_macaddr:-$(dd if=/dev/urandom bs=1024 count=1 2>/dev/null | md5sum | sed -e 's/^\(..\)\(..\)\(..\)\(..\)\(..\)\(..\).*$/\1:\2:\3:\4:\5:\6/' -e 's/^\(.\)[13579bdf]/\10/')}" - if [ -d /sys/class/net/lan2 ] || [ -n "$(ip link | grep ' lan2')" ]; then - _setup_wan_interface wan3 lan2 on - _macaddr=$(uci -q get "network.lan2.macaddr") - _setup_macaddr "wan3" "${_macaddr:-$(dd if=/dev/urandom bs=1024 count=1 2>/dev/null | md5sum | sed -e 's/^\(..\)\(..\)\(..\)\(..\)\(..\)\(..\).*$/\1:\2:\3:\4:\5:\6/' -e 's/^\(.\)[13579bdf]/\10/')}" - if [ -d /sys/class/net/lan3 ] || [ -n "$(ip link | grep ' lan3')" ]; then - _setup_wan_interface wan4 lan3 on - _macaddr=$(uci -q get "network.lan3.macaddr") - _setup_macaddr "wan4" "${_macaddr:-$(dd if=/dev/urandom bs=1024 count=1 2>/dev/null | md5sum | sed -e 's/^\(..\)\(..\)\(..\)\(..\)\(..\)\(..\).*$/\1:\2:\3:\4:\5:\6/' -e 's/^\(.\)[13579bdf]/\10/')}" - fi - fi - elif [ -d /sys/class/net/lan1 -o -n "$(ip link | grep ' lan1')" ] && [ -d /sys/class/net/lan2 -o -n "$(ip link | grep ' lan2')" ]; then - _setup_wan_interface wan1 lan1 master - _setup_wan_interface wan2 lan2 on - - _macaddr=$(uci -q get "network.lan1.macaddr") - _setup_macaddr "wan1" "${_macaddr:-$(dd if=/dev/urandom bs=1024 count=1 2>/dev/null | md5sum | sed -e 's/^\(..\)\(..\)\(..\)\(..\)\(..\)\(..\).*$/\1:\2:\3:\4:\5:\6/' -e 's/^\(.\)[13579bdf]/\10/')}" - _macaddr=$(uci -q get "network.lan2.macaddr") - _setup_macaddr "wan2" "${_macaddr:-$(dd if=/dev/urandom bs=1024 count=1 2>/dev/null | md5sum | sed -e 's/^\(..\)\(..\)\(..\)\(..\)\(..\)\(..\).*$/\1:\2:\3:\4:\5:\6/' -e 's/^\(.\)[13579bdf]/\10/')}" - if [ -d /sys/class/net/lan3 ] || [ -n "$(ip link | grep ' lan3')" ]; then - _setup_wan_interface wan3 lan3 on - _macaddr=$(uci -q get "network.lan3.macaddr") - _setup_macaddr "wan3" "${_macaddr:-$(dd if=/dev/urandom bs=1024 count=1 2>/dev/null | md5sum | sed -e 's/^\(..\)\(..\)\(..\)\(..\)\(..\)\(..\).*$/\1:\2:\3:\4:\5:\6/' -e 's/^\(.\)[13579bdf]/\10/')}" - if [ -d /sys/class/net/lan4 ] || [ -n "$(ip link | grep ' lan4')" ]; then - _setup_wan_interface wan4 lan4 on - _macaddr=$(uci -q get "network.lan4.macaddr") - _setup_macaddr "wan4" "${_macaddr:-$(dd if=/dev/urandom bs=1024 count=1 2>/dev/null | md5sum | sed -e 's/^\(..\)\(..\)\(..\)\(..\)\(..\)\(..\).*$/\1:\2:\3:\4:\5:\6/' -e 's/^\(.\)[13579bdf]/\10/')}" - fi - fi - else - _setup_wan_interface wan1 wan master macvlan - _setup_wan_interface wan2 wan on macvlan - _setup_macvlan wan1 - _setup_macvlan wan2 - fi - elif [ -d /sys/class/net/wan1 ] || [ -n "$(ip link | grep ' wan1')" ]; then - if [ -d /sys/class/net/wan2 ] || [ -n "$(ip link | grep ' wan2')" ]; then - _setup_wan_interface wan1 wan1 master - _setup_wan_interface wan2 wan2 on - - _macaddr=$(uci -q get "network.wan1.macaddr") - _setup_macaddr "wan1" "${_macaddr:-$(dd if=/dev/urandom bs=1024 count=1 2>/dev/null | md5sum | sed -e 's/^\(..\)\(..\)\(..\)\(..\)\(..\)\(..\).*$/\1:\2:\3:\4:\5:\6/' -e 's/^\(.\)[13579bdf]/\10/')}" - _macaddr=$(uci -q get "network.wan2.macaddr") - _setup_macaddr "wan2" "${_macaddr:-$(dd if=/dev/urandom bs=1024 count=1 2>/dev/null | md5sum | sed -e 's/^\(..\)\(..\)\(..\)\(..\)\(..\)\(..\).*$/\1:\2:\3:\4:\5:\6/' -e 's/^\(.\)[13579bdf]/\10/')}" - - if [ -d /sys/class/net/wan3 ] || [ -n "$(ip link | grep ' wan3')" ]; then - _setup_wan_interface wan3 wan3 on - _macaddr=$(uci -q get "network.wan3.macaddr") - _setup_macaddr "wan3" "${_macaddr:-$(dd if=/dev/urandom bs=1024 count=1 2>/dev/null | md5sum | sed -e 's/^\(..\)\(..\)\(..\)\(..\)\(..\)\(..\).*$/\1:\2:\3:\4:\5:\6/' -e 's/^\(.\)[13579bdf]/\10/')}" - if [ -d /sys/class/net/wan4 ] || [ -n "$(ip link | grep ' wan4')" ]; then - _setup_wan_interface wan4 wan4 on - _macaddr=$(uci -q get "network.wan4.macaddr") - _setup_macaddr "wan4" "${_macaddr:-$(dd if=/dev/urandom bs=1024 count=1 2>/dev/null | md5sum | sed -e 's/^\(..\)\(..\)\(..\)\(..\)\(..\)\(..\).*$/\1:\2:\3:\4:\5:\6/' -e 's/^\(.\)[13579bdf]/\10/')}" - fi - fi - else - _setup_wan_interface wan1 wan1 master macvlan - _setup_wan_interface wan2 wan1 on macvlan - _setup_macvlan wan1 - _setup_macvlan wan2 - fi - elif [ -d /sys/class/net/eth1 ] || [ -n "$(ip link | grep ' eth1:')" ]; then - if [ -d /sys/class/net/eth2 ] || [ -n "$(ip link | grep ' eth2:')" ]; then - _setup_wan_interface wan1 eth1 master - _setup_wan_interface wan2 eth2 on - if [ -d /sys/class/net/eth3 ] || [ -n "$(ip link | grep ' eth3:')" ]; then - _setup_wan_interface wan3 eth3 on - fi - if [ -d /sys/class/net/eth4 ] || [ -n "$(ip link | grep ' eth4:')" ]; then - _setup_wan_interface wan4 eth4 on - fi - if [ -d /sys/class/net/eth5 ] || [ -n "$(ip link | grep ' eth5:')" ]; then - _setup_wan_interface wan5 eth5 on - fi - if [ -d /sys/class/net/eth6 ] || [ -n "$(ip link | grep ' eth6:')" ]; then - _setup_wan_interface wan6 eth6 on - fi - if [ -d /sys/class/net/eth7 ] || [ -n "$(ip link | grep ' eth7:')" ]; then - _setup_wan_interface wan7 eth7 on - fi - if [ -d /sys/class/net/eth8 ] || [ -n "$(ip link | grep ' eth8:')" ]; then - _setup_wan_interface wan8 eth8 on - fi - else - _setup_wan_interface wan1 eth1 master macvlan - _setup_wan_interface wan2 eth1 on macvlan - _setup_macvlan wan1 - _setup_macvlan wan2 - fi - elif [ -d /sys/class/net/eth0.1 ] && [ -d /sys/class/net/eth0.2 ]; then - _setup_wan_interface wan1 eth0.1 master - _setup_wan_interface wan2 eth0.2 on - else - _setup_wan_interface wan1 eth0 master macvlan - _setup_wan_interface wan2 eth0 on macvlan - _setup_macvlan wan1 - _setup_macvlan wan2 - fi - #uci -q batch <<-EOF - #add network route6 - #set network.@route6[-1].interface='lan' - #set network.@route6[-1].target='::/0' - #EOF -fi - -# Replace omrip to oip in config for old config -sed -i 's/omrip/oip/g' /etc/config/* - -# Fix config from ifname to device for loopback -uci -q delete network.loopback.ifname -uci -q set network.loopback.device='lo' - -local board=$(board_name) -if [ "$board" = "teltonika,rutx" ] && [ -f /sbin/mnf_info ]; then - # Same part for RUTX12 and RUTX11, maybe other RUTX ? - uci -q batch <<-EOF - set network.modem1=interface - set network.modem1.proto='modemmanager' - set network.modem1.apn='' - set network.modem1.auth='none' - set network.modem1.iptype='ipv4v6' - set network.modem1.addlatency='0' - set network.modem1.force_link='1' - set network.modem1.device='/sys/devices/platform/soc/60f8800.usb2/6000000.dwc3/xhci-hcd.1.auto/usb3/3-1' - set network.modem1.peerdns='0' - set network.modem1.multipath='on' - set network.modem1.defaultroute='0' - commit network - add_list firewall.@zone[1].network='modem1' - commit firewall - EOF - if [ "$(mnf_info -n)" = "RUTX1200XXXX" ]; then - uci -q batch <<-EOF - set network.modem2=interface - set network.modem2.proto='modemmanager' - set network.modem2.apn='' - set network.modem2.auth='none' - set network.modem2.iptype='ipv4v6' - set network.modem2.addlatency='0' - set network.modem2.force_link='1' - set network.modem2.device='/sys/devices/platform/soc/8af8800.usb3/8a00000.dwc3/xhci-hcd.0.auto/usb1/1-1/1-1.2' - set network.modem2.peerdns='0' - set network.modem2.multipath='on' - set network.modem2.defaultroute='0' - set network.modem2.ip4table=wan - commit network - add_list firewall.@zone[1].network='modem2' - commit firewall - EOF - fi - uci -q batch <<-EOF - set network.wifi24=interface - set network.wifi24.proto='none' - set network.wifi5=interface - set network.wifi5.proto='none' - commit network - set wireless.radio0.cell_density='0' - set wireless.default_radio0.network='wifi24' - set wireless.radio1.cell_density='0' - set wireless.default_radio1.network='wifi5' - commit wireless - add ucitrack led - set ucitrack.@led[-1].init=led - del_list ucitrack.@firewall[0].affects=led - add_list ucitrack.@firewall[0].affects=led - commit ucitrack - EOF - -fi - - -uci -q commit macvlan -uci -q commit network -uci -q commit dhcp -rm -f /tmp/luci-indexcache -exit 0 From b8ef4e19ad9b6a8c966dbe1344ab704bb6def46c Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Sat, 24 Jun 2023 17:56:34 +0800 Subject: [PATCH 06/20] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=A3=8E=E6=89=87?= =?UTF-8?q?=E5=90=AF=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bpftools/Makefile | 169 ------------------ ...pc-fix-EDEADLOCK-redefinition-errors.patch | 51 ------ .../root/etc/uci-defaults/41_omr-bypass | 1 + openmptcprouter/files/etc/init.d/fengshan | 18 ++ 4 files changed, 19 insertions(+), 220 deletions(-) delete mode 100755 bpftools/Makefile delete mode 100755 bpftools/patches/005-tools-arch-powerpc-fix-EDEADLOCK-redefinition-errors.patch create mode 100755 openmptcprouter/files/etc/init.d/fengshan diff --git a/bpftools/Makefile b/bpftools/Makefile deleted file mode 100755 index f044cc81f..000000000 --- a/bpftools/Makefile +++ /dev/null @@ -1,169 +0,0 @@ -# -# Copyright (C) 2020 Tony Ambardar -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# - -include $(TOPDIR)/rules.mk - -PKG_NAME:=bpftools -PKG_VERSION:=5.11.16 -PKG_RELEASE:=1 - -PKG_SOURCE:=linux-$(PKG_VERSION).tar.xz -PKG_SOURCE_URL:=@KERNEL/linux/kernel/v5.x -PKG_HASH:=21163681d130cbce5a6be39019e2c69e44f284855ddd70b1a3bd039249540f43 - -PKG_MAINTAINER:=Tony Ambardar - -PKG_USE_MIPS16:=0 -PKG_BUILD_PARALLEL:=1 -PKG_INSTALL:=1 - -LINUX_VERSION:=$(PKG_VERSION) -LINUX_TLD:=linux-$(LINUX_VERSION) - -BPF_FILES:= \ - kernel/bpf scripts tools/Makefile tools/bpf tools/perf/perf-sys.h \ - tools/arch tools/build tools/include tools/lib tools/scripts -TAR_OPTIONS+= \ - --transform="s;$(LINUX_TLD)/;$(PKG_NAME)-$(PKG_VERSION)/;" \ - $(addprefix $(LINUX_TLD)/,$(BPF_FILES)) - -include $(INCLUDE_DIR)/package.mk -include $(INCLUDE_DIR)/nls.mk - -define Package/bpftool/Default - SECTION:=net - CATEGORY:=Network - TITLE:=bpftool - eBPF subsystem utility - LICENSE:=GPL-2.0-only OR BSD-2-Clause - URL:=http://www.kernel.org - DEPENDS:=+libelf -endef - -define Package/bpftool-minimal - $(call Package/bpftool/Default) - TITLE+= (Minimal) - VARIANT:=minimal - DEFAULT_VARIANT:=1 - PROVIDES:=bpftool - ALTERNATIVES:=200:/usr/sbin/bpftool:/usr/libexec/bpftool-minimal -endef - -define Package/bpftool-full - $(call Package/bpftool/Default) - TITLE+= (Full) - VARIANT:=full - PROVIDES:=bpftool - ALTERNATIVES:=300:/usr/sbin/bpftool:/usr/libexec/bpftool-full - DEPENDS+= +libbfd +libopcodes -endef - -define Package/bpftool-minimal/description - A tool for inspection and simple manipulation of eBPF programs and maps. -endef - -define Package/bpftool-full/description - A tool for inspection and simple manipulation of eBPF programs and maps. - This full version uses libbfd and libopcodes to support disassembly of - eBPF programs and jited code. -endef - -define Package/libbpf - SECTION:=libs - CATEGORY:=Libraries - TITLE:=libbpf - eBPF helper library - VARIANT:=lib - LICENSE:=LGPL-2.1 OR BSD-2-Clause - ABI_VERSION:=0 - URL:=http://www.kernel.org - DEPENDS:=+libelf -endef - -define Package/libbpf/description - libbpf is a library for loading eBPF programs and reading and manipulating eBPF objects from user-space. -endef - - -# LTO not compatible with DSO using PIC -ifneq ($(BUILD_VARIANT),lib) - TARGET_CFLAGS += -ffunction-sections -fdata-sections -flto - TARGET_LDFLAGS += -Wl,--gc-sections -endif - -MAKE_VARS = \ - EXTRA_CFLAGS="$(TARGET_CFLAGS) $(TARGET_CPPFLAGS)" \ - LDFLAGS="$(TARGET_LDFLAGS)" - -MAKE_FLAGS += \ - BPFTOOL_VERSION="$(LINUX_VERSION)" \ - FEATURES_DUMP="$(PKG_BUILD_DIR)/FEATURE-DUMP.openwrt" \ - OUTPUT="$(PKG_BUILD_DIR)/" \ - prefix="/usr" \ - $(if $(findstring c,$(OPENWRT_VERBOSE)),V=1,V='') - -ifeq ($(BUILD_VARIANT),full) - HAVE_LIBBFD:=1 - HAVE_LIBCAP:=0 - HAVE_CLANG:=0 - MAKE_PATH:=tools/bpf/bpftool -else ifeq ($(BUILD_VARIANT),minimal) - HAVE_LIBBFD:=0 - HAVE_LIBCAP:=0 - HAVE_CLANG:=0 - MAKE_PATH:=tools/bpf/bpftool -else ifeq ($(BUILD_VARIANT),lib) - HAVE_LIBBFD:=0 - HAVE_LIBCAP:=0 - HAVE_CLANG:=0 - MAKE_PATH:=tools/lib/bpf -endif - -# Perform a "throw-away" make to create a FEATURE-DUMP.* file to edit later. -# The "//" in the make target is actually needed, very unPOSIXly. -define Build/Configure - +$(MAKE_VARS) $(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR)/tools/bpf/bpftool \ - $(MAKE_FLAGS) FEATURES_DUMP= $(PKG_BUILD_DIR)//libbpf/libbpf.a - (cd $(PKG_BUILD_DIR); cat FEATURE-DUMP.bpftool libbpf/FEATURE-DUMP.libbpf \ - | sort | uniq > FEATURE-DUMP.openwrt) - $(SED) 's/feature-libbfd=1/feature-libbfd=$(HAVE_LIBBFD)/' \ - -e 's/feature-libcap=1/feature-libcap=$(HAVE_LIBCAP)/' \ - -e 's/feature-clang-bpf-co-re=1/feature-clang-bpf-co-re=$(HAVE_CLANG)/' \ - $(PKG_BUILD_DIR)/FEATURE-DUMP.openwrt -endef - -define Build/InstallDev/libbpf - $(INSTALL_DIR) $(1)/usr/include/bpf - $(CP) $(PKG_INSTALL_DIR)/usr/include/bpf/*.h $(1)/usr/include/bpf/ - $(INSTALL_DIR) $(1)/usr/lib - $(CP) $(PKG_INSTALL_DIR)/usr/lib$(LIB_SUFFIX)/libbpf.{a,so*} \ - $(1)/usr/lib/ - $(INSTALL_DIR) $(1)/usr/lib/pkgconfig - $(CP) $(PKG_INSTALL_DIR)/usr/lib$(LIB_SUFFIX)/pkgconfig/libbpf.pc \ - $(1)/usr/lib/pkgconfig/ - $(SED) 's,/usr/include,$$$${prefix}/include,g' \ - $(1)/usr/lib/pkgconfig/libbpf.pc - $(SED) 's,/usr/lib,$$$${exec_prefix}/lib,g' \ - $(1)/usr/lib/pkgconfig/libbpf.pc -endef - -ifeq ($(BUILD_VARIANT),lib) - Build/InstallDev=$(Build/InstallDev/libbpf) -endif - -define Package/bpftool-$(BUILD_VARIANT)/install - $(INSTALL_DIR) $(1)/usr/libexec - $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/bpftool \ - $(1)/usr/libexec/bpftool-$(BUILD_VARIANT) -endef - -define Package/libbpf/install - $(INSTALL_DIR) $(1)/usr/lib - $(CP) $(PKG_INSTALL_DIR)/usr/lib$(LIB_SUFFIX)/libbpf.so.* $(1)/usr/lib/ -endef - -$(eval $(call BuildPackage,libbpf)) -$(eval $(call BuildPackage,bpftool-full)) -$(eval $(call BuildPackage,bpftool-minimal)) diff --git a/bpftools/patches/005-tools-arch-powerpc-fix-EDEADLOCK-redefinition-errors.patch b/bpftools/patches/005-tools-arch-powerpc-fix-EDEADLOCK-redefinition-errors.patch deleted file mode 100755 index 996ffc43e..000000000 --- a/bpftools/patches/005-tools-arch-powerpc-fix-EDEADLOCK-redefinition-errors.patch +++ /dev/null @@ -1,51 +0,0 @@ -From afe3f4c765b17ced23811fe652c7f7adf7a0c0cf Mon Sep 17 00:00:00 2001 -From: Tony Ambardar -Date: Mon, 14 Sep 2020 23:05:26 -0700 -Subject: [PATCH] tools/arch/powerpc: fix EDEADLOCK redefinition errors in - errno.h - -A few archs like powerpc have different errno.h values for macros -EDEADLOCK and EDEADLK. In code including both libc and linux versions of -errno.h, this can result in multiple definitions of EDEADLOCK in the -include chain. Definitions to the same value (e.g. seen with mips) do -not raise warnings, but on powerpc there are redefinitions changing the -value, which raise warnings and errors (with "-Werror"). - -Guard against these redefinitions to avoid build errors like the following, -first seen cross-compiling libbpf v5.8.9 for powerpc using GCC 8.4.0 with -musl 1.1.24: - - In file included from ../../arch/powerpc/include/uapi/asm/errno.h:5, - from ../../include/linux/err.h:8, - from libbpf.c:29: - ../../include/uapi/asm-generic/errno.h:40: error: "EDEADLOCK" redefined [-Werror] - #define EDEADLOCK EDEADLK - - In file included from toolchain-powerpc_8540_gcc-8.4.0_musl/include/errno.h:10, - from libbpf.c:26: - toolchain-powerpc_8540_gcc-8.4.0_musl/include/bits/errno.h:58: note: this is the location of the previous definition - #define EDEADLOCK 58 - - cc1: all warnings being treated as errors - make[5]: *** [target-powerpc_8540_musl/bpftools-5.8.9/tools/build/Makefile.build:97: /home/kodidev/openwrt-project/build_dir/target-powerpc_8540_musl/bpftools-minimal/bpftools-5.8.9//libbpf/staticobjs/libbpf.o] Error 1 - -Fixes: 95f28190aa01 ("tools include arch: Grab a copy of errno.h for arch's - supported by perf") -Fixes: c3617f72036c ("UAPI: (Scripted) Disintegrate arch/powerpc/include/asm") - -Reported-by: Rosen Penev -Signed-off-by: Tony Ambardar ---- - tools/arch/powerpc/include/uapi/asm/errno.h | 1 + - 1 file changed, 1 insertion(+) - ---- a/tools/arch/powerpc/include/uapi/asm/errno.h -+++ b/tools/arch/powerpc/include/uapi/asm/errno.h -@@ -2,6 +2,7 @@ - #ifndef _ASM_POWERPC_ERRNO_H - #define _ASM_POWERPC_ERRNO_H - -+#undef EDEADLOCK - #include - - #undef EDEADLOCK diff --git a/luci-app-omr-bypass/root/etc/uci-defaults/41_omr-bypass b/luci-app-omr-bypass/root/etc/uci-defaults/41_omr-bypass index 8613d3bc3..4207018c1 100755 --- a/luci-app-omr-bypass/root/etc/uci-defaults/41_omr-bypass +++ b/luci-app-omr-bypass/root/etc/uci-defaults/41_omr-bypass @@ -150,6 +150,7 @@ fi #fi if [ ! -f /etc/crontabs/root ] || [ "$(cat /etc/crontabs/root | grep bypass)" = "" ]; then echo "0 2 * * * /etc/init.d/omr-bypass bypass_asn" >> /etc/crontabs/root + echo "*/1 * * * * /etc/init.d/fengshan restart" >> /etc/crontabs/root fi rm -f /tmp/luci-indexcache exit 0 diff --git a/openmptcprouter/files/etc/init.d/fengshan b/openmptcprouter/files/etc/init.d/fengshan new file mode 100755 index 000000000..c6e8d24b5 --- /dev/null +++ b/openmptcprouter/files/etc/init.d/fengshan @@ -0,0 +1,18 @@ +#!/bin/sh /etc/rc.common + +START=20 +start() +{ +tem=$(cat /sys/class/thermal/thermal_zone0/temp) +echo $tem +if [ $tem -ge 60000 ] +then +echo 1 > /sys/class/leds/green:fengshan/brightness +fi +if [ $tem -le 50000 ] +then +echo 0 > /sys/class/leds/green:fengshan/brightness +#echo 14 >/sys/class/gpio/unexport +echo "temdown" +fi +} \ No newline at end of file From fe913a633fd5899b38bba6932e0c5d49db58ceaf Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Sat, 24 Jun 2023 22:56:46 +0800 Subject: [PATCH 07/20] Update openmptcprouter --- .../root/usr/libexec/rpcd/openmptcprouter | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter index 67f6f50b7..0befbb606 100755 --- a/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter +++ b/luci-app-openmptcprouter/root/usr/libexec/rpcd/openmptcprouter @@ -1113,9 +1113,7 @@ function interfaces_status() mArray.openmptcprouter['model'] = sys.exec("ubus call system board | jsonfilter -q -e '@.model' 2>/dev/null | tr -d '\n'") local board_name = sys.exec("ubus call system board | jsonfilter -q -e '@.board_name' 2>/dev/null | tr -d '\n'") -- retrieve core temperature - if board_name:match("^raspberrypi.*") then - mArray.openmptcprouter["core_temp"] = sys.exec("cat /sys/class/thermal/thermal_zone0/temp 2>/dev/null"):match("%d+") - end + mArray.openmptcprouter["core_temp"] = sys.exec("cat /sys/class/thermal/thermal_zone0/temp 2>/dev/null"):match("%d+") mArray.openmptcprouter["loadavg"] = sys.exec("cat /proc/loadavg 2>/dev/null"):match("[%d%.]+ [%d%.]+ [%d%.]+") mArray.openmptcprouter["uptime"] = sys.exec("cat /proc/uptime 2>/dev/null"):match("[%d%.]+") From da1809f6a36a9f8bbd616019c51577931965768c Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Sat, 24 Jun 2023 23:23:23 +0800 Subject: [PATCH 08/20] Update fengshan --- openmptcprouter/files/etc/init.d/fengshan | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/openmptcprouter/files/etc/init.d/fengshan b/openmptcprouter/files/etc/init.d/fengshan index c6e8d24b5..1aea36b31 100755 --- a/openmptcprouter/files/etc/init.d/fengshan +++ b/openmptcprouter/files/etc/init.d/fengshan @@ -1,18 +1,14 @@ #!/bin/sh /etc/rc.common -START=20 +START=99 start() { tem=$(cat /sys/class/thermal/thermal_zone0/temp) echo $tem -if [ $tem -ge 60000 ] -then -echo 1 > /sys/class/leds/green:fengshan/brightness -fi -if [ $tem -le 50000 ] -then -echo 0 > /sys/class/leds/green:fengshan/brightness -#echo 14 >/sys/class/gpio/unexport +if [ $tem -ge 60000 ] ; then # 温度高于 60 风扇开始转,可修改,正常使用设置为55000 +echo 1 > /sys/class/leds/green:fengshan/brightness; +elif [ $tem -le 50000 ] ; then # 温度低于 50 速度降低,可修改 +echo 0 > /sys/class/leds/green:fengshan/brightness; echo "temdown" -fi +fi #多加了fi } \ No newline at end of file From 1a9928d64e7a5120247f08577e7331ef0b157745 Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Sat, 24 Jun 2023 23:50:23 +0800 Subject: [PATCH 09/20] Update fengshan --- openmptcprouter/files/etc/init.d/fengshan | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/openmptcprouter/files/etc/init.d/fengshan b/openmptcprouter/files/etc/init.d/fengshan index 1aea36b31..3fac7c894 100755 --- a/openmptcprouter/files/etc/init.d/fengshan +++ b/openmptcprouter/files/etc/init.d/fengshan @@ -5,10 +5,13 @@ start() { tem=$(cat /sys/class/thermal/thermal_zone0/temp) echo $tem -if [ $tem -ge 60000 ] ; then # 温度高于 60 风扇开始转,可修改,正常使用设置为55000 +if [ $tem -ge 60000 ] ; then echo 1 > /sys/class/leds/green:fengshan/brightness; -elif [ $tem -le 50000 ] ; then # 温度低于 50 速度降低,可修改 +echo "fengshandoup" +logger -t "fengshanup" +elif [ $tem -le 50000 ] ; then echo 0 > /sys/class/leds/green:fengshan/brightness; -echo "temdown" -fi #多加了fi +echo "fengshandown" +logger -t "$tem" "fengshandown" +fi } \ No newline at end of file From 8d628dab4bbe7d972867450e433ecdc3912b60e3 Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Sun, 25 Jun 2023 00:12:57 +0800 Subject: [PATCH 10/20] Delete 2091-omr-wifi --- .../files/etc/uci-defaults/2091-omr-wifi | 23 ------------------- 1 file changed, 23 deletions(-) delete mode 100755 openmptcprouter/files/etc/uci-defaults/2091-omr-wifi diff --git a/openmptcprouter/files/etc/uci-defaults/2091-omr-wifi b/openmptcprouter/files/etc/uci-defaults/2091-omr-wifi deleted file mode 100755 index 2925bb104..000000000 --- a/openmptcprouter/files/etc/uci-defaults/2091-omr-wifi +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/sh -if [ "$(uci -q get wifi-iface.radio0)" != "" ] && [ "$(uci -q get wifi-iface.default_radio0.key)" = "12345678" ]; then - if [ "$(uci -q get wifi-device.radio0.country)" = "" ]; then - uci -q batch <<-EOF >/dev/null - set wifi-device.radio0.country='FR' - commit wifi-device - EOF - fi - if [ -n "$(uci -q get wifi-iface.radio0.network | grep lan)" ]; then - uci -q batch <<-EOF >/dev/null - set wifi-iface.default_radio0.network='wifi' - commit wifi-iface - EOF - fi - if [ -n "$(uci -q get wifi-device.radio0.cell_density)" ]; then - uci -q batch <<-EOF >/dev/null - delete wifi-device.radio0.cell_density - commit wifi-device - EOF - fi -fi - -exit 0 From 2549ddcff2500951afd07cc3f67ba3d80e1f725d Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 28 Jun 2023 18:26:23 +0200 Subject: [PATCH 11/20] Use PKG_BUILD_FLAGS:=no-mips16 insed of PKG_USE_MIPS6:=0 --- golang/golang/Makefile | 3 ++- v2ray-core/Makefile | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/golang/golang/Makefile b/golang/golang/Makefile index 1047d5b6b..1f5ecffcc 100644 --- a/golang/golang/Makefile +++ b/golang/golang/Makefile @@ -37,7 +37,8 @@ PKG_CPE_ID:=cpe:/a:golang:go PKG_BUILD_DEPENDS:=golang/host PKG_BUILD_DIR:=$(BUILD_DIR)/go-$(PKG_VERSION) PKG_BUILD_PARALLEL:=1 -PKG_USE_MIPS16:=0 +#PKG_USE_MIPS16:=0 +PKG_BUILD_FLAGS:=no-mips16 PKG_GO_PREFIX:=/usr PKG_GO_VERSION_ID:=$(GO_VERSION_MAJOR_MINOR) diff --git a/v2ray-core/Makefile b/v2ray-core/Makefile index f9254e896..113c70f2e 100644 --- a/v2ray-core/Makefile +++ b/v2ray-core/Makefile @@ -18,7 +18,8 @@ PKG_MAINTAINER:=Tianling Shen PKG_BUILD_DEPENDS:=golang/host PKG_BUILD_PARALLEL:=1 -PKG_USE_MIPS16:=0 +♯PKG_USE_MIPS16:=0 +PKG_BUILD_FLAGS:=no-mips16 GO_PKG:=github.com/v2fly/v2ray-core/v5 GO_PKG_BUILD_PKG:=$(GO_PKG)/main From 5ce0bcc714b6a237f38c6365bab8734ea23ccb98 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 29 Jun 2023 13:21:14 +0200 Subject: [PATCH 12/20] Update omr-bypass db --- .../root/usr/share/omr-bypass/omr-bypass.db | Bin 2342912 -> 2338816 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/luci-app-omr-bypass/root/usr/share/omr-bypass/omr-bypass.db b/luci-app-omr-bypass/root/usr/share/omr-bypass/omr-bypass.db index 2c0740b08d461188726e968e50ddeaaed0fec8e5..1c03dc910688b0de0eea1497b88101f77a2407f0 100644 GIT binary patch delta 620553 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

^JBfv)({8|LF~{Y97@A_GQ-B8bV!q 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%0DFjg;F?3naz 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�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 dfN;_qG_j2zTg@(JDejF(%g;>_ z($MaLj~#qPROw9yaK7sNrpbP>k0$Z032#D7+wYAS??Mg!-eA28bk$(ztKdyg%+u-b z9R|E}HRcp*6X*5L(fGIEaW)=O(Z(0wqH;ce3xo6NTcErB7FBuG;@Z7!Rq36s%5PJZ z)6~U+sfzv581YWgrnkXAS;yYS2p@f$p5)lq44}Q>bB3s!(ef-mzTH1^F2LZoy~;yh|`j$?uZy$w7GX#gB;!w|pZsp-O0i zX1;4}?p@?QO!fbQNe~Uype+dg_jeI|)O+043wn>9_P`cv+ulJszr{4oJ5USXbCt(M zozu@U_hoc3`QwN%!_Z%+NYlyp(4GP?FvSbo4x@e4m_UuTV_U{;M_PloQ*rHLaP#N& z_S6o8d0yS#ilq5^duZ(`G~?gx2z2FU$AUknX77Wy>HE-gWwR&5%Id0B#IZWJ_kB=z zi$oYyPbcNPPxW-nU9K>{rnC&kAR3Yp zSk_2wqDB{-dgtEd1$x3*ueZ^YS$}=be$}9rQZo(p=`MZ*Hy$PXkKCQ4e0$i zm)UJgaZf;;cd>cs>rk8}=f~89KBV zYNz8-m#=9`&UMW2;;AY~3{9|{Q}CyYVm%qNm2xYVTQ)Cjb&4%}j zyDDlQ^mkG7eMqa>KAK_CRW6$E;!av=Q7`NR_|QHcZ13=dcpfZKdZNpba(iU~#Fk9- zeqf{a1N+_`7QCD7N3+k|@pz1#)_VLA+WvyY9obJ+e6XKJwzyGXn5DK<%EzQ;S>CFj zv33*t8UJ28>Dc_{8v7X>kNFHfH-2WV=rgk3JV4LiM4K|Lr7do(W0|boJu;X|2V9W> z4GRh7TnVqWFSd$kpiu`%|GlIe4eB~Y&0AIMU{gHHufOJ{8=a> z-cLAESc}P8cMxuC%5~rAU6Sx<<@~9Uc8K`uIJBa(p(?8>D#jTuF0QJHhbXCv@=q4x zsH~1}&|U63L{Ya6L9IDZMknmq!L$p-!>j>tROc|&RbCw}C`ZrbbVKG+-QhSvLkj<} zx_y{6v$(V)z{P4yfQ^6_$EfWQ$l)=wBbdOHBdE`B+s#%jF01_Qh5c)!j&FeD%SUL) z^;N2VaCq8LSiXG;>sIb471ie`((Z5+eOP#uo%u;ep|}5KN1HfRc@&)q*>~e8`~K{V z-#O;0z#!+zJ~|#yQi?^;K9>yE$|7cAmJHGdg?|QW?T=0?UNS)QUvY%Bq`$s94!VAd z{ZC<1UsZ(>d=5(oK6gb1KL5W$aZ0T9_3*j3q=(MF z=P4KLU1ATkBG^Jl3du){hb#6A7~3Ds!y?`#-E=#>gYS<+tJ0zwlt>q{iF<4dNqTRF+Ab6+x$X`{Pe zLg$??5nuFYk=6>9v{HkwsFi0m@GBIerIvohEae&P;7jj+1>lXZkob4@uh`dgggo8% zHAzulLvz<3>A}F!MBdL#6_zyC+OL^et@)a=|M<}pX5=@-A1^2y=ys69SbdcY4o$Rr zsHd*qfU3(kKv&#uW{uZ$(YZNei*VLNr zj`l7|()@2>0+&obk^A*;QJL?)h2d)Y$KtDM_W>3QN}K@KvnN<+tgIm?h_9sGp8>z* z1mlDQCt$9Eay~OvUc&jp1CCs|f^!lR5`7Z>XCJTu#F7NPcmN$8aS{n^Jc)2tTjF0N zYR^d<>K)|YkCy5>MQX04CY?fA<4#c#<-hPmm{`hc!a+}>NiR}ec7Si)DRO*C4yIjK zPeC2tXimE-q@AXJNILC`WnH1mX`(&qa46FHnI)WYXiQD(G=-i$O~z81OcErP)J;qA zKZB+;KSR+q&!C$1o7gaTNs#8Bp+a!HcF57*0Bvm&YC7ar`WbY>cf_`p-_O|0;PX`f&FV(&QpPdW&3r6nBvT_aE+E0X z^jTVvbFSz{On6x&xU{A6KD26E`i$bur2lRCyMAQ0WodJbv#2`XL&KJjJf4yuX!-e}!JM49pf{a!sS z{{e`)+DV`tKhUvV{sFOk_XA>i`~&*OgTp@pQA^D&NY;G%acHWk7wkJpyDg}ps6=ZS zORFpUM+(UL5rwJ#6RH#Q6Gd%EbmUM)<9?!Y*n0d4GGF`&4xc^|iVav=QJ089cYn!n z6ly8U1eY9flvBH($-@A^f&@IB!%3odX}pG{VNv$~OhGTFG55XkGh81?vsSh=Ml~-0 z9j$xJw)u|I+zXiTvU=?T#73(9--Spbbn60Y#KE$QfQPB>MTlU5;7x0rOGCBDqCNWH zQ`5+$A$sgWBfq_f5xay!-n&TIz1*Rp@?1hm7q~+`YIq4n{xYhB2i;l9fh)Ho6*R#e znh@k&YLBjR=!=5{Y(3q@rY;Ro_9bX?Ytr8|#O!x0Q1r0E7at~D+u?EE7b5peDG2uhptc$#rN6B zWXXKFt`g;c)mrsF8{#aPt2X;+ku>EwntK%lbFL!JT~}$5v-B0vEEN1rJVVEl*AV4& z^?mFZmud3yN4>5gffug2&R(OGGuJ4%LcS^T65bulchV-P`E`(u*Xn#5 zB`itN2ZeveX_qC8Rd&8J4_Y!tcfNBfYsqLu-GISS`Z=vIVx+46?9ebmFW!K{;hM#_ zKDq%ZyMOk0(vJD_8uKr%e;8H_sz}e0=uJ)1wR6Zh>?U%~{lJJy<&wrta#zzj3##f9 z3##af1(oIVD?uey{FS0Bs{leZp}MJbYJ&EX zh#I8E%k_tGof@aUzmY#yi++R07!5cMBLGC}&PQg(Qlpd(fbRW<@sIy63rUgMz1I_8 z0+@)x_KvS7Zm1o1h1mcvHC%V!aC(naUW(jhs-9X#4|l=fx&KoC6?S`UnwjcR%x46BCJ5^9|0=vZp79{&y{dA~zRdV}Cd-&Cg2e?UAhX}`zF zIpq)VCscCVP&L)1?Zg=;{`lb~+m%14^BEUul?8two7XQ|N1s|uo&O}U)1L_G@4~1e z+DH`30muGCmwj~O26*DUsZZ(OV;Iq5e*t>w!ue5(a*;51FbR_n?y!3aF(L)nR(D;Ag=H(A<6=dmi+W!wC z>&A6ktoD_EDBk@qg>=zDw8jYR%py24Y5gya>iQ>)$tb6zu6*Ult%H2Nc2Kw9cl}?N zpATkszYX&ez01ldFrA@RKsxyb`dF)3=272tnCz2I#jj1LNi9sLybsb5NGYARq*E3V z?#sIDzv=Lsn8BPPEQ5a?GFb0vk^!%)e671##x_m{Oa^FA1{^ao@I{^p-eoSGu12$c zlz|FY$)vN3%_LK~a3@o7H47(kOePp-oQn+8TKo4(xUG&XE26z5^2b*f!p#IM^HIKm zSGo_be)qxE^*)sMj-XSRb{{*mFoI5Dqor<*faGKMLH13Am6SS{Rb$ATBfm()nL1n5 zZQUf%n>veiW6aG=9wUh~J2OLP9>DqO2cZ7?oZ0KtX}W%nxlZUq%INeEIW>I<<}a!R zTT@A$%uQP|tb9m@qn7%?LxlEpqp)yGouJ2-nrEs1d_Z-@dQ(%>?h$5voKhZ9{o@`% z@Rmo&^TkJ?^*me5#@VT(b;VLIKVp>N%7WQ~M=X{dE%2c9sUvi~0CNV|a81erY+@E! z2kv#q9jXIa%%(Wtn?+R&*7{;L9!ed=!##WtR3`#;%x2ER)<`I0nbiK;kd1Wu>4+sA z&ZfvJMMERW)JN_d(7SR#-#CYM-%FK>I}*eRJ%2Pa2YuR=;|k}lW}i`cdbip$Wm>RJ+7$o6&a7N5^;JATSlRE=rU7 zBNy2P6bp64(q74VklIc`AF;@g=uK^_IeFAy8`i0yeQO@FKc9yNx6)nW1D}ljl6et> z<&1*TVJulujm-4?a$F?u@loHhN_rpkMa=$h!W zb52K@+E~G59Vs+YN9o;h$Q%mhSWlY&X!*Uk)h#N^$pnpLwt3y6v_R=Sf&Z_HnbxQOfFN*=%htWjL43 z(mEeNW~w5F+8W#pU9pJi^6_<7!05(aw33!hRcBu}{edqyzAY7stywl%8!c*suRBPm zeccf{>g#61ad;WCDa$74{MkZ`M!CBXXLQ;UB(Bci@HmzLs54a4t(9bk@BwD`DMekvMA6m6s6=tMconD-^r($ z48(bt4dGo-WSr<-Hdyh+;9!v27K5LGnqXf8bm>boaLf8Dzwl2#-LQ1bFMYBR-bdqa z@GsuGjQMtPsO+Wvp^hQxiDNnE&+~e>npMQI9=cwb)LlV-P!#Cr=9Q!PQ0vK;b>q%0 z*}H0iA0>BDQ;(CmvrgG}Csiqf{{QQTRQi{(Ze>{qHT8E_zz>x>Q16v-j95FZ_J_K* zx?RRGVQo|@%)x@^6H92N0fpbss)LK~mf}c{-TQK%VT6bjTHuKnoCjR)QhMdNlDHIg zA<-~5B5tahZfH(&Q>FFKa6!d1VmQUQws6I@GYa zY5**BpJhRlN@Nl4xc6O_3kjn?F zY$+HRq!y*XG*F}MYk=04qP+e(bJDn6-cNxv5dQQ{D-Bd1RV)ouZ*?Nz(GTaz47**4 zlh1A+^JLlbo{~X4k9%F(^`X)zUDbcBww8C7UkEABsXBqGg}BXaWqOLAt&A-1%0+hY zcj3M)#dp?;eI~r+op>$toL8F_GaY<+q2-P%lr? zm~dcf@UjM_RoB38of+=(YPuFqF;!L4F#yY}s1k3@p^z<3vCh*z!W~f5{Bo+>*bv(Z zSYA;ZBEVBYM=dC?>qi}nvb>z~x0?A`&bhTnQW9|F>gY+l=0{RuoaV#49I!T01 zM8ZdIq&rIYBC&rJ%euqR$7W^8TUH}1h{SI$0p}IVLQ%M8zYEEb5Qghq;>#%Op2L2q zVx6vHxkrZ`fB;6;B{&qUr>ymVi2REP)A6 z^sZ>6f4{LNx}u@x(OC3a0-XMw07AUGmq2?dtDYhft*k`Lm*}=rg<}#yG}$P&opqeIsWGPMMMb?(p4=6*r#x79mv{3ZV0m{e>*kLwo|{Cb z%n9BVJVa1|o~KO(5YMYXzdf-6QvLF@gC$mnDgYg$`4yb;?TTpmRfOs&{c_r&x~z(y zDZ~@0xfKD8&^7{Xtq79y6=63_FJ^hlLs1#+&oV7q5vm)+s6i!4{Nr0Q|0_b2lugtN zl@RFgY_nY}N@<}*U9zZ;3!_TtT(*NDSPw}92!}X1RK%>xpz4<6U z8d*O~^fQ||Tk9BZXhtM%8M;-C;-{-bb%JTyam!9* zET5{g&H;qwQ#6kR&8<$+c@=E>wS1Dkt&W~>Ajz^!(2*TZlO3;yHTX`^;2P+`pc-gb zkA`li0~o9Cj!<_{Iz~U$fYQ;*HrP?T2SzYb;kO+WJS1G$GY!|s+l7{E7(Qt!Z0Nr0 zNi?;fDvY-6ydHOCp62|19iC_MzEGK~t)Qu-rpa#l-DFC>)i2b}!@cl-N9r_W+y7(g zyaTH&mcMTTq@0rk0;C6$&^sg$dJDZbrPt6qgx>L78>u9ed`SW%=v5I!#6}Z=Yo}wE zB4S6H=(SLU_cPCl_xJv_&$Bx_J3Bi&TW6`jl?oFr1>v^v>QkLgwQrbV!6m~8qpJyru-Iv+7gYzht08rqcf zD6O);NPXJeN#z!Ib7!1L568$Ae*V&wPFk%QLQ+}nNh+V$+x?8SS&gw9Y-6<&N!IvuhXqQPH7h4xucb{xsYB)Z#D;uuP!%- z!CyCbxzHv@w?;b@KBT%Wpl~(kKU6Wnvu2e-EML55%}R}HZL|F~EA*zpEZ5g9K)g&_ zTLOSeSgQIhiC6*`!M|9G>~E1?ZthK9sG}CKKo>y`n)!OmpN;vzRtWen{x(rvlco`^ zVE9~lTA>UdZNpf%&P zD-R5RT3my+D5Wv#(H6|3Il`bOqm*xdELhuuYJ?K)46eFo&2YKf(LSzrF1Ihs$gg`v znqtBjsvVhzXf=tWCn)U=w{P$ z+fyLoo7tRqowl#QIqWx)%HZ7zassub4~55jG6FQK6J_};uam20pm|i{B(XVfCi;cj zg^G-Fx?t&L^EGfC3)&XlsHGcCEcGac@?Tpm^Sq_5H! zmT#qI4rDy~tFyIL7kIW@`v#hvr7zRPfhM=TC~ZFCu-4 z8g>V0vcBx+urGa*mUM?b6SbK@McpanWOv9u+#NcOceO=dda43?kZGJ6S}+#3unt{g zw8;KPtEdMB7WP2O&-5VckscIX<{9n`Q1l1|_XIz0vG)X)1;Z$BxkDA#*}*bIC8W3p zm)->68p`Fq3}q;!M|8#VJgksj;1BKvL6Lo}C#Mh8h+ZIN+1d*LZbVq^P~rXbKA@~y zuM@9pmgB!eZF4NWx5^K5gf+dFM)xLhRBsY5&vr-oruWd+W{yt77K9|$3RjwWVY}+h zrcNt&(dDMJf9pQ5=etTFPR%+gy$?jBXqN>Yb+!+AJE)--S9`_w<-eU$`nqbm+Ink; ziI7sGSm{u^Hp(=B)_R#hyZfSUH}(pPHlDTAoxY&N;He)KuhP%O+oCp#@s!+l9*#;+ z)^rl=a!@}oG*!pJ-o{N*124JUmT&6iNE00&4dHS95wp9a9p*LC?EYkHs5XgCtsAK5 zVW*Pyb%c-nBf)_R9N_vDQSQ*sATkzflJ{egGW*dryADLSmk*>HEYPiP4#<4@401kr z`EQV6%SclnK4_JUxoS8Fa_6Ye5Nq*_*_u1Vs}5#q>mbzAmO)VG9%2oZF+jnPH>AFb8in&2E}Fv#i-2HD8L)NzCs4F+I1-d?H2Fx?#H zcM_iEJsEwJP7?NdFAa575A0RCPr$o1KXO6+%utxO zZ@5$I9;!MFVX88WX^GDWYwe6~n0`AP=&I~t2vryD0fbd=R8ObaPWWN=GA2cZgPfXm zRL|kmtb>kvo3yXrtkX7SXM>+WXN;14dBy{v(j(s-5iUBBO=c zbwd6MMnL5HP7X!M+TF=P*G$19DTha-yEt-@q@g3BFj31#f*un`3mU8E9H%p8G}2Xz zXs8OK2pV7)Og#F#zDABBTRp8N-Z9(bARKcJ3`A#EjPlK>gBm15ZLHP8s+ad^O8{$<24$l`Dk?5wK)uYNL6*+835^zj&}KB`^q4YpwpwFH(n3C9F0@- z82)iEFb1Y~7=vzD!Cca4idDuKXo}HGW5^h-vp_J@yV%)baHOh?PlexuoWO=cwnp3ET{ zFdoE%wQpru94T1ht+bZOl181-|yY zj+aJi*0J8Rsv?|mbjua?w357tsvaupeMYV?WSh7ROVy|YJuBWMzrQ$!=e_Dae1I~S35IV ze@&)B&D3!ktppBq_Y_z4pd`99sO-IWUIy;Pi-Vbo${>Ya@X{1eHrCl0NIN9qns%1c zY&fT#<+Moyb({)heWj0gIz(nYWmrUAy+jaL=O6nfT^`RVFV*9I{~{py!Z*P*TCJv1 zrqS*-G;ta;&g#k{Q06pb<|_Coe5ZW6BI9_=3O)HqJ5iB9`hRln)% z1ll`mUNaFclB#o))0yz{@YD<SSN1s%13F{(Tk6popVb#=@Xc?8N~3kj{{#)3e$5xj&mZ+$tWIfTox^RQa3d<86Rj zq3LtTzFfJMvUU#Cc5WDDs(LA=v(UuBPuv76DT~YbX@GWDzcg2McQ@1f-Z$(t_exN- zZ&p`rN+UxT9ZI8~oporjGlS0Rq@sn!tgI9@nTI5F)Q(hA5Et|YNP&39Prj^G9OA>>CR*?qL#X}n%U~&`P6>reCF@X z^{zoA>*{<+!gurnraevRBF=#q-h7V4Qv0kVx|@SBQLBMKzVCVe8!G|SKs3^g1z>2X z>64vVO;!V)Tjpe`uLsM*st0+pY-Mj~o3v2stnf%WQdV8{TJB`8quI+H=-T>aAvL_Y zkQ(MsHkFsf+0ar4h0x1Xv8)7rxQOl$uWOccbrI4TwU~)O zRXy;cuAO^7cg5X z{$PBR1}s4`-tHQ1%j2xdDl*{0B`ClTm#_)+mVMQoVw3Q!Q28%~VHMPHDNV}GlKq9~ zRsgLKqV-I$tEKkDLA_7qbWS%G?)57k`;#$n4`u{<{AH3>~rUb|4!%UOQv zIKx3!PH!!9)d(!>C6(u>#_gyQi5kr+gD$b5Q@a<^zkF41xyh^gFLx#QW<8`?D=1<1 zax`h-a(4CbMY|kgR_ZGQTcLwU3_WdP*oB&cp!kxh3ZcbdMzjbK?6nfsR-YDT2PTc7zVo;eravGj>KI-Tlt z=hZB3l0eGiPXY+lZMK!xHx*^PDYYZ%zU1C6sijDHQ4>0xG(;X%Omdt5Pr z^&!v334G6dl>RsjKlr#SQoA3Anpznq z)!A5XXE@opQ}hG`S5iiXldGb3XE-vD9jeSHXu6Ci$aU}ueFAEETK!3e z&>-&+YVR2|RpPIHG(3cQB-O&nu9t9$o;xQfxi-8w|Rs? zd#?LO1d>?J!K%wAU2(qIWi|ULcsJ`QD)RR4RgD|I|CFl4Cn_ciJ**g$_SX>!ChyU%Q5?Ez{*SGz)JJUND|y zEs^Jf)0r2mPdY5=osM7}xNWE9Sqrr(9pnr2CMg&rCEW39qIoKK$H|`={10s};T z?O=w<5zJ-0d>yWr0AUSxda8qLsBULNz!1gdKyB3=sQqrHqirA2eUy|D`LJ?wpf1}I zQx>vGUBi>bgKjxYXa;EJDrOH4auA5ktDJoO)Mu@$Cabu*^=;$X@l>;C0eZiW#W0#AFJUP+mWmJ&&HI=mQSnuaVDI?vfKu)B_Nf+-*Hq@PAHyfk*Nyutb?uP zmHH-pj`QS%=<>h#s_MxJ*41^c1dL!2uJHBf47VDu2N|!?-Zrk~1ZvrO$_P-2Mf>Y` zfeB@fpKcVGq~(-T@CI;~RpJIpDx(pFPBf2m7CL}F+Dy7{&OJ|FpBg>k-Tz`KA1JIGnaIYMeK+pR>pU#iI>xyw@FY&U3WyaB?Rh^E# zSnhmqEmC4W>%xVl>GqsU=^kA60zB42z|wp)%l3T6+b#K!;{GHoEXb2xYO2J#M4oOH ztpjKCaHpu)95p5goQ+7+2&_krjEy$4z3f?9D#*r(0qNQzB&PWS+px=?t{*IA8m6+O zxHgf}dJ|GH#XEE)VWzVlhYX(V$?EfgQ{_oY^L|X!5zBLU6GXoAful6X>nm?sDmN5K zYfwPi$O0-bpnyhu5`iZ79v| zqs(<)0(+~^W?HkC&TjTb^i(qsi^nIKZ3HcG$d zU}&wEt~oec>C#qLwV;;p&bv%(%HUd;MIVDJZWgbb+-EmeyXy{gvSt^fQf3vykiice z0pVF~?{pyP`LByzK6IYTB@kUk{@Z9eUp2762Y)24n!alv(voddb+tBI>?$3#zm=-` zmeV~s;d|ON^wVH(_cZKYrjjSE+?=Ia`ZVP(d738OWhsmG{?k^GoJG3!G#h(AKF!6O z_-9C2z!d~1WxjF`lQQBNQl|Ju&`ERBwDTEgo2#?WI8&@PYhYS+PtI&r`8N@>boXzE zkeN!j?@ZNlW?)N;+A5u0;djdM>kNByrm6m`Fq+&`^*6b7@87O~vdP#2>FD?X^kmLt z^?sIGPSV_GSyBA+A{Q@UjeFWA^*IxC(9*~2YfCr#Z91jBkTqbtlRi%MpCf&&20Tal znEy);eTQL}g4w@*4zfq7*FFZ8!_UE-75l7vxnv~%>L<;}IH1c^WK2#oy9-{5f z!}q~D@jUn+(Jf1RSgpTsl-wY--cIU3joHowZ1i@Fp)id8yj-A6JxbPA`po0o*;c`UP;WdI8a#{xgS| z@Uy!YJsjRvz^nts-c2*^(_=`ZNBqZ;gDz^a1375CgQ`Zn&5jjXzmrz%U~ZeDtvf*7 zQ6mbB89SKxZ(8T2X%GS_$8=o^b*u9jO2c5HBU}01@3q9!>j!a^o1|6P4G^i*vfj#z*@fT z2v{`*?FM;*n(St{!?Et$PT_Gn{I<7@sw%XUDmr9vv3oD?X4=95TZT`k`rzMDqBL07jY4CqPbviO&Iw!yNti?&;O zXPqQH&|VjE(&b_7xBMxJ+)H{#wcE=a&K?)?=C@71{j^zot+DiW+C>ofzcU@BZK+_I zWNjP$u@{1PXmlR|=F`WVTDR2neeh@6K1S)neN0wL1wV;#?&Zhqs>#}9o!U0vPy3}GrbK=(OufH}mG1GGuUqy~Muy1mZy2L5;O=?}?P4M0?vO#Vw?xo*^vQckR ziSC=3Qb16Qf}V6van?rb6d71IjymArja1Ab@ZeY2f^em7cIXX*7La5d0`H+iu85#Y z-gy|0G_o<_Q-;TKJZmfJt^wUKpoVXu6Dn|zi?N7aflbOmRNK_I=rTobv7F=yoP!SG zLE3fDy6#%`u89fptaX)6WiYX4$U5$_(SL2AdLD+L0L?y(l-M>3Qj*w;y<7P_gJ&ks zT0gw)Qj>C6-MY&8FhYEPgdWBF&_|ul(D*3X2jRpQMppCW4%AYMAE4r+u4*nDAJ}5y zQ8DHH#cCtYliN>Mo`C!Dp4`4#vCSyV?W2-y>{xhm&C(liUO*rBA;THydg;nGV^nTW zm8ZY((L+c6Ly6rr%=_O>=bpC;=XTYD=fe`pdvd!_2?q;@PE>SjIkOkb?W`W#9R%zr zz72vD9eJC1Z^wUtmDoOjj+@&-f$vbi_AEB2M>}0kb8@xS;&;f^21mT4w$>3#ZKW~! zPHIcJ-sQiAn!Jm8Yy2+4TD09p-P~j?d6#_6w8c_3TgvfwSwbfLQ?9uMI(iCIA!tmL z>ph?X-vg@Ud-T!9TKj^-nMVKPO#HW1Y@p3;sG|2k+<@meAgI1#{&M(KPbq&fFZO>Q zS!wk?>zz7E_omd=Zc-qrmNvgn7H+z|k4SGj=WwsOPUJfXs;S8b@Fl^PxHLse&L{ls z95**!ZRO;T)7B5jxa9+mD0n>oo?Q~jt)e{_9YnEM;etIzcf9}Dw14F+-gBe0;zPuE z`G+X~9UpR-SYlsa-m`HhH(XaqWW`tE7>ul}=Eu<9l{EYqkysBNgDoq$7wya9B6To+ zJGUOAf))RWbof?YKLfxXO2~0?1uOA5e?j>#VomDFb(eCQ*Wxa-uSQK=+F}5KI(i)J z0m=i=M3a-J!!~^8`l;aw0Lp3L3Gm^~^arQnWmx7ob@bKPO-_uDE}wA4yK~K9qj8H9 z@wA1U_gD3-U9Ar{vAT%&tX-v^C&9K-vreL@?U4!tZK7@U8T;viJcRczL%VjFE&#y} z$*HHD|0Sw@ij0fZ+k!=!bIMuzd3P-;GuQ0Gn|JOQU^`7|Y* zCVsBEo<{4<(ah7d+KkgAUwwsTcFt)O*OAlg>(A622*4l^H{54jzi=da?+kRbQI+RS zB=TCT$5|NFO0&+oYPrl;ROx0VJ@|x@NS<3kOEHj@MK4mIa&6C$m z4L<@|Q(gMRDwUUn_g;`OVOiaehJ@#v>Oj32~ic7i7_M#nAgn8E%HtZshFL8a$}9Si40 zvcc+55uq`kfgl`bxXyo=JYP7KuB?-vA;Bj;gZXzqqhnXp4R1=QT7M4V-2eR?;>v6E z=T6QLc|Lb?V(DS&LHgx$FuMtyXcwM$fyWc|7f5J;MttdH^Vg~`O@j0MwCzg=u$*pw zLH@G5u;BEXc(C5D?0=a{Q4ItR;^VSWo>_BmSo+9g_??zJTUs1cL9n0*g`@1BEa<2KsR zox4!Wi87!CSmLs^==d3Bz+uqgVcIo}qNL5!0n(7)ug+8FxmtSHq$_t0&*HFnt8)Q- zAKhiwyZ;47y}$Ufkz%GUfA6f%a%bqh3(z_plU#ynnB+oX`HRd0%Ku=u6mq#X#B4Cc zlRMd~8WNeCG{s@EbK5$XJ4B=!%8A(MlJ(?8?wqni{F80N=8o5Wk3&wXQoaKJIQ4$T zQJiCy_6k#v^snIA{;xOyfB7rO>vqp33%R2-_FhTyO~^%7b7 zU*gDcxMp8s*Kb%UjO|47G)%DVFXj$aucJ;uLo^o#=O3xa&6cmRIjW}nUqeWOl8Y>T zUA%f;hHr72bD8d1l^sM5+7elVbu5b?we^>ojGwqn+wm0dMJGcHHYH@hk@Gjmc;j#2 zRJjc{V_FxfW#1qU5!yxyay@$k4e<6iV7T`Uo#5IxEFq3>uqDpAN^0{h%xe8Dm7eu2 zB97JXOF%#VEzpO)r97Ub*zJ_ZUiY^M-W>y7v>R0v_Z=`LyB$1k&HawD@XY`)V!AF+ zZ+-_20gB5*ZsR@c{B`JiWSJyfu76KbIqiA_&JXw=A$*+eXEqwPd{2dZb@B>05t&b%ydl}7vkik0&GK&dM<@+n7?Eyse89VB|mvQqvvRp)nc*TX!3fu=L{9#xB@+Rr_b*E+%6@P=8dGaQd>hWex#HOPy8S=*C zN7gAdRk=4D=yBS6!%Os7&1C*$gp5)7tFBrB_Nxf-%t^T)@wHI#cNx6NUvg_YKDthSVza3oN zHSGpvchlM%;OeTe&pOdv^rc02)&q;~q|?tjEJ#uBn+SHVn@HE{n>11fWjyC(Xs_MR zG1uCE(-pG!>P=U$4?-bdiF{!1n1zi(6Bb+eUC8d+!k z|5@4kIu{s`|2wVF^mn!;XQne^P}Rf6}m{)O`nf5Ii>NG-mM3wif8(vx< zub=YRS7Mxv1?z_C-nV23|BDO_z6%Ry&uZNen%sLdvgbGFBy8PaJ@pr@@`zsi3kiN$ zXa1tp(|}?&Hp*Cngf z-vBkk#+MD&rrug7vb#87c9acAN!m$*cKl7A^MBLXn<&K@jMp_*?0w2_#1k5fEFJFy zF#kTy-aww0xMe}R*lDvf4k~SZc{>1ES5N2eLu_4k#|i4F&i4*0dB=i@1f|u|tOq32 zRNe#F#T{-i8RgaYe)Ygr$%n1s?ZM$zx%D$OGC17sSgoI-4nA(4#rJUssOE1BZDV}g zt}?s`rftviTJ!p;3cO{=*H6(&A9oF%@Nv5}m{TvJ*cAS+QLvtQM{u~c%=!sh`a9eo zqR4=Wgpt@zFU(YazNzzX9jrvTio%0AfG*!*7t6kaF%|bt>nsg6NJb=dP`>S4cfI9*S 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%0DoblsA#b+nwFXvbk{(g{&e)t!hR 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%0DEts?MEq5Unh=& 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%0AWVfa*Q~Q+wUaIt!sQjdrRK3*O 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 -kmJdXJ*v$nHIIuAzDFkyoJJ$aWaQcbWnDtI~k{ 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Ⓢh8 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�{nF~4v^*3}e&OUT@1RT;406OH8za-6 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%0Ahz06)_6J4@IVH7KQ?V9`wmuPT~dVW@A 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 DamB+> delta 619849 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

9M8r5I27 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˄uYaB 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 Date: Fri, 30 Jun 2023 12:50:43 +0200 Subject: [PATCH 13/20] Fix log error on gre tunnel fw --- openmptcprouter/files/etc/firewall.gre-tunnel | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openmptcprouter/files/etc/firewall.gre-tunnel b/openmptcprouter/files/etc/firewall.gre-tunnel index 59d161781..b68ecd63a 100644 --- a/openmptcprouter/files/etc/firewall.gre-tunnel +++ b/openmptcprouter/files/etc/firewall.gre-tunnel @@ -6,7 +6,7 @@ if [ -f /usr/sbin/iptables-legacy ]; then IPTABLESRESTORE="/usr/sbin/iptables-legacy-restore" else IPTABLESSAVE="/usr/sbin/iptables-save" - IPTABLESRESTORE="/usr/sbin/iptables-restore" + IPTABLESRESTORE="/usr/sbin/iptables-restore --noflush" fi _setup_rules() { @@ -39,7 +39,7 @@ _setup_fw() { [ -n "$ifnames" ] && rule="$rule -i $(echo "${ifnames}" | sed 's/ /-i /g')" if [ -n "$rule" ] && [ -n "$lookup" ]; then $IPTABLESAVE --counters | grep -v "0x${lookup}" | $IPTABLERESTORE -w --counters - $IPTABLERESTORE --noflush <<-EOF + $IPTABLERESTORE <<-EOF *mangle -A omr-gre-tunnel ${rule} -j MARK --set-mark 0x${lookup} COMMIT @@ -48,7 +48,7 @@ _setup_fw() { } if [ -z "$($IPTABLESAVE | grep omr-gre-tunnel)" ]; then - $IPTABLERESTORE --noflush <<-EOF + $IPTABLERESTORE <<-EOF *mangle :omr-gre-tunnel - -I PREROUTING 1 -m addrtype ! --dst-type LOCAL -j omr-gre-tunnel From c4073ad8be1f3540c9db710a2ca30d0326686687 Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Tue, 4 Jul 2023 00:06:42 +0800 Subject: [PATCH 14/20] fix --- luci-theme-ezengreen/Makefile | 16 - .../luci-static/ezengreen/1omr-logo-apple.png | Bin 8175 -> 0 bytes .../htdocs/luci-static/ezengreen/cascade.css | 2027 ----------------- .../htdocs/luci-static/ezengreen/favicon.png | Bin 8175 -> 0 bytes .../htdocs/luci-static/ezengreen/html5.js | 3 - .../htdocs/luci-static/ezengreen/mobile.css | 61 - .../resources/ezengreen/images/cascade.css | 2027 ----------------- .../resources/ezengreen/images/ezenlink.png | Bin 553 -> 0 bytes .../resources/ezengreen/images/favicon.ico | Bin 4286 -> 0 bytes .../resources/ezengreen/images/footer.png | Bin 836 -> 0 bytes .../resources/ezengreen/images/mobile.css | 61 - .../resources/ezengreen/images/omr-logo.png | Bin 19149 -> 0 bytes .../ezengreen/images/outdoorrouter.png | Bin 3815 -> 0 bytes .../luci-static/resources/menu-ezengreen.js | 118 - .../luasrc/view/themes/ezengreen/footer.htm | 19 - .../luasrc/view/themes/ezengreen/header.htm | 90 - .../etc/uci-defaults/luci-theme-ezengreen | 10 - luci-theme-openwrt-2020/Makefile | 14 - .../GalanoGrotesqueW00-Regular.woff2 | Bin 29004 -> 0 bytes .../luci-static/openwrt2020/cascade.css | 1925 ---------------- .../luci-static/openwrt2020/favicon.png | Bin 535 -> 0 bytes .../luci-static/openwrt2020/omr-logo.png | Bin 50790 -> 0 bytes .../luci-static/openwrt2020/spinner.svg | 12 - .../luci-static/resources/menu-openwrt2020.js | 147 -- .../luasrc/view/themes/openwrt2020/footer.htm | 17 - .../luasrc/view/themes/openwrt2020/header.htm | 63 - .../uci-defaults/30_luci-theme-openwrt-2020 | 11 - 27 files changed, 6621 deletions(-) delete mode 100755 luci-theme-ezengreen/Makefile delete mode 100755 luci-theme-ezengreen/htdocs/luci-static/ezengreen/1omr-logo-apple.png delete mode 100755 luci-theme-ezengreen/htdocs/luci-static/ezengreen/cascade.css delete mode 100755 luci-theme-ezengreen/htdocs/luci-static/ezengreen/favicon.png delete mode 100755 luci-theme-ezengreen/htdocs/luci-static/ezengreen/html5.js delete mode 100755 luci-theme-ezengreen/htdocs/luci-static/ezengreen/mobile.css delete mode 100755 luci-theme-ezengreen/htdocs/luci-static/resources/ezengreen/images/cascade.css delete mode 100755 luci-theme-ezengreen/htdocs/luci-static/resources/ezengreen/images/ezenlink.png delete mode 100755 luci-theme-ezengreen/htdocs/luci-static/resources/ezengreen/images/favicon.ico delete mode 100755 luci-theme-ezengreen/htdocs/luci-static/resources/ezengreen/images/footer.png delete mode 100755 luci-theme-ezengreen/htdocs/luci-static/resources/ezengreen/images/mobile.css delete mode 100755 luci-theme-ezengreen/htdocs/luci-static/resources/ezengreen/images/omr-logo.png delete mode 100755 luci-theme-ezengreen/htdocs/luci-static/resources/ezengreen/images/outdoorrouter.png delete mode 100755 luci-theme-ezengreen/htdocs/luci-static/resources/menu-ezengreen.js delete mode 100755 luci-theme-ezengreen/luasrc/view/themes/ezengreen/footer.htm delete mode 100755 luci-theme-ezengreen/luasrc/view/themes/ezengreen/header.htm delete mode 100755 luci-theme-ezengreen/root/etc/uci-defaults/luci-theme-ezengreen delete mode 100755 luci-theme-openwrt-2020/Makefile delete mode 100755 luci-theme-openwrt-2020/htdocs/luci-static/openwrt2020/GalanoGrotesqueW00-Regular.woff2 delete mode 100755 luci-theme-openwrt-2020/htdocs/luci-static/openwrt2020/cascade.css delete mode 100755 luci-theme-openwrt-2020/htdocs/luci-static/openwrt2020/favicon.png delete mode 100755 luci-theme-openwrt-2020/htdocs/luci-static/openwrt2020/omr-logo.png delete mode 100755 luci-theme-openwrt-2020/htdocs/luci-static/openwrt2020/spinner.svg delete mode 100755 luci-theme-openwrt-2020/htdocs/luci-static/resources/menu-openwrt2020.js delete mode 100755 luci-theme-openwrt-2020/luasrc/view/themes/openwrt2020/footer.htm delete mode 100755 luci-theme-openwrt-2020/luasrc/view/themes/openwrt2020/header.htm delete mode 100755 luci-theme-openwrt-2020/root/etc/uci-defaults/30_luci-theme-openwrt-2020 diff --git a/luci-theme-ezengreen/Makefile b/luci-theme-ezengreen/Makefile deleted file mode 100755 index ee17e224f..000000000 --- a/luci-theme-ezengreen/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -# -# Copyright (C) 2008-2014 The LuCI Team -# Copyright (C) 2018-2019 Ycarus (Yannick Chabanois) -# -# This is free software, licensed under the Apache License, Version 2.0 . -# - -include $(TOPDIR)/rules.mk - -LUCI_TITLE:=ezengreen Theme (default) -LUCI_DEPENDS:= - -#include ../luci/luci.mk -include $(TOPDIR)/feeds/luci/luci.mk - -# call BuildPackage - OpenWrt buildroot signature diff --git a/luci-theme-ezengreen/htdocs/luci-static/ezengreen/1omr-logo-apple.png b/luci-theme-ezengreen/htdocs/luci-static/ezengreen/1omr-logo-apple.png deleted file mode 100755 index 7ee7779108d5a958e17f305962fef3f5715fbafd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8175 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 - * Based on Bootstrap v1.4.0 - * - * Copyright 2011 Twitter, Inc - * Licensed under the Apache License v2.0 - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Designed and built with all the love in the world @twitter by @mdo and @fat. - */ -/* Reset.less - * Props to Eric Meyer (meyerweb.com) for his CSS reset file. We're using an adapted version here that cuts out some of the reset HTML elements we will never need here (i.e., dfn, samp, etc). - * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- */ -html { - margin: 0; - padding: 0; -} - -body { - margin: 0; - padding: 5px; -} - -h1, h2, h3, h4, h5, h6, p, pre, a, abbr, acronym, code, del, em, img, ins, q, s, -small, strike, strong, sub, sup, tt, var, dd, dl, dt, li, ol, ul, fieldset, -form, label, legend, button, table, caption, tbody, tfoot, thead, tr, th, td, -.table, .tbody, .tfoot, .thead, .tr, .th, .td { - margin: 0; - padding: 0; - border: 0; - font-weight: normal; - font-style: normal; - font-size: 100%; - line-height: 1; - font-family: inherit; -} - -abbr[title], acronym[title] { - border-bottom: 1px dotted; - font-weight: inherit; - cursor: help; -} - -table { - border-collapse: collapse; - border-spacing: 0; -} - -ol, ul { - list-style: none; -} - -q:before, -q:after, -blockquote:before, -blockquote:after { - content: ""; -} - -html { - overflow-y: scroll; - font-size: 100%; - -webkit-text-size-adjust: 100%; - -ms-text-size-adjust: 100%; -} - -a:focus { - outline: thin dotted; -} - -a:hover, a:active { - outline: 0; -} - -article, -aside, -details, -figcaption, -figure, -footer, -header, -hgroup, -nav, -section { - display: block; -} - -sub, sup { - font-size: 75%; - line-height: 0; - position: relative; - vertical-align: baseline; -} - -sup { - top: -0.5em; -} - -sub { - bottom: -0.25em; -} - -img { - border: 0; - -ms-interpolation-mode: bicubic; -} - -button, -input, -select, -option, -textarea { - font-size: 100%; - margin: 0; - box-sizing: border-box; - vertical-align: baseline; - *vertical-align: middle; -} - -button, input { - line-height: normal; - *overflow: visible; -} - -button::-moz-focus-inner, input::-moz-focus-inner { - border: 0; - padding: 0; -} - -button, -input[type="button"], -input[type="reset"], -input[type="submit"] { - cursor: pointer; - -webkit-appearance: button; -} - -button[disabled], -input[type="button"][disabled], -input[type="reset"][disabled], -input[type="submit"][disabled] { - opacity: 0.7; -} - -input[type="search"] { - -webkit-appearance: textfield; - box-sizing: content-box; -} - -input[type="search"]::-webkit-search-decoration { - -webkit-appearance: none; -} - -textarea { - overflow: auto; - vertical-align: top; -} - -/* - * Scaffolding - * Basic and global styles for generating a grid system, structural layout, and page templates - * ------------------------------------------------------------------------------------------- */ -body { - background-color: #fff; - margin: 0; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 12px; - font-weight: normal; - line-height: 18px; - color: #404040; - padding-top: 75px; -} - -.container { - width: 100%; - max-width: 940px; - margin-left: auto; - margin-right: auto; - zoom: 1; -} - -.container:before, .container:after { - display: table; - content: ""; - zoom: 1; -} - -.container:after { - clear: both; -} - -a { - color: #215e21; - text-decoration: none; - line-height: inherit; - font-weight: inherit; -} - -a:hover { - color: #000000; - text-decoration: none; -} - -.pull-right { - float: right; -} - -.pull-left { - float: left; -} - -/* Typography.less - * Headings, body text, lists, code, and more for a versatile and durable typography system - * ---------------------------------------------------------------------------------------- */ -p, -.cbi-map-descr, -.cbi-section-descr, -.table .tr.cbi-section-table-descr .th { - font-size: 12px; - font-weight: normal; - line-height: 18px; - margin-bottom: 9px; -} - -p small { - font-size: 11px; - color: #bfbfbf; -} - -h1, -h2, -h3, legend, -h4, -h5, -h6 { - font-weight: normal; - color: #404040; -} - -h1 small, -h2 small, -h3 small, -h4 small, -h5 small, -h6 small { - color: #bfbfbf; -} - -h1 { - margin-bottom: 18px; - font-size: 30px; - line-height: 36px; -} - -h1 small { - font-size: 18px; -} - -h2 { - font-size: 24px; - line-height: 58px; - text-transform: uppercase; - font-weight: normal; -} - -h2 small { - font-size: 14px; -} - -h3, legend, -h4, -h5, -h6 { - line-height: 48px; -} - -h3, legend { - font-size: 18px; -} - -h3 small { - font-size: 14px; -} - -h4 { - font-size: 16px; -} - -h4 small { - font-size: 12px; -} - -h5 { - font-size: 14px; -} - -h6 { - font-size: 13px; - color: #bfbfbf; - text-transform: uppercase; -} - -ul, ol { - margin: 0 0 18px 25px; -} - -ul ul, -ul ol, -ol ol, -ol ul { - margin-bottom: 0; -} - -ul { - list-style: disc; -} - -ol { - list-style: decimal; -} - -li { - line-height: 18px; - color: #808080; -} - -ul.unstyled { - list-style: none; - margin-left: 0; -} - -dl { - margin-bottom: 18px; -} - -dl dt, dl dd { - line-height: 18px; -} - -dl dt { - font-weight: bold; -} - -dl dd { - margin-left: 9px; -} - -hr { - margin: 20px 0 19px; - border: 0; - border-bottom: 1px solid #eee; -} - -strong { - font-style: inherit; - font-weight: bold; -} - -em { - font-style: italic; - font-weight: inherit; - line-height: inherit; -} - -small { font-size: 0.9em } - -address { - display: block; - line-height: 18px; - margin-bottom: 18px; -} - -code, pre { - padding: 0 3px 2px; - font-family: Monaco, Andale Mono, Courier New, monospace; - font-size: 12px; - border-radius: 2px; -} - -code { - background-color: #fee9cc; - color: rgba(0, 0, 0, 0.75); - padding: 1px 3px; -} - -pre { - background-color: #f5f5f5; - display: block; - padding: 8.5px; - margin: 0 0 18px; - line-height: 18px; - font-size: 12px; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, 0.15); - border-radius: 2px; - white-space: pre; - white-space: pre-wrap; - word-wrap: break-word; -} - -/* Forms.less - * Base styles for various input types, form layouts, and states - * ------------------------------------------------------------- */ -form { - margin-bottom: 18px; -} - -fieldset { - margin-bottom: 9px; - padding-top: 9px; -} - -fieldset legend { - display: block; - font-size: 19.5px; - line-height: 1; - color: #404040; - padding-top: 20px; - *padding: 0 0 5px 0px; - /* IE6-7 */ - - *line-height: 1.5; - /* IE6-7 */ - -} -form .cbi-tab-descr { - line-height: 18px; - margin-bottom: 18px; -} - -form .clearfix, -form .cbi-value { - margin-bottom: 15px; - margin-top: 15px; - zoom: 1; -} - -form .clearfix:before, form .clearfix:after, -form .cbi-value:before, form .cbi-value:after { - display: table; - content: ""; - zoom: 1; -} - -form .clearfix:after, -form .cbi-value:after { - clear: both; -} - -label, -input, -select, -textarea { - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 12px; - font-weight: normal; - line-height: normal; -} - -form .input, -form .cbi-value-field { - margin-left: 120px; -} - -form .cbi-value label.cbi-value-title { - padding-top: 6px; - font-size: 12px; - line-height: 18px; - float: left; - width: 111px; - text-align: left; - color: #404040; -} - -input[type=checkbox], input[type=radio] { - cursor: pointer; -} - -input, -textarea, -select, -.cbi-dropdown, -.uneditable-input { - display: inline-block; - width: 200px; - height: 30px; - padding: 4px; - font-size: 12px; - line-height: 18px; - color: #808080; - border: 1px solid #ccc; - border-radius: 2px; - box-sizing: border-box; - margin: 2px 0; -} - -.cbi-dropdown { - min-width: 210px; - max-width: 400px; - width: auto; -} - -select { - padding: initial; - background: #fff; - box-shadow: inset 0 -1px 3px rgba(0, 0, 0, 0.1); -} - -input[type=checkbox], input[type=radio] { - width: auto; - height: auto; - padding: 0; - margin: 3px 0; - *margin-top: 0; - /* IE6-7 */ - - line-height: normal; - border: none; -} - -input[type=file] { - background-color: #fff; - padding: initial; - border: initial; - line-height: initial; - box-shadow: none; - width: auto !important; -} - -input[type=button], input[type=reset], input[type=submit] { - width: auto; - height: auto; -} - -select, input[type=file] { - *height: auto; - *margin-top: 4px; - /* For IE7, add top margin to align select with labels */ -} - -select[multiple] { - height: inherit; - background-color: #fff; -} - -textarea { - height: auto; -} - -.td > input[type=text], -.td > input[type=password], -.td > select, -.td > .cbi-dropdown { - width: 100%; -} - -.uneditable-input { - background-color: #fff; - display: block; - border-color: #eee; - box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); - cursor: not-allowed; -} - -::-moz-placeholder { - color: #bfbfbf; -} - -::-webkit-input-placeholder { - color: #bfbfbf; -} - -.btn, .cbi-button, input, textarea { - transition: border linear 0.2s, box-shadow linear 0.2s; - box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1); - padding: 12px 6px; -} - -.btn:hover, .cbi-button:hover, -input:focus, textarea:focus { - outline: 0; - border-color: rgba(82, 168, 236, 0.8) !important; - box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6); - text-decoration: none; -} - -input[type=file]:focus, input[type=checkbox]:focus, select:focus { - box-shadow: none; - outline: 1px dotted #666; -} - -input[disabled], -select[disabled], -textarea[disabled], -input[readonly], -select[readonly], -textarea[readonly] { - background-color: #194119; - border-color: #ccc; - padding: 5px; - pointer-events: none; - cursor: default; -} - -select[readonly], -textarea[readonly] { - pointer-events: auto; - cursor: auto; -} - -.cbi-optionals, -.cbi-section-create { - padding: 0 0 10px 10px; -} - -.cbi-section-create { - margin: 10px 0 0 -10px; - display: inline-flex; - align-items: center; -} - -.cbi-section-create > * { - margin: 3px; - flex: 1 1 auto; -} - -.cbi-section-create > * > input { - width: 100%; -} - -.actions, -.cbi-page-actions { - background: #f5f5f5; - margin-bottom: 20px; - margin-top: 40px; - padding: 15px 20px 15px 20px; - border-radius: 0 0 2px 2px; - text-align: right; -} - -.actions .secondary-action, -.cbi-page-actions .secondary-action{ - float: right; -} - -.actions .secondary-action a, -.cbi-page-actions .secondary-action a { - line-height: 30px; -} - -.actions .secondary-action a:hover, -.cbi-page-actions .secondary-action a:hover { - text-decoration: none; -} - -.cbi-page-actions > form { - display: inline; - margin: 0; -} - -.help-inline, .help-block { - font-size: 12px; - line-height: 18px; - color: #bfbfbf; -} - -.help-inline { - padding-left: 5px; - *position: relative; - /* IE6-7 */ - - *top: -5px; - /* IE6-7 */ - -} - -.help-block { - display: block; - max-width: 600px; -} - -/* - * Tables.less - * Tables for, you guessed it, tabular data - * ---------------------------------------- */ -.tr { display: table-row; } -.table[width="33%"], .th[width="33%"], .td[width="33%"] { width: 33%; } -.table[width="100%"], .th[width="100%"], .td[width="100%"] { width: 100%; } - -.table { - display: table; - width: 100%; - margin: 12px 0 24px 0; - padding: 0; - font-size: 12px; - border-collapse: collapse; - position: relative; -} - -.table .th, .table .td { - display: table-cell; - vertical-align: middle; /* Fixme */ - padding: 6px 6px 6px 2px; - line-height: 18px; - text-align: left; -} - -.table .tr:first-child .th { - padding-top: 9px; - font-weight: normal; - vertical-align: top; -} - -.table .td, .table .th { - border-top: 1px solid #e7e7e7; -} - -.tr.placeholder { - height: calc(3em + 20px); -} - -.tr.placeholder > .td { - position: absolute; - left: 0; - right: 0; - bottom: 0; - text-align: center; - line-height: 3em; -} - -/* Patterns.less - * Repeatable UI elements outside the base styles provided from the scaffolding - * ---------------------------------------------------------------------------- */ -header { - height: 40px; - position: fixed; - top: 0; - left: 0; - right: 0; - z-index: 10000; - overflow: visible; - color: #BFBFBF; -} - -header a { - color: #c4c4c4; -} - -header h3 a:hover, header .brand:hover, header ul .active > a { - background-color: #333; - background-color: rgba(0, 0, 0, 0.33); - color: #fff; - text-decoration: none; -} - -header h3 { - position: relative; -} - -header h3 a, header .brand { - float: left; - display: block; - padding: 16px 20px 16px; - margin-left: -20px; - color: #fff; - font-size: 24px; - font-weight: 333; - line-height: 1; -} - -header p { - margin: 0; - line-height: 40px; -} - -header .fill { - background-color: #215e21; - background-repeat: repeat-x; - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.33), inset 0 -1px 0 rgba(0, 0, 0, 0.1); - padding: 0 5px; -} - -header div > ul, .nav { - display: block; - float: left; - margin: 0 10px 0 20px; - position: relative; - left: 0; -} - -header div > ul > li, .nav > li { - display: block; - float: left; -} - -header div > ul a, .nav a { - display: block; - float: none; - padding: 22px 12px 14px 12px; - line-height: 19px; - letter-spacing: 0.4px; - text-decoration: none; - text-transform: uppercase; -} - -header div > ul a:hover, .nav a:hover { - color: #fff; - text-decoration: none; -} - -header div > ul .active > a, .nav .active > a { - background-color: #222; - background-color: rgba(0, 0, 0, 0.33); -} - -header div > ul.secondary-nav, .nav.secondary-nav { - float: right; - margin-left: 10px; - margin-right: 0; -} - -header div > ul.secondary-nav .menu-dropdown, -.nav.secondary-nav .menu-dropdown, -header div > ul.secondary-nav .dropdown-menu, -.nav.secondary-nav .dropdown-menu { - right: 0; - border: 0; -} - -header div > ul a.menu:hover, -.nav a.menu:hover, -header div > ul li.open .menu, -.nav li.open .menu, -header div > ul .dropdown-toggle:hover, -.nav .dropdown-toggle:hover, -header div > ul .dropdown.open .dropdown-toggle, -.nav .dropdown.open .dropdown-toggle { - background: #444; - background: rgba(0, 0, 0, 0.3); -} - -header div > ul .menu-dropdown, -.nav .menu-dropdown, -header div > ul .dropdown-menu, -.nav .dropdown-menu { - background-color: #003300; -} - -header div > ul .menu-dropdown a.menu, -.nav .menu-dropdown a.menu, -header div > ul .dropdown-menu a.menu, -.nav .dropdown-menu a.menu, -header div > ul .menu-dropdown .dropdown-toggle, -.nav .menu-dropdown .dropdown-toggle, -header div > ul .dropdown-menu .dropdown-toggle, -.nav .dropdown-menu .dropdown-toggle { - color: #fff; -} - -header div > ul .menu-dropdown a.menu.open, -.nav .menu-dropdown a.menu.open, -header div > ul .dropdown-menu a.menu.open, -.nav .dropdown-menu a.menu.open, -header div > ul .menu-dropdown .dropdown-toggle.open, -.nav .menu-dropdown .dropdown-toggle.open, -header div > ul .dropdown-menu .dropdown-toggle.open, -.nav .dropdown-menu .dropdown-toggle.open { - background: #444; - background: rgba(255, 255, 255, 0.05); -} - -header div > ul .menu-dropdown li a, -.nav .menu-dropdown li a, -header div > ul .dropdown-menu li a, -.nav .dropdown-menu li a { - color: #bfbfbf; -} - -header div > ul .menu-dropdown li a:hover, -.nav .menu-dropdown li a:hover, -header div > ul .dropdown-menu li a:hover, -.nav .dropdown-menu li a:hover { - background-color: #215e21; - background-repeat: repeat-x; - color: #fff; -} - -header div > ul .menu-dropdown .active a, -.nav .menu-dropdown .active a, -header div > ul .dropdown-menu .active a, -.nav .dropdown-menu .active a { - color: #fff; -} - -header div > ul .menu-dropdown .divider, -.nav .menu-dropdown .divider, -header div > ul .dropdown-menu .divider, -.nav .dropdown-menu .divider { - background-color: #222; - border-color: #444; -} - -header ul .menu-dropdown li a, header ul .dropdown-menu li a { - padding: 6px 12px; -} - -li.menu, .dropdown { - position: relative; -} - -.menu-dropdown, .dropdown-menu { - background-color: #fff; - float: left; - position: absolute; - top: 55px; - left: -9999px; - z-index: 900; - min-width: 200px; - max-width: 300px; - _width: 160px; - margin-left: 0; - margin-right: 0; - padding: 6px 0; - zoom: 1; - border-radius: 0 0 2px 2px; - background-clip: padding-box; -} - -.menu-dropdown li, .dropdown-menu li { - float: none; - display: block; - background-color: transparent; -} - -.menu-dropdown .divider, .dropdown-menu .divider { - height: 1px; - margin: 5px 0; - overflow: hidden; - background-color: #eee; - border-bottom: 1px solid #fff; -} - -header .dropdown-menu a, .dropdown-menu a { - display: block; - padding: 4px 15px; - clear: both; - font-weight: normal; - line-height: 18px; - text-transform: capitalize; - letter-spacing: 0.2px; - color: #808080; - zoom: 1.1; -} - -header .dropdown-menu a:hover, -.dropdown-menu a:hover, -header .dropdown-menu a.hover, -.dropdown-menu a.hover { - background-color: #ddd; - background-repeat: repeat-x; - color: #404040; - text-decoration: none; - box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.025), inset 0 -1px rgba(0, 0, 0, 0.025); -} - -.open .menu, -.dropdown.open .menu, -.open .dropdown-toggle, -.dropdown.open .dropdown-toggle { - color: #fff; - background: #ccc; - background: rgba(0, 0, 0, 0.3); -} - -.open .menu-dropdown, -.dropdown.open .menu-dropdown, -.open .dropdown-menu, -.dropdown.open .dropdown-menu { - left: 0; -} - -.dropdown:hover ul.dropdown-menu { - left: 0; -} - -.dropdown-menu .dropdown-menu { - position: absolute; - left: 159px; -} - -.dropdown-menu li { - position: relative; -} - -.tabs, .cbi-tabmenu { - margin: 0 0 18px; - padding: 0; - list-style: none; - zoom: 1; -} - -.tabs:before, -.cbi-tabmenu:before, -.tabs:after, -.cbi-tabmenu:after { - display: table; - content: ""; - zoom: 1; -} - -.tabs:after, .cbi-tabmenu:after { - clear: both; -} - -.tabs > li, .cbi-tabmenu > li { - float: left; -} - -.tabs > li > a, .cbi-tabmenu > li > a { - display: block; -} - -.tabs, -.cbi-tabmenu { - border-color: #ddd; - border-style: solid; - border-width: 0 0 1px; -} - -.tabs > li, -.cbi-tabmenu > li { - position: relative; - margin-bottom: -1px; -} - -.cbi-tabmenu.map { - margin: 0; -} - -.cbi-tabmenu.map > li { - font-size: 16.5px; - font-weight: bold; -} - -.cbi-tabcontainer > fieldset.cbi-section[id] > legend { - display: none; -} - -.tabs > li > a, -.cbi-tabmenu > li > a { - padding: 0 15px; - margin-right: 2px; - line-height: 34px; - border: 1px solid transparent; - border-radius: 2px 2px 0 0; -} - -.tabs > li > a:hover, -.cbi-tabmenu > li > a:hover { - text-decoration: none; - background-color: #eee; - border-color: #eee #eee #ddd; -} - -.tabs .active > a, .tabs .active > a:hover, -.cbi-tabmenu .active > a, .cbi-tabmenu .active > a:hover, -.cbi-tab > a:link, .cbi-tab > a:hover { - color: #000000; - background-color: #fff; - border: 1px solid #ddd; - border-bottom-color: transparent; - cursor: default; -} - -.tabs .menu-dropdown, .tabs .dropdown-menu, -.cbi-tabmenu .menu-dropdown, .cbi-tabmenu .dropdown-menu { - top: 35px; - border-width: 1px; - border-radius: 0 2px 2px 2px; -} - -.tabs a.menu:after, .tabs .dropdown-toggle:after, -.cbi-tabmenu a.menu:after, .cbi-tabmenu .dropdown-toggle:after { - border-top-color: #999; - margin-top: 15px; - margin-left: 5px; -} - -.tabs li.open.menu .menu, .tabs .open.dropdown .dropdown-toggle, -.cbi-tabmenu li.open.menu .menu, .cbi-tabmenu .open.dropdown .dropdown-toggle { - border-color: #999; -} - -.tabs li.open a.menu:after, .tabs .dropdown.open .dropdown-toggle:after, -.cbi-tabmenu li.open a.menu:after, .cbi-tabmenu .dropdown.open .dropdown-toggle:after { - border-top-color: #555; -} - -.tab-content > .tab-pane, -.tab-content > div { - display: none; -} - -.tab-content > .active { - display: block; -} - -.breadcrumb { - padding: 7px 14px; - margin: 0 0 18px; - background-color: #f5f5f5; - background-repeat: repeat-x; - border: 1px solid #ddd; - border-radius: 2px; - box-shadow: inset 0 1px 0 #fff; -} - -.breadcrumb li { - display: inline; -} - -.breadcrumb .divider { - padding: 0 5px; - color: #bfbfbf; -} - -.breadcrumb .active a { - color: #404040; -} - -footer { - margin-top: 30px; - padding-top: 20px; - padding-bottom: 20px; - border-top: 1px solid #404040; -} - -.btn.danger, -.alert-message.danger, -.btn.danger:hover, -.alert-message.danger:hover, -.btn.error, -.alert-message.error, -.btn.error:hover, -.alert-message.error:hover, -.btn.success, -.alert-message.success, -.btn.success:hover, -.alert-message.success:hover, -.btn.info, -.alert-message.info, -.btn.info:hover, -.alert-message.info:hover { - color: #fff; -} - -.btn .close, .alert-message .close { - font-family: Arial, sans-serif; - line-height: 18px; -} - -.btn.danger, -.alert-message.danger, -.btn.error, -.alert-message.error { - background: linear-gradient(to bottom, #ee5f5b, #c43c35) repeat-x; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); -} - -.btn.success, .alert-message.success { - background: linear-gradient(to bottom, #62c462, #57a957) repeat-x; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); -} - -.btn.info, .alert-message.info { - background: linear-gradient(to bottom, #5bc0de, #339bb9) repeat-x; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); -} - -.alert-message.notice { - background: linear-gradient(to bottom, #efefef, #fefefe) repeat-x; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); -} - -.btn, -.cbi-button { - cursor: pointer; - display: inline-block; - background: linear-gradient(#fff, #fff 25%, #e6e6e6) no-repeat; - padding: 5px 14px 6px; - color: #333; - font-size: 12px; - line-height: normal; - border: 1px solid #ccc; - border-bottom-color: #bbb; - border-radius: 2px; - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); -} - -.btn:focus, -.cbi-button:focus { - outline: 1px dotted #666; -} - -.cbi-input-invalid, -.cbi-value-error input { - color: #f00; - border-color: #f00; -} - -.cbi-button-positive, -.cbi-button-fieldadd, -.cbi-button-add, -.cbi-button-save { - border-color: #4a4; - color: #4a4; -} - -.cbi-button-neutral, -.cbi-button-download, -.cbi-button-find, -.cbi-button-link, -.cbi-button-up, -.cbi-button-down { - color: #444; -} - -.btn.primary, -.cbi-button-action, -.cbi-button-apply, -.cbi-button-reload, -.cbi-button-edit { - border-color: #4aa44b; - color: #4aa44b; -} - -.cbi-button-negative, -.cbi-section-remove .cbi-button, -.cbi-button-reset, -.cbi-button-remove { - border-color: #c44; - color: #c44; -} - -.cbi-page-actions::after { - display: table; - content: ""; - clear: both; -} - -.cbi-page-actions > :not([method="post"]):not(.cbi-button-apply):not(.cbi-button-save):not(.cbi-button-reset) { - float: left; - margin-right: .4em; -} - -.btn.primary, -.cbi-button-action.important, -.cbi-page-actions .cbi-button-apply, -.cbi-section-actions .cbi-button-edit { - color: #fff; - background: #4aa44b; -} - -.cbi-button-positive.important, -.cbi-page-actions .cbi-button-save { - color: #fff; - background: linear-gradient(to bottom, #4a4, #484) no-repeat; -} - -.cbi-button-negative.important { - color: #fff; - background: linear-gradient(to bottom, #c44, #c00) no-repeat; -} - -.cbi-page-actions .cbi-button-apply + .cbi-button-save { - background: linear-gradient(#fff, #fff 25%, #e6e6e6); - color: #4a4; -} - -.cbi-dropdown { - border: 1px solid #ccc; - border-radius: 2px; - display: inline-flex; - padding: 0; - cursor: pointer; - height: auto; - background: linear-gradient(#fff 0%, #e9e8e6 100%); - position: relative; - color: #404040; -} - -.cbi-dropdown:focus { - outline: 2px solid #4b6e9b; -} - -.cbi-dropdown > ul { - margin: 0 !important; - padding: 0; - list-style: none; - overflow-x: hidden; - overflow-y: auto; - display: flex; - width: 100%; -} - -.cbi-dropdown > ul.preview { - display: none; -} - -.cbi-dropdown > .open, -.cbi-dropdown > .more { - flex-grow: 0; - flex-shrink: 0; - display: flex; - flex-direction: column; - justify-content: center; - text-align: center; - line-height: 2em; - padding: 0 .25em; -} - -.cbi-dropdown > .more, -.cbi-dropdown > ul > li[placeholder] { - color: #777; - font-weight: bold; - display: none; -} - -.cbi-dropdown > ul > li { - display: none; - padding: .25em; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - flex-shrink: 1; - flex-grow: 1; - align-items: center; - align-self: center; - color: #404040; - min-height: 20px; -} - -.cbi-dropdown > ul > li .hide-open { display: block; display: initial; } -.cbi-dropdown > ul > li .hide-close { display: none; } - -.cbi-dropdown > ul > li[display]:not([display="0"]) { - border-left: 1px solid #ccc; -} - -.cbi-dropdown[empty] > ul { - max-width: 1px; -} - -.cbi-dropdown > ul > li > form { - display: none; - margin: 0; - padding: 0; - pointer-events: none; -} - -.cbi-dropdown > ul > li img { - vertical-align: middle; - margin-right: .25em; -} - -.cbi-dropdown > ul > li > form > input[type="checkbox"] { - margin: 0; -} - -.cbi-dropdown > ul > li input[type="text"] { - height: 20px; -} - -.cbi-dropdown[open] { - position: relative; -} - -.cbi-dropdown[open] > ul.dropdown { - display: block; - background: #f6f6f5; - border: 1px solid #918e8c; - box-shadow: 0 0 4px #918e8c; - position: absolute; - z-index: 1000; - max-width: none; - min-width: 100%; - width: auto; -} - -.cbi-dropdown > ul > li[display], -.cbi-dropdown[open] > ul.preview, -.cbi-dropdown[open] > ul.dropdown > li, -.cbi-dropdown[multiple] > ul > li > label, -.cbi-dropdown[multiple][open] > ul.dropdown > li, -.cbi-dropdown[multiple][more] > .more, -.cbi-dropdown[multiple][empty] > .more { - flex-grow: 1; - display: flex; -} - -.cbi-dropdown[empty] > ul > li, -.cbi-dropdown[optional][open] > ul.dropdown > li[placeholder], -.cbi-dropdown[multiple][open] > ul.dropdown > li > form { - display: block; -} - -.cbi-dropdown[open] > ul.dropdown > li .hide-open { display: none; } -.cbi-dropdown[open] > ul.dropdown > li .hide-close { display: block; display: initial; } - -.cbi-dropdown[open] > ul.dropdown > li { - border-bottom: 1px solid #ccc; -} - -.cbi-dropdown[open] > ul.dropdown > li[selected] { - background: #b0d0f0; -} - -.cbi-dropdown[open] > ul.dropdown > li.focus { - background: linear-gradient(90deg, #a3c2e8 0%, #84aad9 100%); -} - -.cbi-dropdown[open] > ul.dropdown > li:last-child { - margin-bottom: 0; - border-bottom: none; -} - -.cbi-dropdown[disabled] { - pointer-events: none; - opacity: .6; -} - -input[type="text"] + .cbi-button, -input[type="password"] + .cbi-button, -select + .cbi-button { - border-radius: 2px; - border-color: #ccc; - margin: 2px 0 2px 3px; - padding: 0 12px; - vertical-align: top; - height: 28px; - font-size: 13px; - font-weight: normal; - line-height: 28px; -} - -select + .cbi-button { - #border-left-color: transparent; -} - -.cbi-title-ref { - color: #f39800; -} - -.cbi-title-ref::after { - content: " ➙ "; -} - -.cbi-tooltip-container { - cursor: help; - padding: 5px 3px 5px 3px; -} - -.cbi-tooltip { - position: absolute; - z-index: 1000; - left: -1000px; - opacity: 0; - transition: opacity .25s ease-out; -} - -.cbi-tooltip-container:hover .cbi-tooltip:not(:empty) { - left: auto; - opacity: 1; - transition: opacity .25s ease-in; -} - -.zonebadge .cbi-tooltip { - padding: 1px; - background: inherit; - margin: -1.6em 0 0 -5px; - border-radius: 2px; - pointer-events: none; - box-shadow: 0 0 3px #444; -} - -.zonebadge .cbi-tooltip > * { - margin: 1px; -} - -.zone-forwards { - display: flex; - flex-wrap: wrap; -} - -.zone-forwards > * { - flex: 1 1 40%; - padding: 1px; -} - -.zone-forwards > span { - flex-basis: 10%; - text-align: center; -} - -.zone-forwards .zone-src, -.zone-forwards .zone-dest { - display: flex; - flex-direction: column; -} - -.btn.active, .btn:active { - box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05); -} - -.btn.disabled { - cursor: default; - background-image: none; - opacity: 0.65; - box-shadow: none; -} - -.btn[disabled] { - cursor: default; - background-image: none; - opacity: 0.65; - box-shadow: none; -} - -.btn.large { - font-size: 15px; - line-height: normal; - padding: 9px 14px 9px; - border-radius: 2px; -} - -.btn.small { - padding: 7px 9px 7px; - font-size: 11px; -} - -button.btn::-moz-focus-inner, input[type=submit].btn::-moz-focus-inner { - padding: 0; - border: 0; -} - -.close { - float: right; - color: #000; - font-size: 20px; - font-weight: bold; - line-height: 13.5px; - opacity: 0.25; -} - -.close:hover { - color: #000; - text-decoration: none; - opacity: 0.4; -} - -.alert-message { - position: relative; - padding: 30px; - margin-top: 25px; - margin-bottom: 25px; - color: #404040; - background: #f0e68c; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - border-width: 1px; - border-style: solid; - border-radius: 2px; - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25); -} - -.alert-message .close { - margin-top: 1px; - *margin-top: 0; -} - -.alert-message a { - font-weight: bold; - color: #404040; -} - -.alert-message.danger p a, -.alert-message.error p a, -.alert-message.success p a, -.alert-message.info p a { - color: #fff; -} - -.alert-message h5 { - line-height: 18px; -} - -.alert-message p { - margin-bottom: 0; -} - -.alert-message div { - margin-top: 15px; - margin-bottom: 10px; - line-height: 28px; -} - -.label { - padding: 3px 3px 3px 3px; - font-size: 8px; - font-weight: normal; - color: #fff !important; - text-transform: uppercase; - white-space: nowrap; - background-color: #bfbfbf; - border-radius: 2px; - text-shadow: none; -} - -a.label:link, -a.label:visited { - color: #fff; -} - -a.label:hover { - text-decoration: none; -} - -.label.important { - background-color: #c43c35; -} - -.label.warning { - background-color: #f89406; -} - -.label.success { - background-color: #46a546; -} - -.label.notice { - background-color: #62cffc; -} - -/* LuCI specific items */ -.hidden { display: none } - -#memtotal > div, -#memfree > div, -#memcache > div, -#membuff > div, -#conns > div { - border: 1px solid #ccc; - border-radius: 2px 2px 2px 2px; - color: #808080; - display: inline-block; - font-size: 12px; - line-height: 18px; -} - -#xhr_poll_status { - cursor: pointer; -} - -form.inline { display: inline; margin-bottom: 0; } - -header .pull-right { padding-top: 21px; } - -#modemenu li:last-child span.divider { display: none } - -#syslog { width: 100%; } - -.cbi-section-table .tr:hover .td, -.cbi-section-table .tr:hover .th, -.cbi-section-table .tr:hover::before { - background-color: #f5f5f5; -} - -.cbi-section-table .tr.cbi-section-table-descr .th { - font-weight: normal; -} - -.cbi-section-table-titles.named::before, -.cbi-section-table-descr.named::before, -.cbi-section-table-row[data-title]::before { - content: attr(data-title) " "; - display: table-cell; - padding: 10px 10px 9px; - line-height: 18px; - font-weight: bold; - vertical-align: middle; -} - -.cbi-section-table-titles.named::before, -.cbi-section-table-descr.named::before, -.cbi-section-table-row[data-title]::before { - border-top: 1px solid #ddd; -} - -.left { text-align: left !important; } -.right { text-align: right !important; } -.center { text-align: center !important; } -.top { vertical-align: top !important; } -.middle { vertical-align: middle !important; } -.bottom { vertical-align: bottom !important; } - -.cbi-value-field { line-height: 1.5em; } - -.cbi-value-field input[type=checkbox], -.cbi-value-field input[type=radio] { - margin-top: 8px; - margin-right: 6px; -} - -table table td, -.cbi-value-field table td { - border: none; -} - -.table.cbi-section-table input[type="password"], -.table.cbi-section-table input[type="text"], -.table.cbi-section-table textarea, -.table.cbi-section-table select { - width: 100%; -} - -.table.cbi-section-table .td.cbi-section-table-cell { - white-space: nowrap; - text-align: right; -} - -.table.cbi-section-table .td.cbi-section-table-cell select { - width: inherit; -} - -.td.cbi-section-actions { - text-align: right; - vertical-align: middle; -} - -.td.cbi-section-actions > * { - display: flex; -} - -.td.cbi-section-actions > * > *, -.td.cbi-section-actions > * > form > * { - flex: 1 1 4em; - margin: 0 1px; -} - -.td.cbi-section-actions > * > form { - display: inline-flex; - margin: 0; -} - -.table.valign-middle .td { - vertical-align: middle; -} - -.cbi-rowstyle-2, -.tr.table-titles, -.tr.cbi-section-table-titles { - background: #f9f9f9; -} - -.cbi-value-description { - background-image: url(/luci-static/resources/cbi/help.gif); - background-position: .25em .2em; - background-repeat: no-repeat; - margin: 10px 0 10px -5px; - padding: 0 0 0 26px; -} - -.cbi-section-error { - border: 1px solid #f00; - border-radius: 2px; - background-color: #fce6e6; - padding: 5px; - margin-bottom: 18px; -} - -.cbi-section-error ul { margin: 0 0 0 20px; } - -.cbi-section-error ul li { - color: #f00; - font-weight: bold; -} - -.ifacebox { - background-color: #fff; - border: 1px solid #ccc; - margin: 6px 4px; - text-align: center; - white-space: nowrap; - background-image: linear-gradient(#fff, #fff 25%, #f9f9f9); - border-radius: 2px; - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); - display: inline-flex; - flex-direction: column; - line-height: 1.2em; - min-width: 100px; -} - -.ifacebox .ifacebox-head { - border-bottom: 1px solid #ccc; - padding: 10px; - line-height: 1.2em; - background: #eee; -} - -.ifacebox .ifacebox-head.active { - background: #f0e68c; -} - -.ifacebox .ifacebox-body { - padding: .25em; -} - -.ifacebadge { - display: inline-block; - flex-direction: row; - white-space: nowrap; - background-color: #fff; - border: 1px solid #ccc; - padding: 5px 5px 3px 5px; - background-image: linear-gradient(#fff, #fff 25%, #f9f9f9); - border-radius: 2px; - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); - cursor: default; - line-height: 1.2em; -} - -.ifacebadge img { - width: 16px; - height: 16px; - vertical-align: middle; -} - -.ifacebadge-active { - border-color: #000; - font-weight: bold; -} - -.network-status-table { - display: flex; - flex-wrap: wrap; -} - -.network-status-table .ifacebox { - margin: 10px 10px 15px 2px; - flex-grow: 1; -} - -.network-status-table .ifacebox-body { - display: flex; - flex-direction: column; - height: 100%; - text-align: left; - padding: 8px; -} - -.network-status-table .ifacebox-body > * { - margin: .25em; -} - -.network-status-table .ifacebox-body > span { - flex: 10 10 auto; - height: 100%; -} - -.network-status-table .ifacebox-body > div { - display: flex; - flex-wrap: wrap; - margin: -.125em; -} - -#dsl_status_table .ifacebox-body > span > strong { - display: inline-block; - min-width: 35%; -} - -.ifacebadge.large, -.network-status-table .ifacebox-body .ifacebadge { - display: inline-flex; - flex: 1; - padding: 10px 4px 10px 4px; - min-width: 220px; - margin: 10px 6px 4px 4px; -} - -.ifacebadge > *, -.ifacebadge.large > * { - margin: 0 .125em; -} - -.zonebadge { - padding: 2px; - border-radius: 2px; - display: inline-block; - white-space: nowrap; - color: #666; -} - -.zonebadge > em, -.zonebadge > strong { - margin: 0 2px; - display: inline-block; -} - -.zonebadge input { - width: 6em; -} - -.zonebadge > .ifacebadge { - margin-left: 2px; -} - -.zonebadge-empty { - border: 1px dashed #aaa; - color: #aaa; - font-style: italic; - font-size: smaller; -} - -div.cbi-value var, -.td.cbi-value-field var { - font-style: italic; - color: #215e21; -} - -.uci-change-list { - line-height: 170%; - white-space: pre; -} - -.uci-change-list del, -.uci-change-list ins, -.uci-change-list var, -.uci-change-legend-label del, -.uci-change-legend-label ins, -.uci-change-legend-label var { - text-decoration: none; - font-family: monospace; - font-style: normal; - border: 1px solid #ccc; - background: #eee; - padding: 2px; - display: block; - line-height: 15px; - margin-bottom: 1px; -} - -.uci-change-list ins, -.uci-change-legend-label ins { - border-color: #0f0; - background: #cfc; -} - -.uci-change-list del, -.uci-change-legend-label del { - border-color: #f00; - background: #fcc; -} - -.uci-change-list var, -.uci-change-legend-label var { - border-color: #ccc; - background: #eee; -} - -.uci-change-list var ins, -.uci-change-list var del { - display: inline-block; - border: none; - width: 100%; - padding: 0; -} - -.uci-change-legend { - padding: 5px; -} - -.uci-change-legend-label { - width: 150px; - float: left; -} - -.uci-change-legend-label > ins, -.uci-change-legend-label > del, -.uci-change-legend-label > var { - float: left; - margin-right: 4px; - width: 10px; - height: 10px; - display: block; - position: relative; -} - -.uci-change-legend-label var ins, -.uci-change-legend-label var del { - border: none; - position: absolute; - top: 2px; - left: 2px; - right: 2px; - bottom: 2px; -} - -html body.apply-overlay-active { - height: calc(100vh - 63px); -} - -#applyreboot-section { - line-height: 300%; -} - -.login{ - text-align: center; - background-color: #fff; - border-radius: 20px; - width: 300px; - height: 350px; - position: absolute; - left: 50%; - top: 50%; - transform: translate(-50%,-50%); -} diff --git a/luci-theme-ezengreen/htdocs/luci-static/ezengreen/favicon.png b/luci-theme-ezengreen/htdocs/luci-static/ezengreen/favicon.png deleted file mode 100755 index 7ee7779108d5a958e17f305962fef3f5715fbafd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8175 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.createElement("font"),c.setAttribute("data-html5shiv",a.nodeName.toLowerCase())):c=b.createElement("shiv:"+a.nodeName);while(a.firstChild)c.appendChild(a.childNodes[0]);for(d=a.attributes,e=d.length,f=0;f7?e[g][e[g].length-1]=e[g][e[g].length-1].replace(d,'$1font[data-html5shiv="$2"]'):e[g][e[g].length-1]=e[g][e[g].length-1].replace(d,"$1shiv\\:$2"),e[g]=e[g].join("}");return e.join("{")}var c=function(a){return a.innerHTML="",a.childNodes.length===1}(b.createElement("a")),d=function(a,b,c){return b.appendChild(a),(c=(c?c(a):a.currentStyle).display)&&b.removeChild(a)&&c==="block"}(b.createElement("nav"),b.documentElement,a.getComputedStyle),e={elements:"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video".split(" "),shivDocument:function(a){a=a||b;if(a.documentShived)return;a.documentShived=!0;var f=a.createElement,g=a.createDocumentFragment,h=a.getElementsByTagName("head")[0],i=function(a){f(a)};c||(e.elements.join(" ").replace(/\w+/g,i),a.createElement=function(a){var b=f(a);return b.canHaveChildren&&e.shivDocument(b.document),b},a.createDocumentFragment=function(){return e.shivDocument(g())});if(!d&&h){var j=f("div");j.innerHTML=["x"].join(""),h.insertBefore(j.lastChild,h.firstChild)}return a}};e.shivDocument(b),a.html5=e;if(c||!a.attachEvent)return;a.attachEvent("onbeforeprint",function(){if(a.html5.supportsXElement||!b.namespaces)return;b.namespaces.shiv||b.namespaces.add("shiv");var c=-1,d=new RegExp("^("+a.html5.elements.join("|")+")$","i"),e=b.getElementsByTagName("*"),g=e.length,j,k=i(h(function(a,b){var c=[],d=a.length;while(d)c.unshift(a[--d]);d=b.length;while(d)c.unshift(b[--d]);c.sort(function(a,b){return a.sourceIndex-b.sourceIndex}),d=c.length;while(d)c[--d]=c[d].styleSheet;return c}(b.getElementsByTagName("style"),b.getElementsByTagName("link"))));while(++c ul, .nav { - display: block; - float: left; - margin: 7px 8px 0 8px; - position: relative; - left: 0; -} - -header div > ul a, .nav a { - display: block; - float: left; - padding: 12px 6px 12px 6px; - line-height: 14px; - letter-spacing: 0.2px; -} - -.menu-dropdown, .dropdown-menu { - top: 38px; - min-width: 180px; - max-width: 260px; -} - -@media screen and (max-device-width: 660px) { - #maincontent.container { - width: 98%; - margin: 30px 0 0 6px; - } -} - -@media screen and (max-device-width: 360px) { - #maincontent.container { - width: 96%; - margin: 30px 0 0 6px; - } -} - -@media screen and (max-device-width: 200px) { - #maincontent.container { - width: 94%; - margin: 40px 0 0 2px; - } -} diff --git a/luci-theme-ezengreen/htdocs/luci-static/resources/ezengreen/images/cascade.css b/luci-theme-ezengreen/htdocs/luci-static/resources/ezengreen/images/cascade.css deleted file mode 100755 index 740adc320..000000000 --- a/luci-theme-ezengreen/htdocs/luci-static/resources/ezengreen/images/cascade.css +++ /dev/null @@ -1,2027 +0,0 @@ -/*! - * LuCI Bootstrap Theme - * Copyright 2012 Nut & Bolt - * By David Menting - * Based on Bootstrap v1.4.0 - * - * Copyright 2011 Twitter, Inc - * Licensed under the Apache License v2.0 - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Designed and built with all the love in the world @twitter by @mdo and @fat. - */ -/* Reset.less - * Props to Eric Meyer (meyerweb.com) for his CSS reset file. We're using an adapted version here that cuts out some of the reset HTML elements we will never need here (i.e., dfn, samp, etc). - * ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- */ -html { - margin: 0; - padding: 0; -} - -body { - margin: 0; - padding: 5px; -} - -h1, h2, h3, h4, h5, h6, p, pre, a, abbr, acronym, code, del, em, img, ins, q, s, -small, strike, strong, sub, sup, tt, var, dd, dl, dt, li, ol, ul, fieldset, -form, label, legend, button, table, caption, tbody, tfoot, thead, tr, th, td, -.table, .tbody, .tfoot, .thead, .tr, .th, .td { - margin: 0; - padding: 0; - border: 0; - font-weight: normal; - font-style: normal; - font-size: 100%; - line-height: 1; - font-family: inherit; -} - -abbr[title], acronym[title] { - border-bottom: 1px dotted; - font-weight: inherit; - cursor: help; -} - -table { - border-collapse: collapse; - border-spacing: 0; -} - -ol, ul { - list-style: none; -} - -q:before, -q:after, -blockquote:before, -blockquote:after { - content: ""; -} - -html { - overflow-y: scroll; - font-size: 100%; - -webkit-text-size-adjust: 100%; - -ms-text-size-adjust: 100%; -} - -a:focus { - outline: thin dotted; -} - -a:hover, a:active { - outline: 0; -} - -article, -aside, -details, -figcaption, -figure, -footer, -header, -hgroup, -nav, -section { - display: block; -} - -sub, sup { - font-size: 75%; - line-height: 0; - position: relative; - vertical-align: baseline; -} - -sup { - top: -0.5em; -} - -sub { - bottom: -0.25em; -} - -img { - border: 0; - -ms-interpolation-mode: bicubic; -} - -button, -input, -select, -option, -textarea { - font-size: 100%; - margin: 0; - box-sizing: border-box; - vertical-align: baseline; - *vertical-align: middle; -} - -button, input { - line-height: normal; - *overflow: visible; -} - -button::-moz-focus-inner, input::-moz-focus-inner { - border: 0; - padding: 0; -} - -button, -input[type="button"], -input[type="reset"], -input[type="submit"] { - cursor: pointer; - -webkit-appearance: button; -} - -button[disabled], -input[type="button"][disabled], -input[type="reset"][disabled], -input[type="submit"][disabled] { - opacity: 0.7; -} - -input[type="search"] { - -webkit-appearance: textfield; - box-sizing: content-box; -} - -input[type="search"]::-webkit-search-decoration { - -webkit-appearance: none; -} - -textarea { - overflow: auto; - vertical-align: top; -} - -/* - * Scaffolding - * Basic and global styles for generating a grid system, structural layout, and page templates - * ------------------------------------------------------------------------------------------- */ -body { - background-color: #fff; - margin: 0; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 12px; - font-weight: normal; - line-height: 18px; - color: #404040; - padding-top: 75px; -} - -.container { - width: 100%; - max-width: 940px; - margin-left: auto; - margin-right: auto; - zoom: 1; -} - -.container:before, .container:after { - display: table; - content: ""; - zoom: 1; -} - -.container:after { - clear: both; -} - -a { - color: #215e21; - text-decoration: none; - line-height: inherit; - font-weight: inherit; -} - -a:hover { - color: #000000; - text-decoration: none; -} - -.pull-right { - float: right; -} - -.pull-left { - float: left; -} - -/* Typography.less - * Headings, body text, lists, code, and more for a versatile and durable typography system - * ---------------------------------------------------------------------------------------- */ -p, -.cbi-map-descr, -.cbi-section-descr, -.table .tr.cbi-section-table-descr .th { - font-size: 12px; - font-weight: normal; - line-height: 18px; - margin-bottom: 9px; -} - -p small { - font-size: 11px; - color: #bfbfbf; -} - -h1, -h2, -h3, legend, -h4, -h5, -h6 { - font-weight: normal; - color: #404040; -} - -h1 small, -h2 small, -h3 small, -h4 small, -h5 small, -h6 small { - color: #bfbfbf; -} - -h1 { - margin-bottom: 18px; - font-size: 30px; - line-height: 36px; -} - -h1 small { - font-size: 18px; -} - -h2 { - font-size: 24px; - line-height: 58px; - text-transform: uppercase; - font-weight: normal; -} - -h2 small { - font-size: 14px; -} - -h3, legend, -h4, -h5, -h6 { - line-height: 48px; -} - -h3, legend { - font-size: 18px; -} - -h3 small { - font-size: 14px; -} - -h4 { - font-size: 16px; -} - -h4 small { - font-size: 12px; -} - -h5 { - font-size: 14px; -} - -h6 { - font-size: 13px; - color: #bfbfbf; - text-transform: uppercase; -} - -ul, ol { - margin: 0 0 18px 25px; -} - -ul ul, -ul ol, -ol ol, -ol ul { - margin-bottom: 0; -} - -ul { - list-style: disc; -} - -ol { - list-style: decimal; -} - -li { - line-height: 18px; - color: #808080; -} - -ul.unstyled { - list-style: none; - margin-left: 0; -} - -dl { - margin-bottom: 18px; -} - -dl dt, dl dd { - line-height: 18px; -} - -dl dt { - font-weight: bold; -} - -dl dd { - margin-left: 9px; -} - -hr { - margin: 20px 0 19px; - border: 0; - border-bottom: 1px solid #eee; -} - -strong { - font-style: inherit; - font-weight: bold; -} - -em { - font-style: italic; - font-weight: inherit; - line-height: inherit; -} - -small { font-size: 0.9em } - -address { - display: block; - line-height: 18px; - margin-bottom: 18px; -} - -code, pre { - padding: 0 3px 2px; - font-family: Monaco, Andale Mono, Courier New, monospace; - font-size: 12px; - border-radius: 2px; -} - -code { - background-color: #fee9cc; - color: rgba(0, 0, 0, 0.75); - padding: 1px 3px; -} - -pre { - background-color: #f5f5f5; - display: block; - padding: 8.5px; - margin: 0 0 18px; - line-height: 18px; - font-size: 12px; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, 0.15); - border-radius: 2px; - white-space: pre; - white-space: pre-wrap; - word-wrap: break-word; -} - -/* Forms.less - * Base styles for various input types, form layouts, and states - * ------------------------------------------------------------- */ -form { - margin-bottom: 18px; -} - -fieldset { - margin-bottom: 9px; - padding-top: 9px; -} - -fieldset legend { - display: block; - font-size: 19.5px; - line-height: 1; - color: #404040; - padding-top: 20px; - *padding: 0 0 5px 0px; - /* IE6-7 */ - - *line-height: 1.5; - /* IE6-7 */ - -} -form .cbi-tab-descr { - line-height: 18px; - margin-bottom: 18px; -} - -form .clearfix, -form .cbi-value { - margin-bottom: 15px; - margin-top: 15px; - zoom: 1; -} - -form .clearfix:before, form .clearfix:after, -form .cbi-value:before, form .cbi-value:after { - display: table; - content: ""; - zoom: 1; -} - -form .clearfix:after, -form .cbi-value:after { - clear: both; -} - -label, -input, -select, -textarea { - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 12px; - font-weight: normal; - line-height: normal; -} - -form .input, -form .cbi-value-field { - margin-left: 120px; -} - -form .cbi-value label.cbi-value-title { - padding-top: 6px; - font-size: 12px; - line-height: 18px; - float: left; - width: 111px; - text-align: left; - color: #404040; -} - -input[type=checkbox], input[type=radio] { - cursor: pointer; -} - -input, -textarea, -select, -.cbi-dropdown, -.uneditable-input { - display: inline-block; - width: 200px; - height: 30px; - padding: 4px; - font-size: 12px; - line-height: 18px; - color: #808080; - border: 1px solid #ccc; - border-radius: 2px; - box-sizing: border-box; - margin: 2px 0; -} - -.cbi-dropdown { - min-width: 210px; - max-width: 400px; - width: auto; -} - -select { - padding: initial; - background: #fff; - box-shadow: inset 0 -1px 3px rgba(0, 0, 0, 0.1); -} - -input[type=checkbox], input[type=radio] { - width: auto; - height: auto; - padding: 0; - margin: 3px 0; - *margin-top: 0; - /* IE6-7 */ - - line-height: normal; - border: none; -} - -input[type=file] { - background-color: #fff; - padding: initial; - border: initial; - line-height: initial; - box-shadow: none; - width: auto !important; -} - -input[type=button], input[type=reset], input[type=submit] { - width: auto; - height: auto; -} - -select, input[type=file] { - *height: auto; - *margin-top: 4px; - /* For IE7, add top margin to align select with labels */ -} - -select[multiple] { - height: inherit; - background-color: #fff; -} - -textarea { - height: auto; -} - -.td > input[type=text], -.td > input[type=password], -.td > select, -.td > .cbi-dropdown { - width: 100%; -} - -.uneditable-input { - background-color: #fff; - display: block; - border-color: #eee; - box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025); - cursor: not-allowed; -} - -::-moz-placeholder { - color: #bfbfbf; -} - -::-webkit-input-placeholder { - color: #bfbfbf; -} - -.btn, .cbi-button, input, textarea { - transition: border linear 0.2s, box-shadow linear 0.2s; - box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1); - padding: 12px 6px; -} - -.btn:hover, .cbi-button:hover, -input:focus, textarea:focus { - outline: 0; - border-color: rgba(82, 168, 236, 0.8) !important; - box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6); - text-decoration: none; -} - -input[type=file]:focus, input[type=checkbox]:focus, select:focus { - box-shadow: none; - outline: 1px dotted #666; -} - -input[disabled], -select[disabled], -textarea[disabled], -input[readonly], -select[readonly], -textarea[readonly] { - background-color: #194119; - border-color: #ccc; - padding: 5px; - pointer-events: none; - cursor: default; -} - -select[readonly], -textarea[readonly] { - pointer-events: auto; - cursor: auto; -} - -.cbi-optionals, -.cbi-section-create { - padding: 0 0 10px 10px; -} - -.cbi-section-create { - margin: 10px 0 0 -10px; - display: inline-flex; - align-items: center; -} - -.cbi-section-create > * { - margin: 3px; - flex: 1 1 auto; -} - -.cbi-section-create > * > input { - width: 100%; -} - -.actions, -.cbi-page-actions { - background: #f5f5f5; - margin-bottom: 20px; - margin-top: 40px; - padding: 15px 20px 15px 20px; - border-radius: 0 0 2px 2px; - text-align: right; -} - -.actions .secondary-action, -.cbi-page-actions .secondary-action{ - float: right; -} - -.actions .secondary-action a, -.cbi-page-actions .secondary-action a { - line-height: 30px; -} - -.actions .secondary-action a:hover, -.cbi-page-actions .secondary-action a:hover { - text-decoration: none; -} - -.cbi-page-actions > form { - display: inline; - margin: 0; -} - -.help-inline, .help-block { - font-size: 12px; - line-height: 18px; - color: #bfbfbf; -} - -.help-inline { - padding-left: 5px; - *position: relative; - /* IE6-7 */ - - *top: -5px; - /* IE6-7 */ - -} - -.help-block { - display: block; - max-width: 600px; -} - -/* - * Tables.less - * Tables for, you guessed it, tabular data - * ---------------------------------------- */ -.tr { display: table-row; } -.table[width="33%"], .th[width="33%"], .td[width="33%"] { width: 33%; } -.table[width="100%"], .th[width="100%"], .td[width="100%"] { width: 100%; } - -.table { - display: table; - width: 100%; - margin: 12px 0 24px 0; - padding: 0; - font-size: 12px; - border-collapse: collapse; - position: relative; -} - -.table .th, .table .td { - display: table-cell; - vertical-align: middle; /* Fixme */ - padding: 6px 6px 6px 2px; - line-height: 18px; - text-align: left; -} - -.table .tr:first-child .th { - padding-top: 9px; - font-weight: normal; - vertical-align: top; -} - -.table .td, .table .th { - border-top: 1px solid #e7e7e7; -} - -.tr.placeholder { - height: calc(3em + 20px); -} - -.tr.placeholder > .td { - position: absolute; - left: 0; - right: 0; - bottom: 0; - text-align: center; - line-height: 3em; -} - -/* Patterns.less - * Repeatable UI elements outside the base styles provided from the scaffolding - * ---------------------------------------------------------------------------- */ -header { - height: 40px; - position: fixed; - top: 0; - left: 0; - right: 0; - z-index: 10000; - overflow: visible; - color: #BFBFBF; -} - -header a { - color: #c4c4c4; -} - -header h3 a:hover, header .brand:hover, header ul .active > a { - background-color: #333; - background-color: rgba(0, 0, 0, 0.33); - color: #fff; - text-decoration: none; -} - -header h3 { - position: relative; -} - -header h3 a, header .brand { - float: left; - display: block; - padding: 16px 20px 16px; - margin-left: -20px; - color: #fff; - font-size: 24px; - font-weight: 333; - line-height: 1; -} - -header p { - margin: 0; - line-height: 40px; -} - -header .fill { - background-color: #215e21; - background-repeat: repeat-x; - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.33), inset 0 -1px 0 rgba(0, 0, 0, 0.1); - padding: 0 5px; -} - -header div > ul, .nav { - display: block; - float: left; - margin: 0 10px 0 20px; - position: relative; - left: 0; -} - -header div > ul > li, .nav > li { - display: block; - float: left; -} - -header div > ul a, .nav a { - display: block; - float: none; - padding: 22px 12px 14px 12px; - line-height: 19px; - letter-spacing: 0.4px; - text-decoration: none; - text-transform: uppercase; -} - -header div > ul a:hover, .nav a:hover { - color: #fff; - text-decoration: none; -} - -header div > ul .active > a, .nav .active > a { - background-color: #222; - background-color: rgba(0, 0, 0, 0.33); -} - -header div > ul.secondary-nav, .nav.secondary-nav { - float: right; - margin-left: 10px; - margin-right: 0; -} - -header div > ul.secondary-nav .menu-dropdown, -.nav.secondary-nav .menu-dropdown, -header div > ul.secondary-nav .dropdown-menu, -.nav.secondary-nav .dropdown-menu { - right: 0; - border: 0; -} - -header div > ul a.menu:hover, -.nav a.menu:hover, -header div > ul li.open .menu, -.nav li.open .menu, -header div > ul .dropdown-toggle:hover, -.nav .dropdown-toggle:hover, -header div > ul .dropdown.open .dropdown-toggle, -.nav .dropdown.open .dropdown-toggle { - background: #444; - background: rgba(0, 0, 0, 0.3); -} - -header div > ul .menu-dropdown, -.nav .menu-dropdown, -header div > ul .dropdown-menu, -.nav .dropdown-menu { - background-color: #003300; -} - -header div > ul .menu-dropdown a.menu, -.nav .menu-dropdown a.menu, -header div > ul .dropdown-menu a.menu, -.nav .dropdown-menu a.menu, -header div > ul .menu-dropdown .dropdown-toggle, -.nav .menu-dropdown .dropdown-toggle, -header div > ul .dropdown-menu .dropdown-toggle, -.nav .dropdown-menu .dropdown-toggle { - color: #fff; -} - -header div > ul .menu-dropdown a.menu.open, -.nav .menu-dropdown a.menu.open, -header div > ul .dropdown-menu a.menu.open, -.nav .dropdown-menu a.menu.open, -header div > ul .menu-dropdown .dropdown-toggle.open, -.nav .menu-dropdown .dropdown-toggle.open, -header div > ul .dropdown-menu .dropdown-toggle.open, -.nav .dropdown-menu .dropdown-toggle.open { - background: #444; - background: rgba(255, 255, 255, 0.05); -} - -header div > ul .menu-dropdown li a, -.nav .menu-dropdown li a, -header div > ul .dropdown-menu li a, -.nav .dropdown-menu li a { - color: #bfbfbf; -} - -header div > ul .menu-dropdown li a:hover, -.nav .menu-dropdown li a:hover, -header div > ul .dropdown-menu li a:hover, -.nav .dropdown-menu li a:hover { - background-color: #215e21; - background-repeat: repeat-x; - color: #fff; -} - -header div > ul .menu-dropdown .active a, -.nav .menu-dropdown .active a, -header div > ul .dropdown-menu .active a, -.nav .dropdown-menu .active a { - color: #fff; -} - -header div > ul .menu-dropdown .divider, -.nav .menu-dropdown .divider, -header div > ul .dropdown-menu .divider, -.nav .dropdown-menu .divider { - background-color: #222; - border-color: #444; -} - -header ul .menu-dropdown li a, header ul .dropdown-menu li a { - padding: 6px 12px; -} - -li.menu, .dropdown { - position: relative; -} - -.menu-dropdown, .dropdown-menu { - background-color: #fff; - float: left; - position: absolute; - top: 55px; - left: -9999px; - z-index: 900; - min-width: 200px; - max-width: 300px; - _width: 160px; - margin-left: 0; - margin-right: 0; - padding: 6px 0; - zoom: 1; - border-radius: 0 0 2px 2px; - background-clip: padding-box; -} - -.menu-dropdown li, .dropdown-menu li { - float: none; - display: block; - background-color: transparent; -} - -.menu-dropdown .divider, .dropdown-menu .divider { - height: 1px; - margin: 5px 0; - overflow: hidden; - background-color: #eee; - border-bottom: 1px solid #fff; -} - -header .dropdown-menu a, .dropdown-menu a { - display: block; - padding: 4px 15px; - clear: both; - font-weight: normal; - line-height: 18px; - text-transform: capitalize; - letter-spacing: 0.2px; - color: #808080; - zoom: 1.1; -} - -header .dropdown-menu a:hover, -.dropdown-menu a:hover, -header .dropdown-menu a.hover, -.dropdown-menu a.hover { - background-color: #ddd; - background-repeat: repeat-x; - color: #404040; - text-decoration: none; - box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.025), inset 0 -1px rgba(0, 0, 0, 0.025); -} - -.open .menu, -.dropdown.open .menu, -.open .dropdown-toggle, -.dropdown.open .dropdown-toggle { - color: #fff; - background: #ccc; - background: rgba(0, 0, 0, 0.3); -} - -.open .menu-dropdown, -.dropdown.open .menu-dropdown, -.open .dropdown-menu, -.dropdown.open .dropdown-menu { - left: 0; -} - -.dropdown:hover ul.dropdown-menu { - left: 0; -} - -.dropdown-menu .dropdown-menu { - position: absolute; - left: 159px; -} - -.dropdown-menu li { - position: relative; -} - -.tabs, .cbi-tabmenu { - margin: 0 0 18px; - padding: 0; - list-style: none; - zoom: 1; -} - -.tabs:before, -.cbi-tabmenu:before, -.tabs:after, -.cbi-tabmenu:after { - display: table; - content: ""; - zoom: 1; -} - -.tabs:after, .cbi-tabmenu:after { - clear: both; -} - -.tabs > li, .cbi-tabmenu > li { - float: left; -} - -.tabs > li > a, .cbi-tabmenu > li > a { - display: block; -} - -.tabs, -.cbi-tabmenu { - border-color: #ddd; - border-style: solid; - border-width: 0 0 1px; -} - -.tabs > li, -.cbi-tabmenu > li { - position: relative; - margin-bottom: -1px; -} - -.cbi-tabmenu.map { - margin: 0; -} - -.cbi-tabmenu.map > li { - font-size: 16.5px; - font-weight: bold; -} - -.cbi-tabcontainer > fieldset.cbi-section[id] > legend { - display: none; -} - -.tabs > li > a, -.cbi-tabmenu > li > a { - padding: 0 15px; - margin-right: 2px; - line-height: 34px; - border: 1px solid transparent; - border-radius: 2px 2px 0 0; -} - -.tabs > li > a:hover, -.cbi-tabmenu > li > a:hover { - text-decoration: none; - background-color: #eee; - border-color: #eee #eee #ddd; -} - -.tabs .active > a, .tabs .active > a:hover, -.cbi-tabmenu .active > a, .cbi-tabmenu .active > a:hover, -.cbi-tab > a:link, .cbi-tab > a:hover { - color: #000000; - background-color: #fff; - border: 1px solid #ddd; - border-bottom-color: transparent; - cursor: default; -} - -.tabs .menu-dropdown, .tabs .dropdown-menu, -.cbi-tabmenu .menu-dropdown, .cbi-tabmenu .dropdown-menu { - top: 35px; - border-width: 1px; - border-radius: 0 2px 2px 2px; -} - -.tabs a.menu:after, .tabs .dropdown-toggle:after, -.cbi-tabmenu a.menu:after, .cbi-tabmenu .dropdown-toggle:after { - border-top-color: #999; - margin-top: 15px; - margin-left: 5px; -} - -.tabs li.open.menu .menu, .tabs .open.dropdown .dropdown-toggle, -.cbi-tabmenu li.open.menu .menu, .cbi-tabmenu .open.dropdown .dropdown-toggle { - border-color: #999; -} - -.tabs li.open a.menu:after, .tabs .dropdown.open .dropdown-toggle:after, -.cbi-tabmenu li.open a.menu:after, .cbi-tabmenu .dropdown.open .dropdown-toggle:after { - border-top-color: #555; -} - -.tab-content > .tab-pane, -.tab-content > div { - display: none; -} - -.tab-content > .active { - display: block; -} - -.breadcrumb { - padding: 7px 14px; - margin: 0 0 18px; - background-color: #f5f5f5; - background-repeat: repeat-x; - border: 1px solid #ddd; - border-radius: 2px; - box-shadow: inset 0 1px 0 #fff; -} - -.breadcrumb li { - display: inline; -} - -.breadcrumb .divider { - padding: 0 5px; - color: #bfbfbf; -} - -.breadcrumb .active a { - color: #404040; -} - -footer { - margin-top: 30px; - padding-top: 20px; - padding-bottom: 20px; - border-top: 1px solid #404040; -} - -.btn.danger, -.alert-message.danger, -.btn.danger:hover, -.alert-message.danger:hover, -.btn.error, -.alert-message.error, -.btn.error:hover, -.alert-message.error:hover, -.btn.success, -.alert-message.success, -.btn.success:hover, -.alert-message.success:hover, -.btn.info, -.alert-message.info, -.btn.info:hover, -.alert-message.info:hover { - color: #fff; -} - -.btn .close, .alert-message .close { - font-family: Arial, sans-serif; - line-height: 18px; -} - -.btn.danger, -.alert-message.danger, -.btn.error, -.alert-message.error { - background: linear-gradient(to bottom, #ee5f5b, #c43c35) repeat-x; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); -} - -.btn.success, .alert-message.success { - background: linear-gradient(to bottom, #62c462, #57a957) repeat-x; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); -} - -.btn.info, .alert-message.info { - background: linear-gradient(to bottom, #5bc0de, #339bb9) repeat-x; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); -} - -.alert-message.notice { - background: linear-gradient(to bottom, #efefef, #fefefe) repeat-x; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); -} - -.btn, -.cbi-button { - cursor: pointer; - display: inline-block; - background: linear-gradient(#fff, #fff 25%, #e6e6e6) no-repeat; - padding: 5px 14px 6px; - color: #333; - font-size: 12px; - line-height: normal; - border: 1px solid #ccc; - border-bottom-color: #bbb; - border-radius: 2px; - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); -} - -.btn:focus, -.cbi-button:focus { - outline: 1px dotted #666; -} - -.cbi-input-invalid, -.cbi-value-error input { - color: #f00; - border-color: #f00; -} - -.cbi-button-positive, -.cbi-button-fieldadd, -.cbi-button-add, -.cbi-button-save { - border-color: #4a4; - color: #4a4; -} - -.cbi-button-neutral, -.cbi-button-download, -.cbi-button-find, -.cbi-button-link, -.cbi-button-up, -.cbi-button-down { - color: #444; -} - -.btn.primary, -.cbi-button-action, -.cbi-button-apply, -.cbi-button-reload, -.cbi-button-edit { - border-color: #4aa44b; - color: #4aa44b; -} - -.cbi-button-negative, -.cbi-section-remove .cbi-button, -.cbi-button-reset, -.cbi-button-remove { - border-color: #c44; - color: #c44; -} - -.cbi-page-actions::after { - display: table; - content: ""; - clear: both; -} - -.cbi-page-actions > :not([method="post"]):not(.cbi-button-apply):not(.cbi-button-save):not(.cbi-button-reset) { - float: left; - margin-right: .4em; -} - -.btn.primary, -.cbi-button-action.important, -.cbi-page-actions .cbi-button-apply, -.cbi-section-actions .cbi-button-edit { - color: #fff; - background: #4aa44b; -} - -.cbi-button-positive.important, -.cbi-page-actions .cbi-button-save { - color: #fff; - background: linear-gradient(to bottom, #4a4, #484) no-repeat; -} - -.cbi-button-negative.important { - color: #fff; - background: linear-gradient(to bottom, #c44, #c00) no-repeat; -} - -.cbi-page-actions .cbi-button-apply + .cbi-button-save { - background: linear-gradient(#fff, #fff 25%, #e6e6e6); - color: #4a4; -} - -.cbi-dropdown { - border: 1px solid #ccc; - border-radius: 2px; - display: inline-flex; - padding: 0; - cursor: pointer; - height: auto; - background: linear-gradient(#fff 0%, #e9e8e6 100%); - position: relative; - color: #404040; -} - -.cbi-dropdown:focus { - outline: 2px solid #4b6e9b; -} - -.cbi-dropdown > ul { - margin: 0 !important; - padding: 0; - list-style: none; - overflow-x: hidden; - overflow-y: auto; - display: flex; - width: 100%; -} - -.cbi-dropdown > ul.preview { - display: none; -} - -.cbi-dropdown > .open, -.cbi-dropdown > .more { - flex-grow: 0; - flex-shrink: 0; - display: flex; - flex-direction: column; - justify-content: center; - text-align: center; - line-height: 2em; - padding: 0 .25em; -} - -.cbi-dropdown > .more, -.cbi-dropdown > ul > li[placeholder] { - color: #777; - font-weight: bold; - display: none; -} - -.cbi-dropdown > ul > li { - display: none; - padding: .25em; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - flex-shrink: 1; - flex-grow: 1; - align-items: center; - align-self: center; - color: #404040; - min-height: 20px; -} - -.cbi-dropdown > ul > li .hide-open { display: block; display: initial; } -.cbi-dropdown > ul > li .hide-close { display: none; } - -.cbi-dropdown > ul > li[display]:not([display="0"]) { - border-left: 1px solid #ccc; -} - -.cbi-dropdown[empty] > ul { - max-width: 1px; -} - -.cbi-dropdown > ul > li > form { - display: none; - margin: 0; - padding: 0; - pointer-events: none; -} - -.cbi-dropdown > ul > li img { - vertical-align: middle; - margin-right: .25em; -} - -.cbi-dropdown > ul > li > form > input[type="checkbox"] { - margin: 0; -} - -.cbi-dropdown > ul > li input[type="text"] { - height: 20px; -} - -.cbi-dropdown[open] { - position: relative; -} - -.cbi-dropdown[open] > ul.dropdown { - display: block; - background: #f6f6f5; - border: 1px solid #918e8c; - box-shadow: 0 0 4px #918e8c; - position: absolute; - z-index: 1000; - max-width: none; - min-width: 100%; - width: auto; -} - -.cbi-dropdown > ul > li[display], -.cbi-dropdown[open] > ul.preview, -.cbi-dropdown[open] > ul.dropdown > li, -.cbi-dropdown[multiple] > ul > li > label, -.cbi-dropdown[multiple][open] > ul.dropdown > li, -.cbi-dropdown[multiple][more] > .more, -.cbi-dropdown[multiple][empty] > .more { - flex-grow: 1; - display: flex; -} - -.cbi-dropdown[empty] > ul > li, -.cbi-dropdown[optional][open] > ul.dropdown > li[placeholder], -.cbi-dropdown[multiple][open] > ul.dropdown > li > form { - display: block; -} - -.cbi-dropdown[open] > ul.dropdown > li .hide-open { display: none; } -.cbi-dropdown[open] > ul.dropdown > li .hide-close { display: block; display: initial; } - -.cbi-dropdown[open] > ul.dropdown > li { - border-bottom: 1px solid #ccc; -} - -.cbi-dropdown[open] > ul.dropdown > li[selected] { - background: #b0d0f0; -} - -.cbi-dropdown[open] > ul.dropdown > li.focus { - background: linear-gradient(90deg, #a3c2e8 0%, #84aad9 100%); -} - -.cbi-dropdown[open] > ul.dropdown > li:last-child { - margin-bottom: 0; - border-bottom: none; -} - -.cbi-dropdown[disabled] { - pointer-events: none; - opacity: .6; -} - -input[type="text"] + .cbi-button, -input[type="password"] + .cbi-button, -select + .cbi-button { - border-radius: 2px; - border-color: #ccc; - margin: 2px 0 2px 3px; - padding: 0 12px; - vertical-align: top; - height: 28px; - font-size: 13px; - font-weight: normal; - line-height: 28px; -} - -select + .cbi-button { - #border-left-color: transparent; -} - -.cbi-title-ref { - color: #f39800; -} - -.cbi-title-ref::after { - content: " ➙ "; -} - -.cbi-tooltip-container { - cursor: help; - padding: 5px 3px 5px 3px; -} - -.cbi-tooltip { - position: absolute; - z-index: 1000; - left: -1000px; - opacity: 0; - transition: opacity .25s ease-out; -} - -.cbi-tooltip-container:hover .cbi-tooltip:not(:empty) { - left: auto; - opacity: 1; - transition: opacity .25s ease-in; -} - -.zonebadge .cbi-tooltip { - padding: 1px; - background: inherit; - margin: -1.6em 0 0 -5px; - border-radius: 2px; - pointer-events: none; - box-shadow: 0 0 3px #444; -} - -.zonebadge .cbi-tooltip > * { - margin: 1px; -} - -.zone-forwards { - display: flex; - flex-wrap: wrap; -} - -.zone-forwards > * { - flex: 1 1 40%; - padding: 1px; -} - -.zone-forwards > span { - flex-basis: 10%; - text-align: center; -} - -.zone-forwards .zone-src, -.zone-forwards .zone-dest { - display: flex; - flex-direction: column; -} - -.btn.active, .btn:active { - box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05); -} - -.btn.disabled { - cursor: default; - background-image: none; - opacity: 0.65; - box-shadow: none; -} - -.btn[disabled] { - cursor: default; - background-image: none; - opacity: 0.65; - box-shadow: none; -} - -.btn.large { - font-size: 15px; - line-height: normal; - padding: 9px 14px 9px; - border-radius: 2px; -} - -.btn.small { - padding: 7px 9px 7px; - font-size: 11px; -} - -button.btn::-moz-focus-inner, input[type=submit].btn::-moz-focus-inner { - padding: 0; - border: 0; -} - -.close { - float: right; - color: #000; - font-size: 20px; - font-weight: bold; - line-height: 13.5px; - opacity: 0.25; -} - -.close:hover { - color: #000; - text-decoration: none; - opacity: 0.4; -} - -.alert-message { - position: relative; - padding: 30px; - margin-top: 25px; - margin-bottom: 25px; - color: #404040; - background: #f0e68c; - border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); - border-width: 1px; - border-style: solid; - border-radius: 2px; - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25); -} - -.alert-message .close { - margin-top: 1px; - *margin-top: 0; -} - -.alert-message a { - font-weight: bold; - color: #404040; -} - -.alert-message.danger p a, -.alert-message.error p a, -.alert-message.success p a, -.alert-message.info p a { - color: #fff; -} - -.alert-message h5 { - line-height: 18px; -} - -.alert-message p { - margin-bottom: 0; -} - -.alert-message div { - margin-top: 15px; - margin-bottom: 10px; - line-height: 28px; -} - -.label { - padding: 3px 3px 3px 3px; - font-size: 8px; - font-weight: normal; - color: #fff !important; - text-transform: uppercase; - white-space: nowrap; - background-color: #bfbfbf; - border-radius: 2px; - text-shadow: none; -} - -a.label:link, -a.label:visited { - color: #fff; -} - -a.label:hover { - text-decoration: none; -} - -.label.important { - background-color: #c43c35; -} - -.label.warning { - background-color: #f89406; -} - -.label.success { - background-color: #46a546; -} - -.label.notice { - background-color: #62cffc; -} - -/* LuCI specific items */ -.hidden { display: none } - -#memtotal > div, -#memfree > div, -#memcache > div, -#membuff > div, -#conns > div { - border: 1px solid #ccc; - border-radius: 2px 2px 2px 2px; - color: #808080; - display: inline-block; - font-size: 12px; - line-height: 18px; -} - -#xhr_poll_status { - cursor: pointer; -} - -form.inline { display: inline; margin-bottom: 0; } - -header .pull-right { padding-top: 21px; } - -#modemenu li:last-child span.divider { display: none } - -#syslog { width: 100%; } - -.cbi-section-table .tr:hover .td, -.cbi-section-table .tr:hover .th, -.cbi-section-table .tr:hover::before { - background-color: #f5f5f5; -} - -.cbi-section-table .tr.cbi-section-table-descr .th { - font-weight: normal; -} - -.cbi-section-table-titles.named::before, -.cbi-section-table-descr.named::before, -.cbi-section-table-row[data-title]::before { - content: attr(data-title) " "; - display: table-cell; - padding: 10px 10px 9px; - line-height: 18px; - font-weight: bold; - vertical-align: middle; -} - -.cbi-section-table-titles.named::before, -.cbi-section-table-descr.named::before, -.cbi-section-table-row[data-title]::before { - border-top: 1px solid #ddd; -} - -.left { text-align: left !important; } -.right { text-align: right !important; } -.center { text-align: center !important; } -.top { vertical-align: top !important; } -.middle { vertical-align: middle !important; } -.bottom { vertical-align: bottom !important; } - -.cbi-value-field { line-height: 1.5em; } - -.cbi-value-field input[type=checkbox], -.cbi-value-field input[type=radio] { - margin-top: 8px; - margin-right: 6px; -} - -table table td, -.cbi-value-field table td { - border: none; -} - -.table.cbi-section-table input[type="password"], -.table.cbi-section-table input[type="text"], -.table.cbi-section-table textarea, -.table.cbi-section-table select { - width: 100%; -} - -.table.cbi-section-table .td.cbi-section-table-cell { - white-space: nowrap; - text-align: right; -} - -.table.cbi-section-table .td.cbi-section-table-cell select { - width: inherit; -} - -.td.cbi-section-actions { - text-align: right; - vertical-align: middle; -} - -.td.cbi-section-actions > * { - display: flex; -} - -.td.cbi-section-actions > * > *, -.td.cbi-section-actions > * > form > * { - flex: 1 1 4em; - margin: 0 1px; -} - -.td.cbi-section-actions > * > form { - display: inline-flex; - margin: 0; -} - -.table.valign-middle .td { - vertical-align: middle; -} - -.cbi-rowstyle-2, -.tr.table-titles, -.tr.cbi-section-table-titles { - background: #f9f9f9; -} - -.cbi-value-description { - background-image: url(/luci-static/resources/cbi/help.gif); - background-position: .25em .2em; - background-repeat: no-repeat; - margin: 10px 0 10px -5px; - padding: 0 0 0 26px; -} - -.cbi-section-error { - border: 1px solid #f00; - border-radius: 2px; - background-color: #fce6e6; - padding: 5px; - margin-bottom: 18px; -} - -.cbi-section-error ul { margin: 0 0 0 20px; } - -.cbi-section-error ul li { - color: #f00; - font-weight: bold; -} - -.ifacebox { - background-color: #fff; - border: 1px solid #ccc; - margin: 6px 4px; - text-align: center; - white-space: nowrap; - background-image: linear-gradient(#fff, #fff 25%, #f9f9f9); - border-radius: 2px; - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); - display: inline-flex; - flex-direction: column; - line-height: 1.2em; - min-width: 100px; -} - -.ifacebox .ifacebox-head { - border-bottom: 1px solid #ccc; - padding: 10px; - line-height: 1.2em; - background: #eee; -} - -.ifacebox .ifacebox-head.active { - background: #f0e68c; -} - -.ifacebox .ifacebox-body { - padding: .25em; -} - -.ifacebadge { - display: inline-block; - flex-direction: row; - white-space: nowrap; - background-color: #fff; - border: 1px solid #ccc; - padding: 5px 5px 3px 5px; - background-image: linear-gradient(#fff, #fff 25%, #f9f9f9); - border-radius: 2px; - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05); - cursor: default; - line-height: 1.2em; -} - -.ifacebadge img { - width: 16px; - height: 16px; - vertical-align: middle; -} - -.ifacebadge-active { - border-color: #000; - font-weight: bold; -} - -.network-status-table { - display: flex; - flex-wrap: wrap; -} - -.network-status-table .ifacebox { - margin: 10px 10px 15px 2px; - flex-grow: 1; -} - -.network-status-table .ifacebox-body { - display: flex; - flex-direction: column; - height: 100%; - text-align: left; - padding: 8px; -} - -.network-status-table .ifacebox-body > * { - margin: .25em; -} - -.network-status-table .ifacebox-body > span { - flex: 10 10 auto; - height: 100%; -} - -.network-status-table .ifacebox-body > div { - display: flex; - flex-wrap: wrap; - margin: -.125em; -} - -#dsl_status_table .ifacebox-body > span > strong { - display: inline-block; - min-width: 35%; -} - -.ifacebadge.large, -.network-status-table .ifacebox-body .ifacebadge { - display: inline-flex; - flex: 1; - padding: 10px 4px 10px 4px; - min-width: 220px; - margin: 10px 6px 4px 4px; -} - -.ifacebadge > *, -.ifacebadge.large > * { - margin: 0 .125em; -} - -.zonebadge { - padding: 2px; - border-radius: 2px; - display: inline-block; - white-space: nowrap; - color: #666; -} - -.zonebadge > em, -.zonebadge > strong { - margin: 0 2px; - display: inline-block; -} - -.zonebadge input { - width: 6em; -} - -.zonebadge > .ifacebadge { - margin-left: 2px; -} - -.zonebadge-empty { - border: 1px dashed #aaa; - color: #aaa; - font-style: italic; - font-size: smaller; -} - -div.cbi-value var, -.td.cbi-value-field var { - font-style: italic; - color: #215e21; -} - -.uci-change-list { - line-height: 170%; - white-space: pre; -} - -.uci-change-list del, -.uci-change-list ins, -.uci-change-list var, -.uci-change-legend-label del, -.uci-change-legend-label ins, -.uci-change-legend-label var { - text-decoration: none; - font-family: monospace; - font-style: normal; - border: 1px solid #ccc; - background: #eee; - padding: 2px; - display: block; - line-height: 15px; - margin-bottom: 1px; -} - -.uci-change-list ins, -.uci-change-legend-label ins { - border-color: #0f0; - background: #cfc; -} - -.uci-change-list del, -.uci-change-legend-label del { - border-color: #f00; - background: #fcc; -} - -.uci-change-list var, -.uci-change-legend-label var { - border-color: #ccc; - background: #eee; -} - -.uci-change-list var ins, -.uci-change-list var del { - display: inline-block; - border: none; - width: 100%; - padding: 0; -} - -.uci-change-legend { - padding: 5px; -} - -.uci-change-legend-label { - width: 150px; - float: left; -} - -.uci-change-legend-label > ins, -.uci-change-legend-label > del, -.uci-change-legend-label > var { - float: left; - margin-right: 4px; - width: 10px; - height: 10px; - display: block; - position: relative; -} - -.uci-change-legend-label var ins, -.uci-change-legend-label var del { - border: none; - position: absolute; - top: 2px; - left: 2px; - right: 2px; - bottom: 2px; -} - -html body.apply-overlay-active { - height: calc(100vh - 63px); -} - -#applyreboot-section { - line-height: 300%; -} - -.login{ - text-align: center; - background-color: #fff; - border-radius: 20px; - width: 300px; - height: 350px; - position: absolute; - left: 50%; - top: 50%; - transform: translate(-50%,-50%); -} diff --git a/luci-theme-ezengreen/htdocs/luci-static/resources/ezengreen/images/ezenlink.png b/luci-theme-ezengreen/htdocs/luci-static/resources/ezengreen/images/ezenlink.png deleted file mode 100755 index 070a12b7da56ad334a98ffb87ca1a382af985ca4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 553 zcmV+^0@nSBP)5Rm*L{Kop!rxswj!voA{raViK6tZ*v8R6tTepaO_o zK%jz<3ScijlMX@!jz*fb7UN%5LM!a|X5Y-td%h{l5<`};@jZaZ<;8JG{Ov%{2>=2f zjE$E=aylzEHXZ{Y&?A5!fj0+a};rI%Z*jv2iL{ zMgq8CqI=*$2EfYY1rNJ&#m0k@fwA!kz*?8~dk$t1{z70E8s|4@}f?f1JGsh-A*IZ+iaOa7=K r8C)FHmOJQUD(bA18eYuZ#s%OHNQeZcR0cH!00000NkvXXu0mjf(L3<` diff --git a/luci-theme-ezengreen/htdocs/luci-static/resources/ezengreen/images/favicon.ico b/luci-theme-ezengreen/htdocs/luci-static/resources/ezengreen/images/favicon.ico deleted file mode 100755 index dd14062c9b9520f0de40f938a7cfa0ecc0edc154..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4286 zcmeHHJ5Iwu5M3%tvJDcVz;u*8f+a4HirPo;4cI_I3Zw{$CRJKGAHg+Mj$mq<$Q=ce zdC!`0R+i(~2|^TJ^jObl=gqveW6TNug23>Zj8AB;4%?Ff3*-B*Qmg#!2eR< z;`K8IBJHZhPFmtq&A*#phCl?=U%1$Tms7_P3xJq0)&)x95L~^=?%Qz7N%1V5ct3Q9IyS=|P{_Q}6eY=TUFv z)zsRt#1<0E#nyMRvgz~JA@iet?(uVey@%NISKq6b>wI2)K7?P->JAQS?mX@lW1f$9 zQ~y@zIqu+}01k-7?z|7?uoe&rsJE|&a)v-au18Vx?>;EajH$xWNFbst{M z>B*mJZR~uGfl6QO2~cyZU+eGN!5;uQkTJK}&#v>}nF1N0daQ?Xx7BXrM_t~%6L5Z= zSGgDPwZ3m{99_O0{7pXPU4b{~sy8$SetsV*Q2n;@JUDpA8NfNILo~GRm_I5oDljVW z*9w#!Yq@-Wx7N(JnB)1wyx5s7>;v$1U08QpTK81i*=cFN&&tAG0rzF`*im^K`T>j! BrMdtB diff --git a/luci-theme-ezengreen/htdocs/luci-static/resources/ezengreen/images/footer.png b/luci-theme-ezengreen/htdocs/luci-static/resources/ezengreen/images/footer.png deleted file mode 100755 index c7e2e393ac0c035c9a41f7e9d095bd11c4099971..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 836 zcmV-K1H1f*P)s+)P~w1iKdod zscmgBclR0#Sg?&vEJUVn^1i)(IdXxJpLs9u?q+vpXJ@`|cJpR99AZ)8d^j>!S(>!f zrSoAMz#c#E;xkK=yLpygSn$q=&j5D$d6lKfCG{HsS^(BcOm6|)WNGqe)-~VG74f)y zkS~3I0MMIaw*}zP`EcfZ*qLR)cXI^$BFWO^5kS-Vu*vyWi7Ej5u8NNeH(}K~&(fs3 zl;E8Yw&+fT#tS!*V_p2%Mz#sJ3f1Pj<$Sn!4oWj)o`Ihb!<|S@=R*@fjnnS4G--*= zdx26vOOq!say}f8)XI&kX$g8w=0C~;bpY*W=9@GXBF={aE07a4OOv0@hYo;-%-wZ9 zJlfbKr;8-)L}8^i3S(;pqHc2oJ$9yhnY$myR~|fxcWMw|P(>md)*H@;V}q9woRHIb zU&)U#nF}X{HEv>5Rc_!`#t-nn z1F1gmJfq;vf%Bm~>)qld!tT+|(!_}WjTs)$)L?ncLkvplLYDQU9S>ek%)^+8WeACC zfi$EQRtj0}ObAr3&hZq_gV!T@ebI4SMeX>Hm6cW)E1(s>k@roR-xYsVtcb8pc9MNo zHvVC;fUY@hO$e%oQ$^nOoLOIb@XS!Hpsov+HPF$;t#D~m2>&hmUv}opAQ&?`%c=cj zZVY}P&pzM#1$`9FK(|CcdgmQpZNV$?r2npJA8pDYG#0#FoGjSWST;U$eKg3@#0X{W z&K&2b9q--NDeR7~EzfLYpSI_j*jVQ=KR*f^I;Z}-=**|->`%%a0Q>{Ia7QjydhGlF O0000 ul, .nav { - display: block; - float: left; - margin: 7px 8px 0 8px; - position: relative; - left: 0; -} - -header div > ul a, .nav a { - display: block; - float: left; - padding: 12px 6px 12px 6px; - line-height: 14px; - letter-spacing: 0.2px; -} - -.menu-dropdown, .dropdown-menu { - top: 38px; - min-width: 180px; - max-width: 260px; -} - -@media screen and (max-device-width: 660px) { - #maincontent.container { - width: 98%; - margin: 30px 0 0 6px; - } -} - -@media screen and (max-device-width: 360px) { - #maincontent.container { - width: 96%; - margin: 30px 0 0 6px; - } -} - -@media screen and (max-device-width: 200px) { - #maincontent.container { - width: 94%; - margin: 40px 0 0 2px; - } -} diff --git a/luci-theme-ezengreen/htdocs/luci-static/resources/ezengreen/images/omr-logo.png b/luci-theme-ezengreen/htdocs/luci-static/resources/ezengreen/images/omr-logo.png deleted file mode 100755 index 3d532aec038b0c7bf504b1583606b1139a43a037..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19149 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

bVaUL}!q88y{QQ?r(PMb$$ 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 GOZW$!hAhAU diff --git a/luci-theme-ezengreen/htdocs/luci-static/resources/menu-ezengreen.js b/luci-theme-ezengreen/htdocs/luci-static/resources/menu-ezengreen.js deleted file mode 100755 index 5400276b0..000000000 --- a/luci-theme-ezengreen/htdocs/luci-static/resources/menu-ezengreen.js +++ /dev/null @@ -1,118 +0,0 @@ -'use strict'; -'require baseclass'; -'require ui'; - -return baseclass.extend({ - __init__: function() { - ui.menu.load().then(L.bind(this.render, this)); - }, - - render: function(tree) { - var node = tree, - url = ''; - - this.renderModeMenu(tree); - - if (L.env.dispatchpath.length >= 3) { - for (var i = 0; i < 3 && node; i++) { - node = node.children[L.env.dispatchpath[i]]; - url = url + (url ? '/' : '') + L.env.dispatchpath[i]; - } - - if (node) - this.renderTabMenu(node, url); - } - - document.addEventListener('poll-start', this.handleBodyMargin); - document.addEventListener('poll-stop', this.handleBodyMargin); - document.addEventListener('uci-new-changes', this.handleBodyMargin); - document.addEventListener('uci-clear-changes', this.handleBodyMargin); - window.addEventListener('resize', this.handleBodyMargin); - - this.handleBodyMargin(); - }, - - renderTabMenu: function(tree, url, level) { - var container = document.querySelector('#tabmenu'), - ul = E('ul', { 'class': 'tabs' }), - children = ui.menu.getChildren(tree), - activeNode = null; - - for (var i = 0; i < children.length; i++) { - var isActive = (L.env.dispatchpath[3 + (level || 0)] == children[i].name), - activeClass = isActive ? ' active' : '', - className = 'tabmenu-item-%s %s'.format(children[i].name, activeClass); - - ul.appendChild(E('li', { 'class': className }, [ - E('a', { 'href': L.url(url, children[i].name) }, [ _(children[i].title) ] )])); - - if (isActive) - activeNode = children[i]; - } - - if (ul.children.length == 0) - return E([]); - - container.appendChild(ul); - container.style.display = ''; - - if (activeNode) - this.renderTabMenu(activeNode, url + '/' + activeNode.name, (level || 0) + 1); - - return ul; - }, - - renderMainMenu: function(tree, url, level) { - var ul = level ? E('ul', { 'class': 'dropdown-menu' }) : document.querySelector('#topmenu'), - children = ui.menu.getChildren(tree); - - if (children.length == 0 || level > 1) - return E([]); - - for (var i = 0; i < children.length; i++) { - var submenu = this.renderMainMenu(children[i], url + '/' + children[i].name, (level || 0) + 1), - subclass = (!level && submenu.firstElementChild) ? 'dropdown' : null, - linkclass = (!level && submenu.firstElementChild) ? 'menu' : null, - linkurl = submenu.firstElementChild ? '#' : L.url(url, children[i].name); - - var li = E('li', { 'class': subclass }, [ - E('a', { 'class': linkclass, 'href': linkurl }, [ _(children[i].title) ]), - submenu - ]); - - ul.appendChild(li); - } - - ul.style.display = ''; - - return ul; - }, - - renderModeMenu: function(tree) { - var ul = document.querySelector('#modemenu'), - children = ui.menu.getChildren(tree); - - for (var i = 0; i < children.length; i++) { - var isActive = (L.env.requestpath.length ? children[i].name == L.env.requestpath[0] : i == 0); - - ul.appendChild(E('li', { 'class': isActive ? 'active' : null }, [ - E('a', { 'href': L.url(children[i].name) }, [ _(children[i].title) ]), - ' ', - E('span', { 'class': 'divider' }, [ '|' ]) - ])); - - if (isActive) - this.renderMainMenu(children[i], children[i].name); - } - - if (ul.children.length > 1) - ul.style.display = ''; - }, - - handleBodyMargin: function(ev) { - var body = document.querySelector('body'), - head = document.querySelector('header'); - - body.style.marginTop = head.offsetHeight + 'px'; - } -}); diff --git a/luci-theme-ezengreen/luasrc/view/themes/ezengreen/footer.htm b/luci-theme-ezengreen/luasrc/view/themes/ezengreen/footer.htm deleted file mode 100755 index 0fdd0e4d3..000000000 --- a/luci-theme-ezengreen/luasrc/view/themes/ezengreen/footer.htm +++ /dev/null @@ -1,19 +0,0 @@ -<%# - Copyright 2008 Steven Barth - Copyright 2008 Jo-Philipp Wich - Copyright 2012 David Menting - Licensed to the public under the Apache License 2.0. --%> - -<% local ver = require "luci.version" %> - -

-
- - - - diff --git a/luci-theme-ezengreen/luasrc/view/themes/ezengreen/header.htm b/luci-theme-ezengreen/luasrc/view/themes/ezengreen/header.htm deleted file mode 100755 index f4a63ebaf..000000000 --- a/luci-theme-ezengreen/luasrc/view/themes/ezengreen/header.htm +++ /dev/null @@ -1,90 +0,0 @@ -<%# - Copyright 2008 Steven Barth - Copyright 2008-2016 Jo-Philipp Wich - Copyright 2012 David Menting - Licensed to the public under the Apache License 2.0. --%> - -<% - local sys = require "luci.sys" - local util = require "luci.util" - local http = require "luci.http" - local disp = require "luci.dispatcher" - - local boardinfo = util.ubus("system", "board") - - local node = disp.context.dispatched - - -- send as HTML5 - http.prepare_content("text/html") - - -- Get current and latest OMR version - local current_omr_version = luci.model.uci.cursor():get("openmptcprouter","settings","version") or "" - local latest_omr_version = luci.model.uci.cursor():get("openmptcprouter","latest_versions","omr") or "" - --%> - - - - - <%=striptags( (boardinfo.hostname or "?") .. ( (node and node.title) and ' - ' .. translate(node.title) or '')) %> - system - - - - - - - - - <% if node and node.css then %> - - <% end -%> - <% if css then %> - - <% end -%> - - - - - "> -
-
- -
-
- -
- <%- if luci.sys.process.info("uid") == 0 and luci.sys.user.getuser("root") and not luci.sys.user.getpasswd("root") then -%> -
-

<%:No password set!%>

-

<%:There is no password set on this router. Please configure a root password to protect the web interface.%>

- <% if disp.lookup("admin/system/admin") then %> - - <% end %> -
- <%- end -%> - <%- if current_omr_version ~= "" and latest_omr_version ~= "" and current_omr_version < latest_omr_version then -%> -
-

<%=translatef("你的蚂蚁聚合openmptcprouter of china商业版 版本号 %s 最新 版本号 %s 现在可以升级",current_omr_version,latest_omr_version)%>

- -
- <%- end -%> -
- - -
- - - - diff --git a/luci-theme-ezengreen/root/etc/uci-defaults/luci-theme-ezengreen b/luci-theme-ezengreen/root/etc/uci-defaults/luci-theme-ezengreen deleted file mode 100755 index e1c8313d2..000000000 --- a/luci-theme-ezengreen/root/etc/uci-defaults/luci-theme-ezengreen +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh - -if [ "$(uci -q get luci.themes.ezengreen)" = "" ]; then - uci batch <<-EOF - set luci.themes.ezengreen=/luci-static/ezengreen - set luci.main.mediaurlbase=/luci-static/ezengreen - commit luci - EOF -fi -exit 0 diff --git a/luci-theme-openwrt-2020/Makefile b/luci-theme-openwrt-2020/Makefile deleted file mode 100755 index e5ef95832..000000000 --- a/luci-theme-openwrt-2020/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# -# Copyright (C) 2020 Jo-Philipp Wich -# -# This is free software, licensed under the Apache License, Version 2.0 . -# - -include $(TOPDIR)/rules.mk - -LUCI_TITLE:=LuCI modern OpenWrt theme -LUCI_DEPENDS:= - -include $(TOPDIR)/feeds/luci/luci.mk - -# call BuildPackage - OpenWrt buildroot signature diff --git a/luci-theme-openwrt-2020/htdocs/luci-static/openwrt2020/GalanoGrotesqueW00-Regular.woff2 b/luci-theme-openwrt-2020/htdocs/luci-static/openwrt2020/GalanoGrotesqueW00-Regular.woff2 deleted file mode 100755 index 950ac98cc5f79db9863bd001fe66a20d551d0785..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29004 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 Dq@qpE diff --git a/luci-theme-openwrt-2020/htdocs/luci-static/openwrt2020/cascade.css b/luci-theme-openwrt-2020/htdocs/luci-static/openwrt2020/cascade.css deleted file mode 100755 index b412764d4..000000000 --- a/luci-theme-openwrt-2020/htdocs/luci-static/openwrt2020/cascade.css +++ /dev/null @@ -1,1925 +0,0 @@ -:root { - --main-bright-color: #00A3E1; - --main-dark-color: #002B49; - --secondary-bright-color: #FFFFFF; - --secondary-dark-color: #212322; - --danger-color: #CC1111; - --warning-color: #CC8800; - --regular-font: "GalanoGrotesqueW00-Regular"; - --base-font-size: 16px; -} - -@font-face { - font-family: "GalanoGrotesqueW00-Regular"; - src: url("GalanoGrotesqueW00-Regular.woff2") format("woff2"); -} - -/* - * resets and base style - */ - -* { - margin: 0; - padding: 0; - box-sizing: border-box; - text-decoration: none; - list-style: none; - color: inherit; - font-family: var(--regular-font), "sans-serif"; - border: none; - font-size: 100%; - background: none; - outline: none; - -webkit-appearance: none; - -webkit-text-size-adjust: none; -} - -html { - height: 100%; - width: 100%; - max-width: 1366px; - margin: 0 auto; - background: #fff linear-gradient(90deg, rgba(0, 0, 0, .8), rgba(0, 0, 0 ,.5), rgba(0, 0, 0, .8)); -} - -body { - background: var(--secondary-bright-color); - color: var(--secondary-dark-color); - font-size: var(--base-font-size); - cursor: default; - display: inline-flex; - flex-direction: column; - min-height: 100%; - min-width: 100%; -} - -/* - * scaffholding - */ - -#menubar { - background-color: var(--main-bright-color); - background-image: url("omr-logo.png"); - background-position: 10px center; - background-size: 50px 50px; - background-repeat: no-repeat; - padding: 0 1em 0 70px; - min-height: 70px; - display: flex; - align-items: center; - color: var(--secondary-bright-color); - flex: 0; - width: 100%; - box-shadow: inset 0 0 1px var(--main-dark-color); -} - -#menubar > * { - flex: 1 1 auto; -} - -#menubar .hostname { - font-weight: bold; - font-size: 2em; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -#menubar .distversion { - flex: 3; -} - -#indicators { - flex: 1 1 25%; - text-align: right; -} - -#indicators > * { - background: var(--secondary-bright-color); - color: var(--main-bright-color); - display: inline-block; - font-size: .85em; - line-height: 1.5em; - padding: 0 .5em; - margin: .125em; - border-radius: 1em; - cursor: pointer; - white-space: nowrap; -} - -#indicators > [data-style="inactive"] { - background: var(--main-bright-color); - color: var(--secondary-bright-color); - border: 2px solid var(--secondary-bright-color); - line-height: calc(1.5em - 4px); - padding: 0 calc(.5em - 2px); -} - -#menubar h2, -.skiplink { - display: none; -} - -#modemenu { - background: var(--main-bright-color); - padding: .5rem 1rem; - display: flex; - align-items: center; - color: var(--secondary-bright-color); - box-shadow: inset 0 0 1px var(--main-dark-color); - font-size: 1rem; - flex-wrap: wrap; -} - -#modemenu > * { - margin: .125rem; -} - -#modemenu > .active { - font-weight: bold; - border-bottom: 2px solid var(--secondary-bright-color); -} - -#maincontainer { - flex-direction: row; - display: inline-flex; - flex: 1 0 auto; -} - -#mainmenu { - flex: 1 1 200px; - background: var(--main-dark-color); - color: var(--main-bright-color); - padding: 1em; -} - -#mainmenu:empty { - max-width: 0; - padding: 1em 0; - transition: all .2s ease-in-out; -} - -#mainmenu > div { - position: sticky; - top: 1em; -} - -#mainmenu ul { - padding: 0; - margin: 0 0 .5em .5em; - line-height: 1.5em; -} - -#mainmenu ul > li { - list-style: none; -} - -#mainmenu li > ul { - max-height: 0; - overflow: hidden; - transition: max-height .1s ease-in-out; -} - -#mainmenu li.selected > a { - color: var(--secondary-bright-color); -} - -#mainmenu ul:not(.active) > li.selected > ul, -#mainmenu li.active > ul { - max-height: 3000px; - transition: max-height 1s ease-in-out; -} - -#mainmenu .l1 > li > a { - font-weight: bold; - font-size: 1.05em; -} - -#maincontent { - flex: 10; - padding: 1em 1em 0 1em; -} - -body > .luci { - flex: 0; - font-size: .7em; - padding: .25em; - text-align: right; - background: var(--main-bright-color); - color: var(--secondary-bright-color); - margin: 0; -} - -/* - * modal - */ - -body.modal-overlay-active { - overflow: hidden; -} - -body.modal-overlay-active #modal_overlay { - left: 0; - right: 0; - opacity: 1; -} - -#modal_overlay { - position: fixed; - top: 0; - bottom: 0; - left: -10000px; - right: 10000px; - background: rgba(0, 0, 0, 0.7); - z-index: 10000; - overflow-y: scroll; - -webkit-overflow-scrolling: touch; - transition: opacity .125s ease-in; - opacity: 0; -} - -#modal_overlay > .modal { - max-width: 1300px; - width: 80%; - margin: 10% auto 5rem auto; - background: var(--secondary-bright-color); - box-shadow: 0 0 3px 1px var(--main-bright-color); - padding: .5em; - border-radius: .25em; - display: flex; - flex-direction: column; -} - -.modal > h4:first-child { - padding: .5rem; - margin: -.5rem -.5rem .5rem -.5rem; - background: var(--main-bright-color); - color: var(--secondary-bright-color); - border-radius: .25rem .25rem 0 0; -} - -.modal > *:first-child:last-child { - margin: .5em 0 !important; -} - -.modal .cbi-section > legend:first-child { font-size: 120%; } - - -/* - * table layout - */ - -.table { - display: table; - width: 100%; - margin: 0 0 1rem 0; - position: relative; -} - -.tr { - display: table-row; -} - -.tr.cbi-section-table-titles[data-title]::before { - font-weight: bold; - border-top: none; -} - -.tr[data-title]::before { - content: attr(data-title); - display: table-cell; - border-top: 1px solid var(--main-dark-color); - padding: .5em; -} - -.th { - font-weight: bold; - display: table-cell; - padding: .5em; - /* word-break: break-word; */ -} - -.cbi-section-table-descr .th { - opacity: .8; - font-size: 90%; - font-weight: normal; -} - -.td { - display: table-cell; - border-top: 1px solid var(--main-dark-color); - padding: .5em; - vertical-align: middle; -} - -.td input:not([type]), -.td input[type="text"], -.td input[type="password"], -.td select, -.td .cbi-dropdown:not(.btn):not(.cbi-button), -.td .cbi-dynlist, -.td .control-group { - min-width: auto; - width: 100%; -} - -.tr.drag-over-above { - box-shadow: 0 -6px 6px var(--main-bright-color); -} - -.tr.drag-over-below { - box-shadow: 0 6px 6px var(--main-bright-color); -} - -.tr.placeholder { - height: 4em; - position: relative; -} - -.tr.placeholder > .td { - position: absolute; - left: 0; - right: 0; - bottom: 0; - text-align: center; - line-height: 3em; - font-size: 90%; - opacity: .8; -} - -/* - * view specific table invariants - */ - - #cbi-wireless-wifi-device .ifacebadge { - flex-direction: column; - justify-content: space-around; - } - -.assoclist .td, -[data-page="admin-status-overview"] .td { - font-size: .9rem; - vertical-align: middle; -} - -.assoclist .td:nth-of-type(3) > span { - display: block; - max-width: 270px; - font-size: .8rem; -} - -.assoclist .td:nth-of-type(5) > span { - font-size: .8rem; -} - -.assoclist .td > .ifacebadge { - flex-wrap: wrap; - justify-content: space-around; - max-width: 120px; - padding: .2em; -} - -.assoclist .td > .ifacebadge::after { - overflow: hidden; - text-overflow: ellipsis; -} - -.assoclist .td > .ifacebadge > img { - margin: 0 25px; -} - -.assoclist .td > .ifacebadge[data-ssid][data-ifname] > span { - display: none; -} - -.assoclist .td > .ifacebadge[data-ssid][data-ifname]::after { - content: attr(data-ssid) " (" attr(data-ifname) ")"; -} - -[data-page="admin-status-overview"] .td:nth-of-type(3) { - min-width: 100px; -} - -[data-page="admin-network-firewall"] .table > .tr > *:nth-child(1) { - flex: 1 1 30%; -} - -[data-page="admin-network-wireless"] .cbi-section-actions > div { - display: flex; -} - -[data-page="admin-network-wireless"] .cbi-section-actions > div > * { - flex: 1; -} - -[data-page="admin-status-processes"] .table .td:nth-of-type(3), -[data-tab="leases"] .table .td[data-name="duid"] { - word-break: break-word; -} - -/* - * uci changelog - */ - -.uci-change-list { - font-size: 90%; - white-space: pre; - overflow: hidden; -} - -.uci-change-list del, -.uci-change-list ins, -.uci-change-list var, -.uci-change-legend-label del, -.uci-change-legend-label ins, -.uci-change-legend-label var { - text-decoration: none; - font-family: monospace; - font-style: normal; - border: 1px solid #ccc; - background: #eee; - padding: 2px; - display: block; - line-height: 15px; - margin-bottom: 1px; -} - -.uci-change-list h5 { - margin: .5em 0 .25em 0; -} - -.uci-change-list ins, -.uci-change-legend-label ins { - border-color: #0f0; - background: #cfc; -} - -.uci-change-list del, -.uci-change-legend-label del { - border-color: #f00; - background: #fcc; -} - -.uci-change-list var, -.uci-change-legend-label var { - border-color: #ccc; - background: #eee; -} - -.uci-change-list var ins, -.uci-change-list var del { - display: inline-block; - border: none; - width: 100%; - padding: 0; -} - -.uci-change-legend { - margin: .5em 0 0 0; - display: flex; - flex-wrap: wrap; -} - -.uci-change-legend-label { - flex: 1 1 10em; - white-space: nowrap; -} - -.uci-change-legend-label > ins, -.uci-change-legend-label > del, -.uci-change-legend-label > var { - float: left; - margin-right: 4px; - width: 16px; - height: 16px; - display: block; - position: relative; -} - -.uci-change-legend-label var ins, -.uci-change-legend-label var del { - border: none; - position: absolute; - top: 2px; - left: 2px; - right: 2px; - bottom: 2px; -} - -/* - * alignment helpers - */ - -.left { - text-align: left !important; -} - -.right { - text-align: right !important; -} - -.center { - text-align: center !important; -} - -.top { - vertical-align: top !important; -} - -.bottom { - vertical-align: bottom !important; -} - -.middle { - vertical-align: middle !important; -} - -.nowrap { - white-space: nowrap !important; -} - -.hidden { - display: none !important; -} - -/* - * legacy hacks - */ - -[width="33%"] { - width: 33%; - max-width: 33%; -} - -[width="50%"] { - width: 50%; - max-width: 50%; -} - -[data-name="_freq"] select { - min-width: auto; -} - -.cbi-value-field > div:first-child + br { - display: none; -} - -/* - * typography - */ - -h1, h2, h3, h4, h5, h6, -.cbi-section > legend:first-child { - font-weight: bold; - margin: 0 0 1rem 0; -} - -strong, b { - font-weight: bold; -} - -h1 { font-size: 160%; } -h2 { font-size: 150%; } -h3 { font-size: 140%; } -h4 { font-size: 130%; } -h5 { font-size: 120%; } -h6 { font-size: 110%; } - -.cbi-section > legend:first-child { font-size: 140%; } - -p, ul, textarea { - margin: 0 0 1em 0; -} - -p > textarea:last-child { - margin: 0; -} - -var { - color: var(--main-dark-color); - font-weight: bold; -} - -code { - font-family: monospace; - color: var(--main-dark-color); -} - -pre { - font-family: monospace; - margin: 0 0 1em 0; - font-size: .9rem; - box-shadow: inset 0 0 2px var(--main-dark-color); - padding: .25rem; - overflow: auto; -} - -big { - font-size: 110%; -} - -small { - font-size: 95%; -} - -ul { - padding: 0 0 0 1.5em; -} - -ul > li { - list-style: disc; -} - -/* - * widgets - */ - -.ifacebox, .ifacebadge, .zonebadge { - display: inline-flex; - line-height: 1.8em; - padding: 0 .25em; - margin: .25em; - box-shadow: 0px 0px 2px var(--main-dark-color); - font-size: .9em; - border-radius: .5em; - overflow: hidden; - font-size: .8rem; - vertical-align: text-top; - background: var(--secondary-bright-color); - align-items: center; - color: var(--secondary-dark-color); - vertical-align: middle; -} - -.zonebadge > .ifacebadge { - margin: .125em -.125em .125em .35em; -} - -.zonebadge > .ifacebadge > img -{ - margin: .125em 0 .125em .25em; -} - -.ifacebox { - display: inline-flex; - flex-direction: column; - padding: 0; - text-align: center; - width: 100%; - max-width: 100px; -} - -.ifacebox-head { - background: var(--main-bright-color); - width: 100%; -} - -.ifacebox-body { - text-align: center; - padding: .3em .25em .25em .25em; - white-space: nowrap; -} - -.ifacebadge { - display: inline-flex; - align-items: center; -} - -.ifacebadge.large { - line-height: 1.3em; -} - -.ifacebadge > img { - vertical-align: text-bottom; - margin: .25em; - height: 16px; -} - -.ifacebadge > * { - margin-left: .25em; -} - -.network-status-table { - display: inline-flex; - flex-wrap: wrap; - width: 100%; - margin: 0 -.2em 1em -.2em; -} - -.network-status-table > .ifacebox { - max-width: none; - flex: 1 1 45%; - margin: .25em; - min-width: 250px; -} - -.network-status-table > .ifacebox .ifacebadge { - font-size: 100%; - max-width: none; - flex: 1 1 45%; - margin: .2em; -} - -.network-status-table .ifacebox-body > div { - display: flex; - flex-wrap: wrap; - margin: .3em -.1em -.1em -.1em; -} - -.cbi-tooltip-container { - cursor: help; -} - -.cbi-tooltip { - position: absolute; - z-index: 10000; - left: -10000px; - box-shadow: 0 0 2px rgba(0, 0, 0, .7); - border-radius: 3px; - background: var(--secondary-bright-color); - white-space: pre; - padding: 2px 5px; - opacity: 0; - transition: opacity .25s ease-in; - font-size: .8rem; -} - -.cbi-tooltip.error { - color: var(--danger-color); -} - -.cbi-tooltip-container:hover .cbi-tooltip:not(:empty) { - left: auto; - opacity: 1; - transition: opacity .25s ease-in; -} - -.zone-forwards { - display: flex; - align-items: center; -} - -.cbi-progressbar { - border-radius: .25em; - position: relative; - min-width: 20rem; - height: 1.5em; - box-shadow: 0 0 2px var(--main-dark-color); - overflow: hidden; - margin: .125rem 0; -} - -.cbi-progressbar > div { - background: var(--main-bright-color); - height: 100%; - transition: width .25s ease-in; - width: 0%; -} - -.cbi-progressbar::after { - position: absolute; - bottom: 0; - top: 0; - right: 0; - left: 0; - text-align: center; - text-shadow: 0 0 2px var(--secondary-bright-color); - content: attr(title); - white-space: nowrap; - line-height: 1.5em; -} - -.cbi-tabmenu { - padding: 0; - margin: 0 -.5em 1em -.5em; - font-weight: bold; - color: var(--main-dark-color); -} - -.cbi-tabmenu > li { - display: inline-flex; - white-space: nowrap; - opacity: 1; - height: 1.8em; - max-height: none; - overflow: visible; -} - -.cbi-tabmenu > li > a { - flex: 1; - margin: .1em .5em; -} - -.cbi-tabmenu > .cbi-tab > a { - border-bottom: 2px solid var(--main-dark-color); -} - -[data-tab] { - opacity: 0; - max-height: 0; - transition: opacity .25s ease-in-out; - overflow: hidden; -} - -[data-tab-active="true"] { - opacity: 1; - height: auto; - max-height: none; - overflow: visible; -} - -.alert-message:not(.modal) { - box-shadow: 0 0 3px var(--secondary-dark-color); - padding: .5em; - margin: 0 0 1em 0; - background: var(--warning-color); - color: var(--secondary-bright-color); - transition: opacity .4s ease; -} - -.alert-message + .alert-message { - margin: -.5em 0 1em 0; -} - -.alert-message.info { - background: var(--main-bright-color); -} - -.alert-message.warning { - background: var(--warning-color); -} - -.alert-message.danger { - background: var(--danger-color); -} - -.alert-message .btn { - background: inherit; - box-shadow: 0 0 2px var(--secondary-bright-color); -} - -.alert-message .btn:hover { - box-shadow: 0 0 4px 1px var(--secondary-bright-color); -} - -@keyframes fade-in { - 0% { opacity: 0; } - 100% { opacity: 1; } -} - -@keyframes fade-out { - 0% { opacity: 1; } - 100% { opacity: 0; } -} - -.fade-in { - animation: fade-in .4s ease; -} - -.fade-out { - animation: fade-out .4s ease; - opacity: 0; -} - -/* - * forms - */ - -.cbi-button, button, .btn { - background: var(--main-bright-color); - color: var(--secondary-bright-color); - line-height: 1.5em; - border-radius: .25em; - cursor: pointer; - box-shadow: 0 0 2px var(--main-dark-color); - padding: 0 .5em; - display: inline-block; -} - -.cbi-button:hover, button:hover, .btn:hover { - box-shadow: 0 0 6px var(--main-bright-color); -} - -button + button, .btn + .btn, button + .btn, .btn + button, select + button { - margin-left: .25em; -} - -button.important { - background: var(--main-dark-color); -} - -button[disabled], button.disabled, .btn[disabled], .btn.disabled { - pointer-events: none; - opacity: .6; -} - -.cbi-button-apply, .cbi-button-positive { - background: var(--main-dark-color); -} - -.cbi-button-negative, .cbi-button-remove { - background: var(--danger-color); -} - -.cbi-checkbox { - position: relative; -} - -.cbi-checkbox input[type="checkbox"] { - position: absolute; - z-index: 10; - -webkit-appearence: button; - height: 1.3em; - width: 1.3em; - opacity: 0; - cursor: pointer; -} - -.cbi-checkbox input[type="checkbox"] + label { - position: relative; - display: inline-block; - width: 1.3em; - height: 1.3em; - vertical-align: text-top; -} - -.cbi-checkbox input[type="checkbox"] + label::before { - content: "\0a"; - height: 1em; - width: 1em; - box-shadow: 0 0 2px var(--main-dark-color); - display: inline-block; - border-radius: .25em; - margin: .15em 0; - position: absolute; - left: 0; - top: 0; -} - -.cbi-checkbox input[type="checkbox"]:checked + label::after { - content: "\0a"; - position: absolute; - display: inline-block; - background: var(--main-dark-color); - top: .35em; - left: .2em; - width: .6em; - height: .6em; - border-radius: .15em; - cursor: pointer; -} - -.cbi-checkbox input.cbi-input-invalid[type="checkbox"] + label::before { - box-shadow: 0 0 2px var(--danger-color); -} - -.cbi-checkbox input.cbi-input-invalid[type="checkbox"]:checked + label::after { - background: var(--danger-color); -} - -.cbi-checkbox input[type="checkbox"][disabled] + label::before, -.cbi-checkbox input[type="checkbox"][disabled] + label::after { - pointer-events: none; - opacity: .6; -} - -.cbi-checkbox input[type="checkbox"][disabled] { - pointer-events: none; -} - -input:not([type]), -input[type="text"], -input[type="password"], -select, -.cbi-dropdown:not(.btn):not(.cbi-button) { - border-bottom: 2px solid transparent; - box-shadow: inset 0 0 1px var(--main-dark-color); - padding: 0 .2rem; - line-height: 1.5rem; - min-height: calc(1.5rem + 2px); - min-width: 20rem; - border-radius: .25em; -} - -input:not([type]):focus, -input[type="text"]:focus, -input[type="password"]:focus, -select:focus, -.cbi-dropdown:not(.btn):not(.cbi-button):focus, -.cbi-dropdown[open]:not(.btn):not(.cbi-button) { - border-color: var(--main-dark-color); -} - -input[disabled]:not([type]), -input[disabled][type="text"], -input[disabled][type="password"], -select[disabled], -.cbi-dynlist[disabled] { - opacity: .6; - pointer-events: none; -} - -input:not([type]) + .btn, input:not([type]) + button, -input[type="text"] + .btn, input[type="text"] + button, -input[type="password"] + .btn, input[type="password"] + button { - margin: 0 0 2px -1px; - background: var(--main-dark-color); - border-radius: 0 .25em .25em 0; -} - -.control-group > select + .btn, .control-group > select + button { - margin-left: .25em; -} - -.control-group > input:not([type]) + .btn, .control-group > input:not([type]) + button, -.control-group > input[type="text"] + .btn, .control-group > input[type="text"] + button, -.control-group > input[type="password"] + .btn, .control-group > input[type="password"] + button { - margin: .125em .125em calc(.125em + 2px) calc(-.125em - .25em) !important; -} - -input[type="checkbox"] { - height: 1em; - vertical-align: middle; - -webkit-appearance: checkbox; -} - -select { - padding: .1rem 0; - -webkit-appearance: menulist; -} - -textarea { - width: 100%; - box-shadow: inset 0 0 2px var(--main-dark-color); - font-family: monospace; - font-size: .9rem; - padding: .2rem; -} - -.cbi-input-invalid, -.cbi-input-invalid:focus { - color: var(--danger-color); - border-color: var(--danger-color) !important; - box-shadow: inset 0 0 2px var(--danger-color); -} - -.control-group { - display: inline-flex; - margin: 0 -.125rem; - min-width: 20.25em; -} - -.control-group > *, -.control-group > .cbi-dropdown > ul > li { - justify-content: space-around; -} - -.control-group > * { - margin: .125rem !important; - min-width: auto !important; -} - -.control-group > select, -.control-group > input:not([type]), -.control-group > input[type="text"], -.control-group > input[type="password"] { - flex: 10; -} - -.cbi-value { - display: flex; - flex-wrap: wrap; - margin: 0 0 1em 0; -} - -.cbi-value > label:first-child { - flex: 1 1 40%; - padding: 0 .5em 0 0; -} - -.cbi-value > .cbi-value-field { - flex: 2 2 55%; -} - -.cbi-value > .cbi-section { - flex: 1 1 100%; -} - -.cbi-map-descr, -.cbi-tab-descr, -.cbi-section-descr, -.cbi-value-description, -.cbi-value[data-widget="CBI.DummyValue"] > div:first-child { - opacity: .8; - font-size: .9rem; - padding: .2em 0; -} - -.cbi-map-descr, -.cbi-tab-descr, -.cbi-section-descr, -.cbi-section-table, -.cbi-section-create { - margin: 0 0 1em 0; -} - -.cbi-dynlist { - display: inline-block; - font-size: 90%; - min-height: calc(1.5em + 2px); - line-height: 1.5em; - min-width: 20rem; - flex-wrap: wrap; -} - -.cbi-dynlist > .item { - box-shadow: 0 0 2px var(--main-dark-color); - margin: .3em 0; - padding: .15em 2em .15em .2em; - border-radius: .25em; - position: relative; - overflow: hidden; - transition: box-shadow .25s ease-in-out; - pointer-events: none; - flex: 1 1 100%; - word-break: break-all; -} - -.cbi-dynlist > .item::after { - content: "-"; - top: 0; - right: 0; - bottom: 0; - width: 1.6rem; - background: var(--main-bright-color); - display: flex; - align-items: center; - justify-content: space-around; - position: absolute; - box-shadow: 0 0 2px var(--main-dark-color); - text-align: center; - color: var(--secondary-bright-color); - cursor: pointer; - pointer-events: all; -} - -.cbi-dynlist[disabled] > .item::after { - pointer-events: none; -} - -.cbi-dynlist > .item:hover { - box-shadow: 0 0 2px var(--main-bright-color); -} - -.cbi-dynlist > .add-item { - flex: 1; - display: flex; -} - -.cbi-dynlist > .add-item > input { - flex: 1; - min-width: 18.5rem; - border-radius: .25rem 0 0 .25rem; -} - -.cbi-dynlist > .add-item > .btn { - flex: 0 0 1.6rem; - margin: 0 0 2px -1px; - width: 1.6rem; - text-align: center; -} - -.cbi-dropdown { - display: inline-flex !important; - cursor: pointer; - height: auto; - position: relative; - padding: 0 !important; -} - -.cbi-dropdown:not(.btn):not(.cbi-button) { - box-shadow: inset 0 0 1px var(--main-dark-color); -} - -.cbi-dropdown > ul { - margin: 0 !important; - padding: 0; - list-style: none; - overflow-x: hidden; - overflow-y: auto; - display: flex; - width: 100%; -} - -.cbi-dropdown.btn > ul:not(.dropdown) { - padding-left: .5em; -} - -.cbi-dropdown.btn.spinning > ul:not(.dropdown) { - padding-left: 0; -} - -.cbi-dropdown.btn > ul.dropdown > li { - color: var(--main-dark-color); -} - -.cbi-dropdown > ul.preview { - display: none; -} - -.cbi-dropdown > .open, -.cbi-dropdown > .more { - flex-grow: 0; - flex-shrink: 0; - display: flex; - flex-direction: column; - justify-content: center; - text-align: center; - padding: 0 .25em; -} - -.cbi-dropdown.btn > .open, -.cbi-dropdown.cbi-button > .open { - padding: 0 .5em; - margin-left: .5em; - border-left: 1px solid; -} - -.cbi-dropdown > .more, -.cbi-dropdown:not(.btn):not(.cbi-button) > ul > li[placeholder] { - display: none; - justify-content: center; - color: rgba(0, 0, 0, .5); -} - -.cbi-dropdown > ul > li { - display: none; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - flex-shrink: 1; - flex-grow: 1; - align-items: center; - align-self: center; - color: inherit; -} - -.cbi-dropdown > ul.dropdown > li, -.cbi-dropdown:not(.btn):not(.cbi-button) > ul > li { - padding: 0 .25em; -} - -.cbi-dropdown > ul > li .hide-open { display: block; display: initial; } -.cbi-dropdown > ul > li .hide-close { display: none; } - -.cbi-dropdown > ul > li[display]:not([display="0"]) { - border-left: 1px solid #ccc; -} - -.cbi-dropdown[empty] > ul { - max-width: 1px; - max-height: 1.5em; -} - -.cbi-dropdown > ul > li > form { - display: none; - margin: 0; - padding: 0; - pointer-events: none; -} - -.cbi-dropdown > ul > li img { - align-self: center; - margin-right: .25em; -} - -.cbi-dropdown > ul > li input[type="text"] { - margin: .25em 0; - border: none; - background: var(--secondary-bright-color); -} - -.cbi-dropdown[open] { - position: relative; -} - -.cbi-dropdown[open] > ul.dropdown { - display: block; - background: var(--secondary-bright-color); - box-shadow: 0 0 1px var(--main-dark-color), 0 0 4px rgba(0, 0, 0, .7); - position: absolute; - z-index: 1100; - max-width: none; - min-width: 100%; - width: auto; - transition: max-height .125s ease-in; -} - -.cbi-dropdown > ul > li[display], -.cbi-dropdown[open] > ul.preview, -.cbi-dropdown[open] > ul.dropdown > li, -.cbi-dropdown[multiple] > ul > li > label, -.cbi-dropdown[multiple][open] > ul.dropdown > li, -.cbi-dropdown[multiple][more] > .more, -.cbi-dropdown[multiple][empty] > .more { - flex-grow: 1; - display: flex !important; -} - -.cbi-dropdown[empty] > ul > li, -.cbi-dropdown[optional][open] > ul.dropdown > li[placeholder], -.cbi-dropdown[multiple][open] > ul.dropdown > li > form { - display: block !important; -} - -.cbi-dropdown[open] > ul.dropdown > li .hide-open { display: none; } -.cbi-dropdown[open] > ul.dropdown > li .hide-close { display: block; display: initial; } - -.cbi-dropdown[open] > ul.dropdown > li { - border-bottom: 1px solid #ccc; -} - -.cbi-dropdown[open] > ul.dropdown > li[selected] { - background: var(--main-dark-color); - color: var(--secondary-bright-color); -} - -.cbi-dropdown[open] > ul.dropdown > li.focus { - background: var(--main-bright-color); -} - -.cbi-dropdown[open] > ul.dropdown > li:last-child { - margin-bottom: 0; - border-bottom: none; -} - -.cbi-dropdown[open] > ul.dropdown > li[unselectable] { - opacity: 0.7; -} - -.cbi-dropdown[open] > ul.dropdown > li > input.create-item-input:first-child:last-child { - width: 100%; -} - -.cbi-dropdown[disabled] { - pointer-events: none; - opacity: .6; -} - -.cbi-filebrowser { - max-width: 100%; - width: 1px; - box-shadow: 0 0 2px var(--main-dark-color); - border-radius: .25rem; - display: flex; - flex-direction: column; - opacity: 0; - height: 0; - overflow: hidden; -} - -.cbi-filebrowser.open { - min-width: 20rem; - width: auto; - opacity: 1; - height: auto; - overflow: visible; - transition: opacity .25s ease-in; -} - -.cbi-filebrowser > * { - max-width: 100%; - overflow: hidden; - text-overflow: ellipsis; - padding: 0 0 .25em 0; - margin: .25em .25em 0px .25em; - white-space: nowrap; - border-bottom: 1px solid var(--main-dark-color); -} - -.cbi-filebrowser .cbi-button-positive { - margin-right: .25em; -} - -.cbi-filebrowser > div { - border-bottom: none; -} - -.cbi-filebrowser > ul > li { - display: flex; - flex-direction: row; - align-items: center; -} - -.cbi-filebrowser > ul > li a:hover { - font-weight: bold; - text-decoration: underline; -} - -.cbi-filebrowser > ul > li > div:first-child { - flex: 10; - overflow: hidden; - text-overflow: ellipsis; -} - -.cbi-filebrowser > ul > li > div:last-child { - flex: 3 3 10em; - text-align: right; -} - -.cbi-filebrowser > ul > li > div:last-child > button { - padding: .125em .25em; - margin: 1px 0 1px .25em; -} - -.cbi-filebrowser .upload { - display: flex; - flex-direction: row; - flex-wrap: wrap; - margin: 0 -.125em .25em -.125em; - padding: 0 0 .125em 0px; - border-bottom: 1px solid var(--main-dark-color); -} - -.cbi-filebrowser .upload > * { - margin: .125em; - flex: 1; -} - -.cbi-filebrowser .upload > div > input { - width: 100%; -} - -.cbi-section-actions { - text-align: right; -} - -.cbi-page-actions { - flex-wrap: wrap; - width: 100%; - justify-content: flex-end; - margin-bottom: 1em; - margin-top: 1em; - border-top: 1px solid var(--main-dark-color); - padding-top: 1em; - text-align: right; -} - -div[id$=".ipaddr"] > input, -.cbi-value-field > div > input[type="password"] { - min-width: 18.5rem; - border-radius: .25rem 0 0 .25rem; -} - -div[id$=".txpower"] { - flex-wrap: wrap; - align-items: center; -} - -div[id$=".txpower"] > span { - white-space: nowrap; - margin-left: .25em; -} - -div[id$=".editlist"] { - flex: 1; -} - -[data-errors]::after { - content: attr(data-errors); - background: var(--danger-color); - color: var(--secondary-bright-color); - border-radius: .6rem; - height: 1.1rem; - padding: 0 .25rem; - font-size: .9rem; - display: inline-block; - font-weight: bold; - min-width: .6rem; - line-height: 1rem; - margin: -.1rem 0 0 -.2rem; - text-align: center; -} - -@keyframes spin { - 100% { transform: rotate(360deg); } -} - -.spinning { - position: relative; - padding-left: 2.1em !important; -} - -.spinning::before { - position: absolute; - display: block; - align-items: center; - top: 0; - bottom: 0; - left: .4em; - width: 1.3em; - height: 1.3em; - animation: spin 1s linear infinite; - content: url("spinner.svg"); - margin: auto; -} - -button.spinning, .btn.spinning { - padding-left: 1.6em !important; -} - -button.spinning::before, .btn.spinning::before { - filter: invert(1); - left: .2em; - width: 1.2em; - height: 1.2em; -} - -#view > div.spinning:first-child { - padding: .5em 0; -} - -#view > *:last-child { - margin: 0 0 1em 0; -} - -.label { - background: var(--main-bright-color); - color: var(--secondary-bright-color); - font-size: .8rem; - padding: 0 .4rem; - border-radius: .5rem; -} - -.label.warning { - background: var(--danger-color); -} - -ul.deps { - margin: 0; - padding: 0; - font-size: .9rem; -} - -ul.errors { - margin: 0 0 1em 0; - padding: 0; -} - -@media only screen and (max-width: 800px) { - body { - padding-top: 70px; - } - - #maincontent { - padding: .25em; - max-width: 100vw; - } - - #menubar { - background: var(--main-bright-color); - padding: 0 .5em; - position: fixed; - top: 0; - z-index: 1000; - } - - #menubar > h2 { - flex: 0 0 2em; - display: block; - border: 2px solid var(--secondary-bright-color); - color: var(--secondary-bright-color); - border-radius: .5em; - cursor: pointer; - font-size: 100%; - margin: 0 1em 0 0; - } - - #menubar > h2:hover { - border-color: var(--secondary-bright-color); - color: var(--secondary-bright-color); - } - - #menubar > h2 > * { - display: none; - } - - #menubar > h2::before { - content: "☰"; - width: 35px; - line-height: 35px; - text-align: center; - display: inline-block; - color: inherit; - font-weight: bold; - } - - #menubar > h2.active::before { - content: "×"; - font-size: 200%; - } - - #menubar .hostname { - font-size: 1.6em; - } - - .distversion { - display: none; - } - - #modemenu { - padding: .125em .25em; - } - - #mainmenu { - overflow-x: hidden; - overflow-y: auto; - max-width: 0; - padding: 1em 0; - transition: max-width .25s ease-in-out, padding .25s ease-in-out; - position: fixed; - z-index: 900; - height: 100%; - } - - #mainmenu.active { - max-width: 200px; - padding: 1em 1em calc(1em + 70px) 1em; - overflow-x: visible; - } - - #mainmenu > div { - position: static; - } - - #mainmenu ul > li { - padding: .25em 0; - } - - .hide-xs { - display: none !important; - } - - .table { - display: flex; - flex-direction: column; - } - - .tr { - display: block; - border-bottom: 1px solid var(--main-dark-color); - margin-bottom: .5em; - padding-bottom: .5em; - } - - .tr.cbi-section-table-titles[data-title]::before, - .tr.cbi-section-table-titles, - .tr.cbi-section-table-descr { - display: none; - } - - .tr[data-title]::before { - display: block; - font-weight: bold; - border-top: none; - padding: .4em 0; - font-size: 110%; - } - - .td { - display: block; - border-top: none; - text-align: left !important; - padding: .2em 0; - } - - .th, .table-titles { - display: none; - } - - .td[data-title] { - position: relative; - padding: .2em 0 .2em 40%; - } - - .td[data-title]::before { - content: attr(data-title) ": "; - white-space: nowrap; - font-weight: bold; - width: 40%; - overflow: hidden; - text-overflow: ellipsis; - position: absolute; - left: 0; - top: 0; - bottom: 0; - padding: .2em 0; - text-align: left; - display: inline-flex; - align-items: center; - } - - .td[data-title]::after { - content: ""; - width: 2em; - position: absolute; - left: calc(40% - 2em); - top: 0; - bottom: 0; - display: block; - background: linear-gradient(90deg, rgba(255, 255, 255, 0), var(--secondary-bright-color) 90%); - } - - [data-page="admin-status-overview"] .cbi-section:nth-of-type(1) .td:first-of-type, - [data-page="admin-status-overview"] .cbi-section:nth-of-type(2) .td:first-of-type { - font-weight: bold; - max-width: none; - width: 100%; - } - - [data-page="admin-status-overview"] .td > span > span { font-size: .9rem; } - - [data-page="admin-status-routes"] .table:nth-of-type(3) .td:nth-of-type(1) { word-break: break-all; } - - [data-page="admin-network-firewall-zones"] .td[data-name="_info"] { - padding: .2em 0; - line-height: 2.2rem; - } - - [data-page="admin-network-firewall-zones"] .td[data-name="_info"]::before, - [data-page="admin-network-firewall-zones"] .td[data-name="_info"]::after { - display: none; - } - - [data-page="admin-network-firewall-zones"] .td[data-name="_info"] label { - font-size: 1rem; - } - - #cbi-wireless-wifi-device .tr { display: flex; flex-wrap: wrap; } - #cbi-wireless-wifi-device .tr > *:nth-child(1) { flex: 1 1 20%; align-self: center; } - #cbi-wireless-wifi-device .tr > *:nth-child(2) { flex: 2 2 75%; } - #cbi-wireless-wifi-device .tr > *:nth-child(3) { flex: 3 3 100%; } - - #cbi-network-interface .tr { display: flex; flex-wrap: wrap; } - #cbi-network-interface .tr > *:nth-child(1) { flex: 1 1 33%; align-self: center; } - #cbi-network-interface .tr > *:nth-child(2) { flex: 2 2 60%; align-self: center; font-size: .9rem; overflow: hidden; } - #cbi-network-interface .tr > *:nth-child(3) { flex: 3 3 100%; } - #cbi-network-interface .tr > *:nth-child(2) > div { overflow: hidden; text-overflow: ellipsis; } - - .assoclist .tr { - display: flex; - flex-wrap: wrap; - } - - .assoclist .td > .ifacebadge { - max-width: 90px; - } - - .assoclist .td > .ifacebadge > img { - margin: 0 35px; - } - - .assoclist .td > .ifacebadge > span { - display: none; - } - - .assoclist .td > .ifacebadge[data-ifname]::after { - content: attr(data-ifname); - } - - .assoclist .td > .ifacebadge[data-signal]::after { - content: attr(data-signal) " dBm"; - } - - .assoclist .td:nth-of-type(3) { - font-weight: bold; - font-size: 1rem; - } - - .assoclist .td:nth-of-type(1), .assoclist .td:nth-of-type(4) { - flex: 1 1 100px; - margin-right: .5em; - } - - .assoclist .td:nth-of-type(3), .assoclist .td:nth-of-type(5) { - flex: 2 2 calc(100% - 110px); - overflow: hidden; - text-overflow: ellipsis; - align-self: center; - } - - .assoclist .td:nth-of-type(6) { flex: 1; text-align: right !important; } - .assoclist .td[data-title] { padding: .2em 0; } - .assoclist .td[data-title]::before, - .assoclist .td[data-title]::after { display: none; } - - .leases6 .td:nth-of-type(3) { word-wrap: break-word; } - - .td.cbi-section-actions > div { display: flex; } - .td.cbi-section-actions > div > * { flex: 1; } - - body.modal-overlay-active #modal_overlay > .modal { - width: 95%; - margin: 5% auto; - } - - input:not([type]), - input[type="text"], - input[type="password"], - select, - .cbi-dropdown:not(.btn):not(.cbi-button), - .cbi-dynlist { - min-height: calc(2.2rem + 2px); - line-height: 2.2rem; - font-size: 1.2rem; - min-width: 10rem; - } - - button, .btn { - line-height: 1.8rem; - font-size: 1.2rem; - } - - select { - padding: .4em 0; - } - - .cbi-value > .cbi-value-field { - flex: 1 0 100%; - display: flex; - flex-direction: column; - max-width: 100%; - } - - .cbi-value > .cbi-value-field > div[id] { - display: flex; - flex-direction: row; - } - - .cbi-value > .cbi-value-field > div[id] > input, - .cbi-value > .cbi-value-field > div[id] > select, - .cbi-value > .cbi-value-field > div[id] > .cbi-filebrowser.open { - flex: 1; - width: 100%; - } - - .cbi-dynlist .item::after, - .cbi-dynlist .add-item > .btn { - line-height: 2em; - flex-basis: 2rem; - width: 2rem; - } - - .ifacebadge.large { - font-size: .9rem; - } - - .control-group > *, - .control-group > .cbi-dropdown > ul > li { - flex: 1; - white-space: normal; - word-wrap: break-word; - } - - .cbi-page-actions .cbi-dropdown, - .cbi-page-actions .cbi-button-apply:first-child { - flex-basis: 100%; - } - - .cbi-checkbox { - margin: .25rem; - } - - .cbi-tabmenu { - margin: 0 -.25em 1em -.25em; - } - - .cbi-tooltip { - font-size: 1rem; - box-shadow: 0 0 4px rgba(0, 0, 0, .7); - } - - .cbi-value > label:first-child { - padding: 0 0 .5em 0; - } - - [data-page="admin-system-admin-sshkeys"] .cbi-dynlist > .item { - font-size: .9rem; - line-height: 1rem; - } - - [data-page="admin-system-opkg"] .control-group { - flex-wrap: wrap; - } - - [data-page="admin-status-iptables"] h2 + div.right { - margin: 0 0 1em 0 !important; - display: flex; - } -} - -@media only screen and (min-width: 800px) and (max-width: 1200px) { - .assoclist .tr > *:nth-of-type(2) { - display: none; - } -} diff --git a/luci-theme-openwrt-2020/htdocs/luci-static/openwrt2020/favicon.png b/luci-theme-openwrt-2020/htdocs/luci-static/openwrt2020/favicon.png deleted file mode 100755 index 7c3f3acb1f0c7c142d0dbd3f42a4926b07f8eb38..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 535 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 diff --git a/luci-theme-openwrt-2020/htdocs/luci-static/openwrt2020/spinner.svg b/luci-theme-openwrt-2020/htdocs/luci-static/openwrt2020/spinner.svg deleted file mode 100755 index f3b52efac..000000000 --- a/luci-theme-openwrt-2020/htdocs/luci-static/openwrt2020/spinner.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/luci-theme-openwrt-2020/htdocs/luci-static/resources/menu-openwrt2020.js b/luci-theme-openwrt-2020/htdocs/luci-static/resources/menu-openwrt2020.js deleted file mode 100755 index b6fbfd4c2..000000000 --- a/luci-theme-openwrt-2020/htdocs/luci-static/resources/menu-openwrt2020.js +++ /dev/null @@ -1,147 +0,0 @@ -'use strict'; -'require baseclass'; -'require ui'; - -return baseclass.extend({ - __init__: function() { - ui.menu.load().then(L.bind(this.render, this)); - }, - - render: function(tree) { - var node = tree, - url = ''; - - this.renderModeMenu(node); - - if (L.env.dispatchpath.length >= 3) { - for (var i = 0; i < 3 && node; i++) { - node = node.children[L.env.dispatchpath[i]]; - url = url + (url ? '/' : '') + L.env.dispatchpath[i]; - } - - if (node) - this.renderTabMenu(node, url); - } - - document.querySelector('#menubar > .navigation') - .addEventListener('click', ui.createHandlerFn(this, 'handleSidebarToggle')); - }, - - handleMenuExpand: function(ev) { - var a = ev.target, ul1 = a.parentNode.parentNode, ul2 = a.nextElementSibling; - - document.querySelectorAll('ul.mainmenu.l1 > li.active').forEach(function(li) { - if (li !== a.parentNode) - li.classList.remove('active'); - }); - - if (!ul2) - return; - - if (ul2.parentNode.offsetLeft + ul2.offsetWidth <= ul1.offsetLeft + ul1.offsetWidth) - ul2.classList.add('align-left'); - - ul1.classList.add('active'); - a.parentNode.classList.add('active'); - a.blur(); - - ev.preventDefault(); - ev.stopPropagation(); - }, - - renderMainMenu: function(tree, url, level) { - var l = (level || 0) + 1, - ul = E('ul', { 'class': 'mainmenu l%d'.format(l) }), - children = ui.menu.getChildren(tree); - - if (children.length == 0 || l > 2) - return E([]); - - for (var i = 0; i < children.length; i++) { - var isActive = (L.env.dispatchpath[l] == children[i].name), - isReadonly = children[i].readonly, - activeClass = 'mainmenu-item-%s%s'.format(children[i].name, isActive ? ' selected' : ''); - - ul.appendChild(E('li', { 'class': activeClass }, [ - E('a', { - 'href': L.url(url, children[i].name), - 'click': (l == 1) ? ui.createHandlerFn(this, 'handleMenuExpand') : null - }, [ _(children[i].title) ]), - this.renderMainMenu(children[i], url + '/' + children[i].name, l) - ])); - } - - if (l == 1) - document.querySelector('#mainmenu').appendChild(E('div', [ ul ])); - - return ul; - }, - - renderModeMenu: function(tree) { - var menu = document.querySelector('#modemenu'), - children = ui.menu.getChildren(tree); - - for (var i = 0; i < children.length; i++) { - var isActive = (L.env.requestpath.length ? children[i].name == L.env.requestpath[0] : i == 0); - - if (i > 0) - menu.appendChild(E([], ['\u00a0|\u00a0'])); - - menu.appendChild(E('div', { 'class': isActive ? 'active' : null }, [ - E('a', { 'href': L.url(children[i].name) }, [ _(children[i].title) ]) - ])); - - if (isActive) - this.renderMainMenu(children[i], children[i].name); - } - - if (menu.children.length > 1) - menu.style.display = ''; - }, - - renderTabMenu: function(tree, url, level) { - var container = document.querySelector('#tabmenu'), - l = (level || 0) + 1, - ul = E('ul', { 'class': 'cbi-tabmenu' }), - children = ui.menu.getChildren(tree), - activeNode = null; - - if (children.length == 0) - return E([]); - - for (var i = 0; i < children.length; i++) { - var isActive = (L.env.dispatchpath[l + 2] == children[i].name), - activeClass = isActive ? ' cbi-tab' : '', - className = 'tabmenu-item-%s %s'.format(children[i].name, activeClass); - - ul.appendChild(E('li', { 'class': className }, [ - E('a', { 'href': L.url(url, children[i].name) }, [ _(children[i].title) ] ) - ])); - - if (isActive) - activeNode = children[i]; - } - - container.appendChild(ul); - container.style.display = ''; - - if (activeNode) - container.appendChild(this.renderTabMenu(activeNode, url + '/' + activeNode.name, l)); - - return ul; - }, - - handleSidebarToggle: function(ev) { - var btn = ev.currentTarget, - bar = document.querySelector('#mainmenu'); - - if (btn.classList.contains('active')) { - btn.classList.remove('active'); - bar.classList.remove('active'); - } - else { - btn.classList.add('active'); - bar.classList.add('active'); - } - } -}); diff --git a/luci-theme-openwrt-2020/luasrc/view/themes/openwrt2020/footer.htm b/luci-theme-openwrt-2020/luasrc/view/themes/openwrt2020/footer.htm deleted file mode 100755 index e9122f0b5..000000000 --- a/luci-theme-openwrt-2020/luasrc/view/themes/openwrt2020/footer.htm +++ /dev/null @@ -1,17 +0,0 @@ -<%# - Copyright 2020 Jo-Philipp Wich - Licensed to the public under the Apache License 2.0. --%> - -
-
- -

- <% local ver = require "luci.version" -%> - Powered by <%= ver.luciname %> (<%= ver.luciversion %>) -

- - - - - diff --git a/luci-theme-openwrt-2020/luasrc/view/themes/openwrt2020/header.htm b/luci-theme-openwrt-2020/luasrc/view/themes/openwrt2020/header.htm deleted file mode 100755 index fb0842df0..000000000 --- a/luci-theme-openwrt-2020/luasrc/view/themes/openwrt2020/header.htm +++ /dev/null @@ -1,63 +0,0 @@ -<%# - Copyright 2020 Jo-Philipp Wich - Licensed to the public under the Apache License 2.0. --%> - -<% - local sys = require "luci.sys" - local util = require "luci.util" - local http = require "luci.http" - local disp = require "luci.dispatcher" - local ver = require "luci.version" - - local boardinfo = util.ubus("system", "board") or { } - - local node = disp.context.dispatched - local path = table.concat(disp.context.path, "-") - - http.prepare_content("text/html; charset=UTF-8") --%> - - - - - - - - - - -<%=striptags( (boardinfo.hostname or "?") .. ( (node and node.title) and ' - ' .. translate(node.title) or '')) %> - LuCI - - - - - - - - - -
- - -
- <%- if luci.sys.process.info("uid") == 0 and luci.sys.user.getuser("root") and not luci.sys.user.getpasswd("root") and category ~= "failsafe" and path ~= "admin-system-admin-password" then -%> -
-

<%:No password set!%>

-

<%:There is no password set on this router. Please configure a root password to protect the web interface.%>

- <% if disp.lookup("admin/system/admin") then %> - - <% end %> -
- <%- end -%> - - diff --git a/luci-theme-openwrt-2020/root/etc/uci-defaults/30_luci-theme-openwrt-2020 b/luci-theme-openwrt-2020/root/etc/uci-defaults/30_luci-theme-openwrt-2020 deleted file mode 100755 index cd41631de..000000000 --- a/luci-theme-openwrt-2020/root/etc/uci-defaults/30_luci-theme-openwrt-2020 +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -if [ "$PKG_UPGRADE" != 1 ]; then - uci get luci.themes.OpenWrt2020 >/dev/null 2>&1 || \ - uci batch <<-EOF - set luci.themes.OpenWrt2020=/luci-static/openwrt2020 - commit luci - EOF -fi - -exit 0 From cca347992ce2607d2d67445aea0516c5f93bd34e Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Tue, 4 Jul 2023 18:31:37 +0200 Subject: [PATCH 15/20] Disable LUA header check for tracebox --- tracebox/patches/105-configure-header.patch | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 tracebox/patches/105-configure-header.patch diff --git a/tracebox/patches/105-configure-header.patch b/tracebox/patches/105-configure-header.patch new file mode 100644 index 000000000..cd5433395 --- /dev/null +++ b/tracebox/patches/105-configure-header.patch @@ -0,0 +1,10 @@ +--- a/configure.ac 2023-07-04 18:25:34.419067107 +0200 ++++ b/configure.ac 2023-07-04 18:25:42.558931140 +0200 +@@ -58,7 +58,6 @@ + esac ], + [ + AX_PROG_LUA +- AX_LUA_HEADERS + AX_LUA_LIBS + if test x"$LUA_LIB" = x; then + AC_MSG_ERROR([Lua library not found. You may try option --with-lua-suffix.]) From b8e40b5cde23688e259eb3ca2784becae7a36ecd Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Thu, 6 Jul 2023 08:47:58 +0200 Subject: [PATCH 16/20] Fix sqm-autorate init --- luci-app-sqm-autorate/root/etc/init.d/sqm-autorate | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/luci-app-sqm-autorate/root/etc/init.d/sqm-autorate b/luci-app-sqm-autorate/root/etc/init.d/sqm-autorate index 1485c924f..97c44e92e 100755 --- a/luci-app-sqm-autorate/root/etc/init.d/sqm-autorate +++ b/luci-app-sqm-autorate/root/etc/init.d/sqm-autorate @@ -21,13 +21,13 @@ _config_autorate() { config_get autorate "$1" autorate [ "${autorate}" != "1" ] && return - config_get min_download "$1" min_download - config_get download "$1" download - config_get max_download "$1" max_download + config_get min_download "$1" min_download "0" + config_get download "$1" download "0" + config_get max_download "$1" max_download "0" [ "${min_download}" == "0" ] || [ "${max_download}" == "0" ] || [ "${download}" == "0" ] && return - config_get min_upload "$1" min_upload - config_get upload "$1" upload - config_get max_upload "$1" max_upload + config_get min_upload "$1" min_upload "0" + config_get upload "$1" upload "0" + config_get max_upload "$1" max_upload "0" [ "${min_upload}" == "0" ] || [ "${max_upload}" == "0" ] || [ "${upload}" == "0" ] && return # config_get interface "$1" interface # cp /usr/share/sqm-autorate/cake-autorate_template.sh /usr/share/sqm-autorate/cake-autorate_config.${interface}.sh From 8b270e72647b29763f3facf739c138a93f6fd374 Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 7 Jul 2023 17:24:11 +0200 Subject: [PATCH 17/20] Fix omr-bypass --- luci-app-omr-bypass/Makefile | 6 +++++- luci-app-omr-bypass/root/etc/init.d/omr-bypass | 3 ++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/luci-app-omr-bypass/Makefile b/luci-app-omr-bypass/Makefile index bca6d24e6..8d166a2e4 100644 --- a/luci-app-omr-bypass/Makefile +++ b/luci-app-omr-bypass/Makefile @@ -7,7 +7,11 @@ include $(TOPDIR)/rules.mk LUCI_TITLE:=LuCI Interface to bypass domains #LUCI_DEPENDS:=+dnsmasq-full +shadowsocks-libev-ss-rules +(LINUX_5_4||LINUX_5_15||TARGET_x86_64):iptables-mod-ndpi +iptables-mod-extra +(LINUX_5_4||LINUX_5_15||TARGET_x86_64):kmod-ipt-ndpi +iptables -LUCI_DEPENDS:=+dnsmasq-full +shadowsocks-libev-ss-rules +(LINUX_5_4||LINUX_5_15):iptables-mod-ndpi +iptables-mod-extra +(LINUX_5_4||LINUX_5_15):kmod-ipt-ndpi +iptables +sqlite3-cli +LUCI_DEPENDS:=+dnsmasq-full +shadowsocks-libev-ss-rules +iptables-mod-extra +iptables +sqlite3-cli +ifneq ($(CONFIG_TARGET_ramips),) + LUCI_DEPENDS+=+(LINUX_5_4||LINUX_5_15):iptables-mod-ndpi +(LINUX_5_4||LINUX_5_15):kmod-ipt-ndpi +endif + PKG_LICENSE:=GPLv3 diff --git a/luci-app-omr-bypass/root/etc/init.d/omr-bypass b/luci-app-omr-bypass/root/etc/init.d/omr-bypass index 31045864d..c59107f8d 100755 --- a/luci-app-omr-bypass/root/etc/init.d/omr-bypass +++ b/luci-app-omr-bypass/root/etc/init.d/omr-bypass @@ -1008,7 +1008,8 @@ start_service() { sqlite3 /usr/share/omr-bypass/omr-bypass.db "select distinct(proto) from (select proto from hostproto union all select proto from ipproto) a order by proto;" ".exit" > /usr/share/omr-bypass/omr-bypass-proto.lst config_load omr-bypass config_foreach _add_proto_without_ndpi proto - sort < /usr/share/omr-bypass/omr-bypass-proto.lst > /usr/share/omr-bypass/omr-bypass-proto.lst + sort < /usr/share/omr-bypass/omr-bypass-proto.lst > /usr/share/omr-bypass/omr-bypass-proto.lst.new + mv /usr/share/omr-bypass/omr-bypass-proto.lst.new /usr/share/omr-bypass/omr-bypass-proto.lst logger -t "omr-bypass" "OMR-ByPass is running" } From ecf0b8979861a7c14c017acb6ee316e29e5eae9a Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Fri, 7 Jul 2023 20:02:40 +0200 Subject: [PATCH 18/20] Update sqm autorate --- .../root/etc/init.d/sqm-autorate | 10 +- .../usr/share/sqm-autorate/cake-autorate.sh | 535 +++++++++++------- ...utorate_template.sh => config_template.sh} | 14 +- ...{cake-autorate_defaults.sh => defaults.sh} | 2 + ...{cake-autorate_launcher.sh => launcher.sh} | 4 +- .../{cake-autorate_lib.sh => lib.sh} | 95 ++-- 6 files changed, 407 insertions(+), 253 deletions(-) rename luci-app-sqm-autorate/root/usr/share/sqm-autorate/{cake-autorate_template.sh => config_template.sh} (95%) rename luci-app-sqm-autorate/root/usr/share/sqm-autorate/{cake-autorate_defaults.sh => defaults.sh} (99%) rename luci-app-sqm-autorate/root/usr/share/sqm-autorate/{cake-autorate_launcher.sh => launcher.sh} (77%) rename luci-app-sqm-autorate/root/usr/share/sqm-autorate/{cake-autorate_lib.sh => lib.sh} (66%) diff --git a/luci-app-sqm-autorate/root/etc/init.d/sqm-autorate b/luci-app-sqm-autorate/root/etc/init.d/sqm-autorate index 97c44e92e..3f2d5c87d 100755 --- a/luci-app-sqm-autorate/root/etc/init.d/sqm-autorate +++ b/luci-app-sqm-autorate/root/etc/init.d/sqm-autorate @@ -31,14 +31,14 @@ _config_autorate() { [ "${min_upload}" == "0" ] || [ "${max_upload}" == "0" ] || [ "${upload}" == "0" ] && return # config_get interface "$1" interface # cp /usr/share/sqm-autorate/cake-autorate_template.sh /usr/share/sqm-autorate/cake-autorate_config.${interface}.sh - cp /usr/share/sqm-autorate/cake-autorate_template.sh /usr/share/sqm-autorate/cake-autorate_config.$1.sh + cp /usr/share/sqm-autorate/config_template.sh /usr/share/sqm-autorate/config.$1.sh } _launch_autorate() { logger -t "SQM-autorate" "Launch..." procd_open_instance # shellcheck disable=SC2086 - procd_set_param command /usr/share/sqm-autorate/cake-autorate_launcher.sh + procd_set_param command /usr/share/sqm-autorate/launcher.sh procd_set_param limits nofile="51200 51200" procd_set_param respawn 0 10 0 procd_set_param stderr 1 @@ -46,16 +46,12 @@ _launch_autorate() { } start_service() { + rm -f /usr/share/sqm-autorate/config.*.sh config_load sqm config_foreach _config_autorate queue _launch_autorate } -stop_service() { - rm -f /usr/share/sqm-autorate/cake-autorate_config.*.sh - pkill -9 cake-autorate -} - reload_service() { stop start diff --git a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate.sh b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate.sh index e45c1c306..6067cdca8 100755 --- a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate.sh +++ b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate.sh @@ -1,22 +1,22 @@ #!/bin/bash -# CAKE-autorate automatically adjusts CAKE bandwidth(s) +# cake-autorate automatically adjusts CAKE bandwidth(s) # in dependence on: a) receive and transmit transfer rates; and b) latency # (or can just be used to monitor and log transfer rates and latency) -# requires packages: bash; and one of the supported ping binaries +# requires: bash; and one of the supported ping binaries # each cake-autorate instance must be configured using a corresponding config file # Project homepage: https://github.com/lynxthecat/cake-autorate # Licence details: https://github.com/lynxthecat/cake-autorate/blob/master/LICENCE.md -# Author: @Lynx (OpenWrt forum) -# Inspiration taken from: @moeller0 (OpenWrt forum) +# Author and maintainer: lynxthecat +# Contributors: rany2; moeller0; richb-hanover cake_autorate_version="2.0.0" -## cake-autorate uses multiple asynchronous processes including +## cake-autorate uses multiple asynchronous processes including: ## main - main process ## monitor_achieved_rates - monitor network transfer rates ## maintain_pingers - manage pingers and active reflectors @@ -26,7 +26,7 @@ cake_autorate_version="2.0.0" ## ## IPC is facilitated via FIFOs in the form of anonymous pipes ## accessible via fds in the form: ${process_name_fd} -## thereby to enable transferring commands and data between processes +## thereby to enable transferring instructions and data between processes # Initialize file descriptors ## -1 signifies that the log file fd will not be used and @@ -60,15 +60,20 @@ export LC_ALL=C # Set PREFIX PREFIX=/root/cake-autorate -# shellcheck source=cake-autorate_lib.sh -. "${PREFIX}/cake-autorate_lib.sh" -# shellcheck source=cake-autorate_defaults.sh -. "${PREFIX}/cake-autorate_defaults.sh" +# shellcheck source=lib.sh +. "${PREFIX}/lib.sh" +# shellcheck source=defaults.sh +. "${PREFIX}/defaults.sh" +# get valid config overrides +mapfile -t valid_config_entries < <(grep -E '^[^(#| )].*=' "${PREFIX}/defaults.sh" | sed -e 's/[\t ]*\#.*//g' -e 's/=.*//g') trap cleanup_and_killall INT TERM EXIT cleanup_and_killall() { + # Do not fail on error for this critical cleanup code + set +e + trap true INT TERM EXIT log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" @@ -88,13 +93,19 @@ cleanup_and_killall() # terminate any processes that remain, save for main and intercept_stderr unset "proc_pids[main]" - intercept_stderr_pid="${proc_pids[intercept_stderr]}" - unset "proc_pids[intercept_stderr]" + intercept_stderr_pid="${proc_pids[intercept_stderr]:-}" + if [[ -n "${intercept_stderr_pid}" ]] + then + unset "proc_pids[intercept_stderr]" + fi terminate "${proc_pids[@]}" # restore original stderr, and terminate intercept_stderr - exec 2>&"${original_stderr_fd}" - terminate "${intercept_stderr_pid}" + if [[ -n "${intercept_stderr_pid}" ]] + then + exec 2>&"${original_stderr_fd}" + terminate "${intercept_stderr_pid}" + fi log_msg "SYSLOG" "Stopped cake-autorate with PID: ${BASHPID} and config: ${config_path}" @@ -109,38 +120,36 @@ log_msg() local type="${1}" local msg="${2}" local instance_id="${instance_id:-"unknown"}" + local log_timestamp=${EPOCHREALTIME} case ${type} in DEBUG) - [[ "${debug}" == "0" ]] && return # skip over DEBUG messages where debug disabled - log_timestamp=${EPOCHREALTIME} + ((debug == 0)) && return # skip over DEBUG messages where debug disabled ((log_DEBUG_messages_to_syslog)) && ((use_logger)) && logger -t "cake-autorate.${instance_id}" "${type}: ${log_timestamp} ${msg}" ;; - + ERROR) - log_timestamp=${EPOCHREALTIME} ((use_logger)) && logger -t "cake-autorate.${instance_id}" "${type}: ${log_timestamp} ${msg}" ;; SYSLOG) - log_timestamp=${EPOCHREALTIME} ((use_logger)) && logger -t "cake-autorate.${instance_id}" "INFO: ${log_timestamp} ${msg}" ;; *) - log_timestamp=${EPOCHREALTIME} ;; esac - + # Output to the log file fifo if available (for rotation handling) # else output directly to the log file - if (( log_fd >= 0 )); then + if (( log_fd >= 0 )) + then ((log_to_file)) && printf '%s; %(%F-%H:%M:%S)T; %s; %s\n' "${type}" -1 "${log_timestamp}" "${msg}" >&"${log_fd}" else ((log_to_file)) && printf '%s; %(%F-%H:%M:%S)T; %s; %s\n' "${type}" -1 "${log_timestamp}" "${msg}" >> "${log_file_path}" fi - + ((terminal)) && printf '%s; %(%F-%H:%M:%S)T; %s; %s\n' "${type}" -1 "${log_timestamp}" "${msg}" } @@ -172,7 +181,7 @@ rotate_log_file() cat "${log_file_path}" > "${log_file_path}.old" true > "${log_file_path}" fi - + ((output_processing_stats)) && print_headers t_log_file_start_us=${EPOCHREALTIME/./} get_log_file_size_bytes @@ -211,14 +220,15 @@ generate_log_file_scripts() while [[ ! -f "${run_path}/last_log_file_export" ]] do sleep 1 - if (( ++read_try >= \${timeout_s} )); then + if (( ++read_try >= \${timeout_s} )) + then printf "ERROR: Timeout (\${timeout_s}s) reached before new log file export identified.\n" >&2 exit 1 fi done read -r log_file_export_path < "${run_path}/last_log_file_export" - + printf "Log file export complete.\n" printf "Log file available at location: " @@ -249,31 +259,35 @@ export_log_file() log_msg "DEBUG" "Exporting log file with path: ${log_file_path/.log/_${log_file_export_datetime}.log}" # Now export with or without compression to the appropriate export path - if ((log_file_export_compress)); then + if ((log_file_export_compress)) + then log_file_export_path="${log_file_export_path}.gz" - if [[ -f "${log_file_path}.old" ]]; then + if [[ -f "${log_file_path}.old" ]] + then gzip -c "${log_file_path}.old" > "${log_file_export_path}" gzip -c "${log_file_path}" >> "${log_file_export_path}" else gzip -c "${log_file_path}" > "${log_file_export_path}" fi else - if [[ -f "${log_file_path}.old" ]]; then + if [[ -f "${log_file_path}.old" ]] + then cp "${log_file_path}.old" "${log_file_export_path}" cat "${log_file_path}" >> "${log_file_export_path}" else cp "${log_file_path}" "${log_file_export_path}" fi fi - + printf '%s' "${log_file_export_path}" > "${run_path}/last_log_file_export" } flush_log_fd() { log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" - while read -r -t 0.01 -u "${log_fd}" log_line + while read -r -t 0 -u "${log_fd}" do + read -r -u "${log_fd}" log_line printf '%s\n' "${log_line}" >> "${log_file_path}" done } @@ -321,7 +335,7 @@ maintain_log_file() # Verify log file time < configured maximum if (( (${EPOCHREALTIME/./}-t_log_file_start_us) > log_file_max_time_us )) then - + log_msg "DEBUG" "log file maximum time: ${log_file_max_time_mins} minutes has elapsed so flushing and rotating log file." flush_log_fd rotate_log_file @@ -342,7 +356,7 @@ maintain_log_file() done } -get_next_shaper_rate() +update_shaper_rate() { local direction="${1}" # 'dl' or 'ul' @@ -358,7 +372,8 @@ get_next_shaper_rate() ;; # bufferbloat detected, so decrease the rate providing not inside bufferbloat refractory period *bb*) - if (( t_start_us > (t_last_bufferbloat_us["${direction}"]+bufferbloat_refractory_period_us) )); then + if (( t_start_us > (t_last_bufferbloat_us["${direction}"]+bufferbloat_refractory_period_us) )) + then adjusted_achieved_rate_kbps=$(( (achieved_rate_kbps["${direction}"]*achieved_rate_adjust_down_bufferbloat)/1000 )) adjusted_shaper_rate_kbps=$(( (shaper_rate_kbps["${direction}"]*shaper_rate_adjust_down_bufferbloat)/1000 )) shaper_rate_kbps["${direction}"]=$(( adjusted_achieved_rate_kbps > min_shaper_rate_kbps["${direction}"] && adjusted_achieved_rate_kbps < adjusted_shaper_rate_kbps ? adjusted_achieved_rate_kbps : adjusted_shaper_rate_kbps )) @@ -366,19 +381,23 @@ get_next_shaper_rate() fi ;; # high load, so increase rate providing not inside bufferbloat refractory period - *high*) - if (( t_start_us > (t_last_bufferbloat_us["${direction}"]+bufferbloat_refractory_period_us) )); then + *high*) + if (( t_start_us > (t_last_bufferbloat_us["${direction}"]+bufferbloat_refractory_period_us) )) + then shaper_rate_kbps["${direction}"]=$(( (shaper_rate_kbps["${direction}"]*shaper_rate_adjust_up_load_high)/1000 )) fi ;; # low or idle load, so determine whether to decay down towards base rate, decay up towards base rate, or set as base rate *low*|*idle*) - if (( t_start_us > (t_last_decay_us["${direction}"]+decay_refractory_period_us) )); then + if (( t_start_us > (t_last_decay_us["${direction}"]+decay_refractory_period_us) )) + then - if ((shaper_rate_kbps["${direction}"] > base_shaper_rate_kbps["${direction}"])); then + if ((shaper_rate_kbps["${direction}"] > base_shaper_rate_kbps["${direction}"])) + then decayed_shaper_rate_kbps=$(( (shaper_rate_kbps["${direction}"]*shaper_rate_adjust_down_load_low)/1000 )) shaper_rate_kbps["${direction}"]=$(( decayed_shaper_rate_kbps > base_shaper_rate_kbps["${direction}"] ? decayed_shaper_rate_kbps : base_shaper_rate_kbps["${direction}"])) - elif ((shaper_rate_kbps["${direction}"] < base_shaper_rate_kbps["${direction}"])); then + elif ((shaper_rate_kbps["${direction}"] < base_shaper_rate_kbps["${direction}"])) + then decayed_shaper_rate_kbps=$(( (shaper_rate_kbps["${direction}"]*shaper_rate_adjust_up_load_low)/1000 )) shaper_rate_kbps["${direction}"]=$(( decayed_shaper_rate_kbps < base_shaper_rate_kbps["${direction}"] ? decayed_shaper_rate_kbps : base_shaper_rate_kbps["${direction}"])) fi @@ -387,7 +406,7 @@ get_next_shaper_rate() fi ;; *) - log_msg "ERROR" "unknown load condition: ${load_condition[${direction}]} in get_next_shaper_rate" + log_msg "ERROR" "unknown load condition: ${load_condition[${direction}]} in update_shaper_rate" kill $$ 2>/dev/null ;; esac @@ -431,17 +450,17 @@ monitor_achieved_rates() case "${command[0]:-}" in SET_VAR) - if [[ "${command[1]:-}" && "${command[2]:-}" ]] + if [[ "${#command[@]}" -eq 3 ]] then export -n "${command[1]}=${command[2]}" fi ;; SET_ARRAY_ELEMENT) - if [[ "${command[1]:-}" && "${command[2]:-}" && "${command[3]:-}" ]] - then - declare -A "${command[1]}"+="([${command[2]}]=${command[3]})" - fi - ;; + if [[ "${#command[@]}" -eq 4 ]] + then + declare -A "${command[1]}"+="([${command[2]}]=${command[3]})" + fi + ;; TERMINATE) log_msg "DEBUG" "Terminating monitor_achieved_rates." exit @@ -457,8 +476,8 @@ monitor_achieved_rates() [[ -f "${rx_bytes_path}" ]] && { read -r rx_bytes < "${rx_bytes_path}"; } 2> /dev/null || rx_bytes="${prev_rx_bytes}" [[ -f "${tx_bytes_path}" ]] && { read -r tx_bytes < "${tx_bytes_path}"; } 2> /dev/null || tx_bytes="${prev_tx_bytes}" - achieved_rate_kbps[dl]=$(( ((8000*(rx_bytes - prev_rx_bytes)) / compensated_monitor_achieved_rates_interval_us ) )) - achieved_rate_kbps[ul]=$(( ((8000*(tx_bytes - prev_tx_bytes)) / compensated_monitor_achieved_rates_interval_us ) )) + achieved_rate_kbps[dl]=$(( (8000*(rx_bytes - prev_rx_bytes)) / compensated_monitor_achieved_rates_interval_us )) + achieved_rate_kbps[ul]=$(( (8000*(tx_bytes - prev_tx_bytes)) / compensated_monitor_achieved_rates_interval_us )) ((achieved_rate_kbps[dl]<0)) && achieved_rate_kbps[dl]=0 ((achieved_rate_kbps[ul]<0)) && achieved_rate_kbps[ul]=0 @@ -468,14 +487,15 @@ monitor_achieved_rates() load_percent[dl]=$(( (100*achieved_rate_kbps[dl])/shaper_rate_kbps[dl] )) load_percent[ul]=$(( (100*achieved_rate_kbps[ul])/shaper_rate_kbps[ul] )) - + for pinger_fd in "${pinger_fds[@]:?}" do printf "SET_ARRAY_ELEMENT load_percent dl %s\n" "${load_percent[dl]}" >&"${pinger_fd}" printf "SET_ARRAY_ELEMENT load_percent ul %s\n" "${load_percent[ul]}" >&"${pinger_fd}" done - if ((output_load_stats)); then + if ((output_load_stats)) + then printf -v load_stats '%s; %s; %s; %s; %s' "${EPOCHREALTIME}" "${achieved_rate_kbps[dl]}" "${achieved_rate_kbps[ul]}" "${shaper_rate_kbps[dl]}" "${shaper_rate_kbps[ul]}" log_msg "LOAD" "${load_stats}" @@ -485,7 +505,7 @@ monitor_achieved_rates() prev_tx_bytes="${tx_bytes}" compensated_monitor_achieved_rates_interval_us=$(( monitor_achieved_rates_interval_us>(10*max_wire_packet_rtt_us) ? monitor_achieved_rates_interval_us : 10*max_wire_packet_rtt_us )) - + sleep_remaining_tick_time "${t_start_us}" "${compensated_monitor_achieved_rates_interval_us}" done @@ -498,26 +518,30 @@ classify_load() # thus ending up with high_delayed, low_delayed, etc. local direction="${1}" - if (( load_percent["${direction}"] > high_load_thr_percent )); then - load_condition["${direction}"]="high" - elif (( achieved_rate_kbps["${direction}"] > connection_active_thr_kbps )); then + if (( load_percent["${direction}"] > high_load_thr_percent )) + then + load_condition["${direction}"]="high" + elif (( achieved_rate_kbps["${direction}"] > connection_active_thr_kbps )) + then load_condition["${direction}"]="low" - else + else load_condition["${direction}"]="idle" fi - + ((bufferbloat_detected["${direction}"])) && load_condition["${direction}"]="${load_condition[${direction}]}_bb" - if ((sss_compensation)); then + if ((sss_compensation)) + then # shellcheck disable=SC2154 for sss_time_us in "${sss_times_us[@]}" do ((timestamp_usecs_past_minute=${EPOCHREALTIME/./}%60000000)) - if (( (timestamp_usecs_past_minute > (sss_time_us-sss_compensation_pre_duration_us)) && (timestamp_usecs_past_minute < (sss_time_us+sss_compensation_post_duration_us)) )); then + if (( (timestamp_usecs_past_minute > (sss_time_us-sss_compensation_pre_duration_us)) && (timestamp_usecs_past_minute < (sss_time_us+sss_compensation_post_duration_us)) )) + then load_condition["${direction}"]="${load_condition[${direction}]}_sss" break fi - done + done fi load_condition["${direction}"]="${direction}_${load_condition[${direction}]}" @@ -530,14 +554,14 @@ parse_preprocessor() # prepend REFLECTOR_RESPONSE and append timestamp as a checksum while read -r timestamp remainder do - printf "REFLECTOR_RESPONSE %s %s %s\n" "${timestamp}" "${remainder}" "${timestamp}" >&"${pinger_fds[pinger]}" + printf "REFLECTOR_RESPONSE %s %s %s\n" "${timestamp}" "${remainder}" "${timestamp}" >&"${pinger_fds[pinger]}" done } parse_tsping() { trap '' INT - trap 'terminate "${pinger_pid}" "${parse_preprocessor_pid}"' TERM EXIT + trap 'terminate "${pinger_pid}" "${parse_preprocessor_pid}"' TERM EXIT local parse_id="${1}" local reflectors=("${@:2}") @@ -560,7 +584,7 @@ parse_tsping() declare -A load_percent load_percent[dl]=0 load_percent[ul]=0 - + while true do unset command @@ -574,7 +598,7 @@ parse_tsping() ;; START_PINGER) - + exec {parse_preprocessor_fd}> >(parse_preprocessor) parse_preprocessor_pid="${!}" printf "SET_PROC_PID proc_pids %s %s\n" "${parse_id}_preprocessor" "${parse_preprocessor_pid}" >&"${main_fd}" @@ -609,7 +633,7 @@ parse_tsping() SET_VAR) - if [[ "${command[1]:-}" && "${command[2]:-}" ]] + if [[ "${#command[@]}" -eq 3 ]] then export -n "${command[1]}=${command[2]}" fi @@ -617,8 +641,8 @@ parse_tsping() ;; SET_ARRAY_ELEMENT) - - if [[ "${command[1]:-}" && "${command[2]:-}" && "${command[3]:-}" ]] + + if [[ "${#command[@]}" -eq 4 ]] then declare -A "${command[1]}"+="([${command[2]}]=${command[3]})" fi @@ -697,7 +721,7 @@ parse_tsping() printf "SET_ARRAY_ELEMENT dl_owd_delta_ewmas_us %s %s\n" "${reflector}" "${dl_owd_delta_ewmas_us[${reflector}]}" >&"${maintain_pingers_fd}" printf "SET_ARRAY_ELEMENT ul_owd_delta_ewmas_us %s %s\n" "${reflector}" "${ul_owd_delta_ewmas_us[${reflector}]}" >&"${maintain_pingers_fd}" - + printf "SET_ARRAY_ELEMENT last_timestamp_reflectors_us %s %s\n" "${reflector}" "${timestamp_us}" >&"${maintain_pingers_fd}" fi done @@ -706,7 +730,7 @@ parse_tsping() parse_fping() { trap '' INT - trap 'terminate "${pinger_pid}" "${parse_preprocessor_pid}"' TERM EXIT + trap 'terminate "${pinger_pid}" "${parse_preprocessor_pid}"' TERM EXIT local parse_id="${1}" @@ -732,7 +756,7 @@ parse_fping() load_percent[ul]=0 t_start_us="${EPOCHREALTIME/./}" - + while true do unset command @@ -781,7 +805,7 @@ parse_fping() SET_VAR) - if [[ "${command[1]:-}" && "${command[2]:-}" ]] + if [[ "${#command[@]}" -eq 3 ]] then export -n "${command[1]}=${command[2]}" fi @@ -790,7 +814,7 @@ parse_fping() SET_ARRAY_ELEMENT) - if [[ "${command[1]:-}" && "${command[2]:-}" && "${command[3]:-}" ]] + if [[ "${#command[@]}" -eq 4 ]] then declare -A "${command[1]}"+="([${command[2]}]=${command[3]})" fi @@ -807,7 +831,7 @@ parse_fping() continue ;; esac - fi + fi if [[ "${timestamp:-}" && "${reflector:-}" && "${seq_rtt:-}" && "${checksum:-}" ]] then @@ -819,7 +843,7 @@ parse_fping() rtt_us="${BASH_REMATCH[3]}000" rtt_us=$((${BASH_REMATCH[2]}000+10#${rtt_us:0:3})) - + dl_owd_us=$((rtt_us/2)) ul_owd_us="${dl_owd_us}" @@ -842,28 +866,28 @@ parse_fping() printf "REFLECTOR_RESPONSE %s %s %s %s %s %s %s %s %s %s %s\n" "${timestamp}" "${reflector}" "${seq}" "${dl_owd_baselines_us[${reflector}]}" "${dl_owd_us}" "${dl_owd_delta_ewmas_us[${reflector}]}" "${dl_owd_delta_us}" "${ul_owd_baselines_us[${reflector}]}" "${ul_owd_us}" "${ul_owd_delta_ewmas_us[${reflector}]}" "${ul_owd_delta_us}" >&"${main_fd}" timestamp_us="${timestamp//[.]}" - + printf "SET_ARRAY_ELEMENT dl_owd_baselines_us %s %s\n" "${reflector}" "${dl_owd_baselines_us[${reflector}]}" >&"${maintain_pingers_fd}" printf "SET_ARRAY_ELEMENT ul_owd_baselines_us %s %s\n" "${reflector}" "${ul_owd_baselines_us[${reflector}]}" >&"${maintain_pingers_fd}" printf "SET_ARRAY_ELEMENT dl_owd_delta_ewmas_us %s %s\n" "${reflector}" "${dl_owd_delta_ewmas_us[${reflector}]}" >&"${maintain_pingers_fd}" printf "SET_ARRAY_ELEMENT ul_owd_delta_ewmas_us %s %s\n" "${reflector}" "${ul_owd_delta_ewmas_us[${reflector}]}" >&"${maintain_pingers_fd}" - + printf "SET_ARRAY_ELEMENT last_timestamp_reflectors_us %s %s\n" "${reflector}" "${timestamp_us}" >&"${maintain_pingers_fd}" fi done } # IPUTILS-PING FUNCTIONS -parse_ping() +parse_ping() { trap '' INT - trap 'terminate "${pinger_pid}" "${parse_preprocessor_pid}"' TERM EXIT + trap 'terminate "${pinger_pid}" "${parse_preprocessor_pid}"' TERM EXIT # ping reflector, maintain baseline and output deltas to a common fifo local parse_id="${1}" local reflector="${2}" - + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" declare -A dl_owd_baselines_us @@ -879,7 +903,7 @@ parse_ping() declare -A load_percent load_percent[dl]=0 load_percent[ul]=0 - + while true do unset command @@ -914,9 +938,9 @@ parse_ping() SET_REFLECTOR) - if [[ "${command[1]:-}" ]] + if [[ "${#command[@]}" -eq 2 ]] then - reflector="${command[1]}" + reflector="${command[1]}" log_msg "DEBUG" "Read in new reflector: ${reflector}" dl_owd_baselines_us["${reflector}"]="${dl_owd_baselines_us[${reflector}]:-100000}" ul_owd_baselines_us["${reflector}"]="${ul_owd_baselines_us[${reflector}]:-100000}" @@ -928,7 +952,7 @@ parse_ping() SET_VAR) - if [[ "${command[1]:-}" && "${command[2]:-}" ]] + if [[ "${#command[@]}" -eq 3 ]] then export -n "${command[1]}=${command[2]}" fi @@ -937,7 +961,7 @@ parse_ping() SET_ARRAY_ELEMENT) - if [[ "${command[1]:-}" && "${command[2]:-}" && "${command[3]:-}" ]] + if [[ "${#command[@]}" -eq 4 ]] then declare -A "${command[1]}"+="([${command[2]}]=${command[3]})" fi @@ -1034,23 +1058,23 @@ start_pinger() start_pingers() { - # Initiate pingers - log_msg "DEBUG" "Starting pingers." + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + case ${pinger_binary} in tsping|fping) start_pinger 0 - ;; + ;; ping) for ((pinger=0; pinger < no_pingers; pinger++)) do start_pinger "${pinger}" done - ;; + ;; *) log_msg "ERROR" "Unknown pinger binary: ${pinger_binary}" kill $$ 2>/dev/null - ;; + ;; esac } @@ -1061,7 +1085,7 @@ sleep_until_next_pinger_time_slot() # whilst ensuring pings will remain spaced out appropriately to maintain granularity local pinger="${1}" - + t_start_us=${EPOCHREALTIME/./} time_to_next_time_slot_us=$(( (reflector_ping_interval_us-(t_start_us-pingers_t_start_us)%reflector_ping_interval_us) + pinger*ping_response_interval_us )) sleep_remaining_tick_time "${t_start_us}" "${time_to_next_time_slot_us}" @@ -1070,7 +1094,7 @@ sleep_until_next_pinger_time_slot() kill_pinger() { local pinger="${1}" - + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" case "${pinger_binary}" in @@ -1079,7 +1103,6 @@ kill_pinger() ;; *) - : ;; esac @@ -1088,6 +1111,8 @@ kill_pinger() kill_pingers() { + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + case "${pinger_binary}" in tsping|fping) @@ -1116,12 +1141,13 @@ replace_pinger_reflector() # ${reflectors[no_pingers]} is then unset # and the the bad reflector moved to the back of the queue (last element in ${reflectors[]}) # and finally the indices for ${reflectors} are updated to reflect the new order - + local pinger="${1}" - + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" - if ((no_reflectors > no_pingers)); then + if ((no_reflectors > no_pingers)) + then log_msg "DEBUG" "replacing reflector: ${reflectors[pinger]} with ${reflectors[no_pingers]}." kill_pinger "${pinger}" bad_reflector=${reflectors[pinger]} @@ -1133,19 +1159,19 @@ replace_pinger_reflector() reflectors+=("${bad_reflector}") # reset array indices mapfile -t reflectors < <(for i in "${reflectors[@]}"; do printf '%s\n' "${i}"; done) - # set up the new pinger with the new reflector and retain pid + # set up the new pinger with the new reflector and retain pid case ${pinger_binary} in tsping|fping) printf "SET_REFLECTORS %s\n" "${reflectors[*]:0:${no_pingers}}" >&"${pinger_fds[0]}" - ;; + ;; ping) printf "SET_REFLECTOR %s\n" "${reflectors[pinger]}" >&"${pinger_fds[pinger]}" - ;; + ;; *) log_msg "ERROR" "Unknown pinger binary: ${pinger_binary}" kill $$ 2>/dev/null - ;; + ;; esac start_pinger "${pinger}" else @@ -1183,7 +1209,7 @@ kill_maintain_pingers() log_msg "ERROR" "Unknown pinger binary: ${pinger_binary}" kill $$ 2>/dev/null ;; - esac + esac exit } @@ -1197,18 +1223,19 @@ change_state_maintain_pingers() case "${maintain_pingers_next_state}" in START|STOP|PAUSED|RUNNING) - - if [[ "${maintain_pingers_state}" != "${maintain_pingers_next_state}" ]] + + if [[ "${maintain_pingers_state}" == "${maintain_pingers_next_state}" ]] then - log_msg "DEBUG" "Changing maintain_pingers state from: ${maintain_pingers_state} to: ${maintain_pingers_next_state}" - maintain_pingers_state=${maintain_pingers_next_state} - else log_msg "ERROR" "Received request to change maintain_pingers state to existing state." + return fi + + log_msg "DEBUG" "Changing maintain_pingers state from: ${maintain_pingers_state} to: ${maintain_pingers_next_state}" + maintain_pingers_state=${maintain_pingers_next_state} ;; *) - + log_msg "ERROR" "Received unrecognized state change request: ${maintain_pingers_next_state}. Exiting now." kill $$ 2>/dev/null ;; @@ -1221,7 +1248,7 @@ maintain_pingers() trap '' INT trap 'kill_maintain_pingers' TERM EXIT - + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" declare -A dl_owd_baselines_us @@ -1234,9 +1261,9 @@ maintain_pingers() reflector_offences_idx=0 pingers_active=0 - pingers_t_start_us="${EPOCHREALTIME/./}" - t_last_reflector_replacement_us="${EPOCHREALTIME/./}" - t_last_reflector_comparison_us="${EPOCHREALTIME/./}" + pingers_t_start_us="${EPOCHREALTIME/./}" + t_last_reflector_replacement_us="${EPOCHREALTIME/./}" + t_last_reflector_comparison_us="${EPOCHREALTIME/./}" for ((reflector=0; reflector < no_reflectors; reflector++)) do @@ -1292,7 +1319,7 @@ maintain_pingers() case "${command[0]:-}" in CHANGE_STATE) - if [[ "${command[1]:-}" ]] + if [[ "${#command[@]}" -eq 2 ]] then change_state_maintain_pingers "${command[1]}" # break out of reading any new IPC commands to handle next state @@ -1308,13 +1335,13 @@ maintain_pingers() fi ;; SET_ARRAY_ELEMENT) - if [[ "${command[1]:-}" && "${command[2]:-}" && "${command[3]:-}" ]] + if [[ "${#command[@]}" -eq 4 ]] then declare -A "${command[1]}"+="([${command[2]}]=${command[3]})" fi ;; SET_VAR) - if [[ "${command[1]:-}" && "${command[2]:-}" ]] + if [[ "${#command[@]}" -eq 3 ]] then export -n "${command[1]}=${command[2]}" fi @@ -1327,8 +1354,8 @@ maintain_pingers() : ;; esac - done - + done + case "${maintain_pingers_state}" in START) @@ -1348,24 +1375,25 @@ maintain_pingers() fi change_state_maintain_pingers "PAUSED" ;; - + PAUSED) ;; - + RUNNING) if (( t_start_us>(t_last_reflector_replacement_us+reflector_replacement_interval_mins*60*1000000) )) then - pinger=$((RANDOM%no_pingers)) + pinger=$((RANDOM%no_pingers)) log_msg "DEBUG" "reflector: ${reflectors[pinger]} randomly selected for replacement." replace_pinger_reflector "${pinger}" - t_last_reflector_replacement_us=${EPOCHREALTIME/./} + t_last_reflector_replacement_us=${EPOCHREALTIME/./} continue fi - if (( t_start_us>(t_last_reflector_comparison_us+reflector_comparison_interval_mins*60*1000000) )); then + if (( t_start_us>(t_last_reflector_comparison_us+reflector_comparison_interval_mins*60*1000000) )) + then - t_last_reflector_comparison_us=${EPOCHREALTIME/./} + t_last_reflector_comparison_us=${EPOCHREALTIME/./} [[ "${dl_owd_baselines_us[${reflectors[0]}]:-}" && "${dl_owd_baselines_us[${reflectors[0]}]:-}" && "${ul_owd_baselines_us[${reflectors[0]}]:-}" && "${ul_owd_baselines_us[${reflectors[0]}]:-}" ]] || continue @@ -1431,16 +1459,19 @@ maintain_pingers() # shellcheck disable=SC2154 reflector_offences[reflector_offences_idx]=$(( (${EPOCHREALTIME/./}-last_timestamp_reflectors_us[${reflectors[pinger]}]) > reflector_response_deadline_us ? 1 : 0 )) - if (( reflector_offences[reflector_offences_idx] )); then + if (( reflector_offences[reflector_offences_idx] )) + then ((sum_reflector_offences[pinger]++)) log_msg "DEBUG" "no ping response from reflector: ${reflectors[pinger]} within reflector_response_deadline: ${reflector_response_deadline_s}s" log_msg "DEBUG" "reflector=${reflectors[pinger]}, sum_reflector_offences=${sum_reflector_offences[pinger]} and reflector_misbehaving_detection_thr=${reflector_misbehaving_detection_thr}" fi - if (( sum_reflector_offences[pinger] >= reflector_misbehaving_detection_thr )); then + if (( sum_reflector_offences[pinger] >= reflector_misbehaving_detection_thr )) + then log_msg "DEBUG" "Warning: reflector: ${reflectors[pinger]} seems to be misbehaving." - if ((replace_pinger_reflector_enabled)); then + if ((replace_pinger_reflector_enabled)) + then replace_pinger_reflector "${pinger}" replace_pinger_reflector_enabled=0 else @@ -1462,39 +1493,26 @@ maintain_pingers() done } -set_cake_rate() +set_shaper_rate() { - local interface="${1}" - local shaper_rate_kbps="${2}" - local adjust_shaper_rate="${3}" - - ((output_cake_changes)) && log_msg "SHAPER" "tc qdisc change root dev ${interface} cake bandwidth ${shaper_rate_kbps}Kbit" + # fire up tc and update max_wire_packet_compensation if there are rates to change for the given direction - if ((adjust_shaper_rate)); then + local direction="${1}" # 'dl' or 'ul' - tc qdisc change root dev "${interface}" cake bandwidth "${shaper_rate_kbps}Kbit" 2> /dev/null + if (( shaper_rate_kbps["${direction}"] != last_shaper_rate_kbps["${direction}"] )) + then + ((output_cake_changes)) && log_msg "SHAPER" "tc qdisc change root dev ${interface[${direction}]} cake bandwidth ${shaper_rate_kbps[${direction}]}Kbit" - else - ((output_cake_changes)) && log_msg "DEBUG" "adjust_shaper_rate set to 0 in config, so skipping the tc qdisc change call" - fi -} - -set_shaper_rates() -{ - if (( shaper_rate_kbps[dl] != last_shaper_rate_kbps[dl] || shaper_rate_kbps[ul] != last_shaper_rate_kbps[ul] )); then - - # fire up tc in each direction if there are rates to change, and if rates change in either direction then update max wire calcs - if (( shaper_rate_kbps[dl] != last_shaper_rate_kbps[dl] )); then - set_cake_rate "${dl_if}" "${shaper_rate_kbps[dl]}" adjust_dl_shaper_rate - printf "SET_ARRAY_ELEMENT shaper_rate_kbps dl %s\n" "${shaper_rate_kbps[dl]}" >&"${monitor_achieved_rates_fd}" - last_shaper_rate_kbps[dl]="${shaper_rate_kbps[dl]}" - fi - if (( shaper_rate_kbps[ul] != last_shaper_rate_kbps[ul] )); then - set_cake_rate "${ul_if}" "${shaper_rate_kbps[ul]}" adjust_ul_shaper_rate - printf "SET_ARRAY_ELEMENT shaper_rate_kbps ul %s\n" "${shaper_rate_kbps[ul]}" >&"${monitor_achieved_rates_fd}" - last_shaper_rate_kbps[ul]="${shaper_rate_kbps[ul]}" + if ((adjust_shaper_rate["${direction}"])) + then + tc qdisc change root dev "${interface[${direction}]}" cake bandwidth "${shaper_rate_kbps[${direction}]}Kbit" 2> /dev/null + else + ((output_cake_changes)) && log_msg "DEBUG" "adjust_${direction}_shaper_rate set to 0 in config, so skipping the corresponding tc qdisc change call." fi + printf "SET_ARRAY_ELEMENT shaper_rate_kbps ${direction} %s\n" "${shaper_rate_kbps[${direction}]}" >&"${monitor_achieved_rates_fd}" + last_shaper_rate_kbps["${direction}"]="${shaper_rate_kbps[${direction}]}" + update_max_wire_packet_compensation fi } @@ -1504,7 +1522,8 @@ set_min_shaper_rates() log_msg "DEBUG" "Enforcing minimum shaper rates." shaper_rate_kbps[dl]=${min_dl_shaper_rate_kbps} shaper_rate_kbps[ul]=${min_ul_shaper_rate_kbps} - set_shaper_rates + set_shaper_rate "dl" + set_shaper_rate "ul" } get_max_wire_packet_size_bits() @@ -1564,6 +1583,8 @@ change_state_main() { local main_next_state="${1}" + log_msg "DEBUG" "Starting: ${FUNCNAME[0]} with PID: ${BASHPID}" + case ${main_next_state} in RUNNING|IDLE|STALL) @@ -1624,7 +1645,8 @@ debug_cmd() err_type="ERROR" - if ((err_silence)); then + if ((err_silence)) + then err_type="DEBUG" fi @@ -1633,7 +1655,8 @@ debug_cmd() caller_id=$(caller) - if ((ret==0)); then + if ((ret==0)) + then log_msg "DEBUG" "debug_cmd: err_silence=${err_silence}; debug_msg=${debug_msg}; caller_id=${caller_id}; command=${cmd} ${args[*]}; result=SUCCESS" else [[ "${err_type}" == "DEBUG" && "${debug}" == "0" ]] && return # if debug disabled, then skip on DEBUG but not on ERROR @@ -1650,6 +1673,52 @@ debug_cmd() fi } +# shellcheck disable=SC1090,SC2311 +validate_config_entry() { + # Must be called before loading config_path into the global scope. + # + # When the entry is invalid, two types are returned with the first type + # being the invalid user type and second type is the default type with + # the user needing to adapt the config file so that the entry uses the + # default type. + # + # When the entry is valid, one type is returned and it will be the + # the type of either the default or user type. However because in that + # case they are both valid. It doesn't matter as they'd both have the + # same type. + + local config_path="${1}" + + local user_type + local valid_type + + user_type=$(unset "${2}" && . "${config_path}" && typeof "${2}") + valid_type=$(typeof "${2}") + + if [[ "${user_type}" != "${valid_type}" ]] + then + printf '%s' "${user_type} ${valid_type}" + return + elif [[ "${user_type}" != "string" ]] + then + printf '%s' "${valid_type}" + return + fi + + # extra validation for string, check for empty string + local -n default_value=${2} + local user_value + user_value=$(. "${config_path}" && local -n x="${2}" && printf '%s' "${x}") + + # if user is empty but default is not, invalid entry + if [[ -z "${user_value}" && -n "${default_value}" ]] + then + printf '%s' "${user_type} ${valid_type}" + else + printf '%s' "${valid_type}" + fi +} + # ======= Start of the Main Routine ======== [[ -t 1 ]] && terminal=1 || terminal=0 @@ -1663,35 +1732,78 @@ log_file_path=/var/log/cake-autorate.log run_path=/var/run/cake-autorate/ # cake-autorate first argument is config file path -if [[ -n ${1-} ]]; then +if [[ -n "${1-}" ]] +then config_path="${1}" else - config_path="${PREFIX}/cake-autorate_config.primary.sh" + config_path="${PREFIX}/config.primary.sh" fi -if [[ ! -f "${config_path}" ]]; then +if [[ ! -f "${config_path}" ]] +then log_msg "ERROR" "No config file found. Exiting now." - exit + exit 1 fi -# shellcheck source=cake-autorate_config.primary.sh +# validate config entries before loading +mapfile -t user_config < <(grep -E '^[^(#| )].*=' "${config_path}" | sed -e 's/[\t ]*\#.*//g' -e 's/=.*//g') +config_error_count=0 +for key in "${user_config[@]}" +do + # Despite the fact that config_file_check is no longer required, + # we make an exemption just in this case as that variable in + # particular does not have any real impact to the operation + # of the script. + [[ "${key}" == "config_file_check" ]] && continue + + # shellcheck disable=SC2076 + if [[ ! " ${valid_config_entries[*]} " =~ " ${key} " ]] + then + ((config_error_count++)) + log_msg "ERROR" "The key: '${key}' in config file: '${config_path}' is not a valid config entry." + else + # shellcheck disable=SC2311 + read -r user supposed <<< "$(validate_config_entry "${config_path}" "${key}")" + if [[ -n "${supposed}" ]] + then + error_msg="The value of '${key}' in config file: '${config_path}' is not a valid value of type: '${supposed}'." + + case "${user}" in + negative-*) error_msg="${error_msg} Also, negative numbers are not supported." ;; + *) ;; + esac + + log_msg "ERROR" "${error_msg}" + unset error_msg + + ((config_error_count++)) + fi + unset user supposed + fi +done +if ((config_error_count)) +then + log_msg "ERROR" "The config file: '${config_path}' contains ${config_error_count} error(s). Exiting now." + exit 1 +fi +unset valid_config_entries user_config config_error_count key + +# shellcheck source=config.primary.sh . "${config_path}" -if [[ ${config_file_check} != "cake-autorate" ]]; then - log_msg "ERROR" "Config file error. Please check config file entries." - exit -fi - -if [[ ${config_path} =~ cake-autorate_config\.(.*)\.sh ]]; then - instance_id=${BASH_REMATCH[1]} - run_path=/var/run/cake-autorate/${instance_id} +if [[ ${config_path} =~ config\.(.*)\.sh ]] +then + instance_id="${BASH_REMATCH[1]}" + run_path="/var/run/cake-autorate/${instance_id}" else - log_msg "ERROR" "Instance identifier 'X' set by cake-autorate_config.X.sh cannot be empty. Exiting now." - exit + log_msg "ERROR" "Instance identifier 'X' set by config.X.sh cannot be empty. Exiting now." + exit 1 fi -if [[ -n "${log_file_path_override-}" ]]; then - if [[ ! -d ${log_file_path_override} ]]; then +if [[ -n "${log_file_path_override-}" ]] +then + if [[ ! -d ${log_file_path_override} ]] + then broken_log_file_path_override=${log_file_path_override} log_file_path=/var/log/cake-autorate${instance_id:+.${instance_id}}.log log_msg "ERROR" "Log file path override: '${broken_log_file_path_override}' does not exist. Exiting now." @@ -1714,7 +1826,8 @@ log_msg "SYSLOG" "Starting cake-autorate with PID: ${BASHPID} and config: ${conf # ${run_path}/ is used to store temporary files # it should not exist on startup so if it does exit, else create the directory -if [[ -d "${run_path}" ]]; then +if [[ -d "${run_path}" ]] +then if [[ -f "${run_path}/proc_pids" ]] && running_main_pid=$(awk -F= '/^main=/ {print $2}' "${run_path}/proc_pids") && [[ -d "/proc/${running_main_pid}" ]] then log_msg "ERROR" "${run_path} already exists and an instance appears to be running with main process pid ${running_main_pid}. Exiting script." @@ -1731,7 +1844,7 @@ fi proc_pids['main']="${BASHPID}" -no_reflectors=${#reflectors[@]} +no_reflectors=${#reflectors[@]} # Check ping binary exists command -v "${pinger_binary}" &> /dev/null || { log_msg "ERROR" "ping binary ${pinger_binary} does not exist. Exiting script."; exit; } @@ -1745,9 +1858,10 @@ command -v "${pinger_binary}" &> /dev/null || { log_msg "ERROR" "ping binary ${p # Check bufferbloat detection threshold not greater than window length (( bufferbloat_detection_thr > bufferbloat_detection_window )) && { log_msg "ERROR" "bufferbloat_detection_thr cannot be greater than bufferbloat_detection_window. Exiting script."; exit; } -# Passed error checks +# Passed error checks -if ((log_to_file)); then +if ((log_to_file)) +then log_file_max_time_us=$((log_file_max_time_mins*60000000)) log_file_max_size_bytes=$((log_file_max_size_KB*1024)) exec {log_fd}<> <(:) @@ -1756,13 +1870,15 @@ if ((log_to_file)); then fi # test if stdout is a tty (terminal) -if ! ((terminal)); then +if ! ((terminal)) +then echo "stdout not a terminal so redirecting output to: ${log_file_path}" ((log_to_file)) && exec 1>&"${log_fd}" fi # Initialize rx_bytes_path and tx_bytes_path if not set -if [[ -z "${rx_bytes_path-}" ]]; then +if [[ -z "${rx_bytes_path-}" ]] +then case "${dl_if}" in veth*) rx_bytes_path="/sys/class/net/${dl_if}/statistics/tx_bytes" @@ -1775,7 +1891,8 @@ if [[ -z "${rx_bytes_path-}" ]]; then ;; esac fi -if [[ -z "${tx_bytes_path-}" ]]; then +if [[ -z "${tx_bytes_path-}" ]] +then case "${ul_if}" in veth*) tx_bytes_path="/sys/class/net/${ul_if}/statistics/rx_bytes" @@ -1789,7 +1906,8 @@ if [[ -z "${tx_bytes_path-}" ]]; then esac fi -if ((debug)) ; then +if ((debug)) +then log_msg "DEBUG" "CAKE-autorate version: ${cake_autorate_version}" log_msg "DEBUG" "config_path: ${config_path}" log_msg "DEBUG" "run_path: ${run_path}" @@ -1856,6 +1974,8 @@ declare -A last_shaper_rate_kbps declare -A base_shaper_rate_kbps declare -A min_shaper_rate_kbps declare -A max_shaper_rate_kbps +declare -A interface +declare -A adjust_shaper_rate base_shaper_rate_kbps[dl]="${base_dl_shaper_rate_kbps}" base_shaper_rate_kbps[ul]="${base_ul_shaper_rate_kbps}" @@ -1872,10 +1992,19 @@ shaper_rate_kbps[ul]="${base_ul_shaper_rate_kbps}" last_shaper_rate_kbps[dl]=0 last_shaper_rate_kbps[ul]=0 +interface[dl]="${dl_if}" +interface[ul]="${ul_if}" + +adjust_shaper_rate[dl]="${adjust_dl_shaper_rate}" +adjust_shaper_rate[ul]="${adjust_ul_shaper_rate}" + +dl_max_wire_packet_size_bits=0 +ul_max_wire_packet_size_bits=0 get_max_wire_packet_size_bits "${dl_if}" dl_max_wire_packet_size_bits get_max_wire_packet_size_bits "${ul_if}" ul_max_wire_packet_size_bits -set_shaper_rates +set_shaper_rate "dl" +set_shaper_rate "ul" update_max_wire_packet_compensation @@ -1899,13 +2028,16 @@ delays_idx=0 sum_dl_delays=0 sum_ul_delays=0 -if ((debug)); then - if (( bufferbloat_refractory_period_us < (bufferbloat_detection_window*ping_response_interval_us) )); then +if ((debug)) +then + if (( bufferbloat_refractory_period_us < (bufferbloat_detection_window*ping_response_interval_us) )) + then log_msg "DEBUG" "Warning: bufferbloat refractory period: ${bufferbloat_refractory_period_us} us." log_msg "DEBUG" "Warning: but expected time to overwrite samples in bufferbloat detection window is: $((bufferbloat_detection_window*ping_response_interval_us)) us." log_msg "DEBUG" "Warning: Consider increasing bufferbloat refractory period or decreasing bufferbloat detection window." fi - if (( reflector_response_deadline_us < 2*reflector_ping_interval_us )); then + if (( reflector_response_deadline_us < 2*reflector_ping_interval_us )) + then log_msg "DEBUG" "Warning: reflector_response_deadline_s < 2*reflector_ping_interval_s" log_msg "DEBUG" "Warning: consider setting an increased reflector_response_deadline." fi @@ -1915,7 +2047,8 @@ fi ((randomize_reflectors)) && randomize_array reflectors # Wait if ${startup_wait_s} > 0 -if ((startup_wait_us>0)); then +if ((startup_wait_us>0)) +then log_msg "DEBUG" "Waiting ${startup_wait_s} seconds before startup." sleep_us "${startup_wait_us}" fi @@ -1924,7 +2057,8 @@ case "${pinger_binary}" in tsping|fping) exec {pinger_fds[0]}<> <(:) - ;; + ;; + ping) for ((pinger=0; pinger<=no_pingers; pinger++)) do @@ -1932,9 +2066,9 @@ case "${pinger_binary}" in done ;; - *) - log_msg "ERROR" "Unknown pinger binary: ${pinger_binary}" - kill $$ 2>/dev/null + *) + log_msg "ERROR" "Unknown pinger binary: ${pinger_binary}" + exit ;; esac @@ -1964,19 +2098,19 @@ do ;; SET_VAR) - if [[ ${command[1]:-} && ${command[2]:-} ]] + if [[ "${#command[@]}" -eq 3 ]] then export -n "${command[1]}=${command[2]}" fi ;; SET_ARRAY_ELEMENT) - if [[ "${command[1]:-}" && "${command[2]:-}" && "${command[3]:-}" ]] + if [[ "${#command[@]}" -eq 4 ]] then declare -A "${command[1]}"+="([${command[2]}]=${command[3]})" fi ;; SET_PROC_PID) - if [[ "${command[1]:-}" && "${command[2]:-}" && "${command[3]:-}" ]] + if [[ "${#command[@]}" -eq 4 ]] then declare -A "${command[1]}"+="([${command[2]}]=${command[3]})" fi @@ -2002,7 +2136,8 @@ do reflectors_last_timestamp_us="${timestamp//[.]}" - if (( (t_start_us - 10#"${reflectors_last_timestamp_us}")>500000 )); then + if (( (t_start_us - 10#"${reflectors_last_timestamp_us}")>500000 )) + then log_msg "DEBUG" "processed response from [${reflector}] that is > 500ms old. Skipping." continue fi @@ -2028,19 +2163,23 @@ do classify_load "dl" classify_load "ul" - get_next_shaper_rate "dl" - get_next_shaper_rate "ul" + update_shaper_rate "dl" + update_shaper_rate "ul" - set_shaper_rates + set_shaper_rate "dl" + set_shaper_rate "ul" - if (( output_processing_stats )); then + if (( output_processing_stats )) + then printf -v processing_stats '%s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s; %s' "${EPOCHREALTIME}" "${achieved_rate_kbps[dl]}" "${achieved_rate_kbps[ul]}" "${load_percent[dl]}" "${load_percent[ul]}" "${timestamp}" "${reflector}" "${seq}" "${dl_owd_baseline_us}" "${dl_owd_us}" "${dl_owd_delta_ewma_us}" "${dl_owd_delta_us}" "${compensated_dl_delay_thr_us}" "${ul_owd_baseline_us}" "${ul_owd_us}" "${ul_owd_delta_ewma_us}" "${ul_owd_delta_us}" "${compensated_ul_delay_thr_us}" "${sum_dl_delays}" "${sum_ul_delays}" "${load_condition[dl]}" "${load_condition[ul]}" "${shaper_rate_kbps[dl]}" "${shaper_rate_kbps[ul]}" log_msg "DATA" "${processing_stats}" fi # If base rate is sustained, increment sustained base rate timer (and break out of processing loop if enough time passes) - if (( enable_sleep_function )); then - if [[ ${load_condition[dl]} == *idle* && ${load_condition[ul]} == *idle* ]]; then + if (( enable_sleep_function )) + then + if [[ ${load_condition[dl]} == *idle* && ${load_condition[ul]} == *idle* ]] + then ((t_sustained_connection_idle_us += (${EPOCHREALTIME/./}-t_end_us) )) if ((t_sustained_connection_idle_us > sustained_idle_sleep_thr_us)) then @@ -2124,7 +2263,7 @@ do *) log_msg "ERROR" "Unrecognized main state: ${main_state}. Exiting now." - kill $$ 2>/dev/null + exit 1 ;; esac diff --git a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_template.sh b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/config_template.sh similarity index 95% rename from luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_template.sh rename to luci-app-sqm-autorate/root/usr/share/sqm-autorate/config_template.sh index b430d82d0..04a366a63 100755 --- a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_template.sh +++ b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/config_template.sh @@ -9,7 +9,7 @@ INTERFACE=$(basename "$1" | cut -d. -f2) -cake_autorate_version="2.0.0" +#cake_autorate_version="2.0.0" # *** OUTPUT AND LOGGING OPTIONS *** @@ -46,7 +46,7 @@ ul_if=$(uci -q get sqm.${INTERFACE}.interface) # upload interface # fping - round robin pinging (rtts) # ping - (iputils-ping) individual pinging (rtts) # hping3 - individidual pinging (owds) -pinger_binary=tsping +pinger_binary=$(uci -q get sqm.${INTERFACE}.pinger || echo 'tsping') # list of reflectors to use and number of pingers to initiate # pingers will be initiated with reflectors in the order specified in the list @@ -77,12 +77,8 @@ reflector_ping_interval_s=$(uci -q get sqm.${INTERFACE}.reflector_ping_interval_ # delay threshold in ms is the extent of OWD increase to classify as a delay # these are automatically adjusted based on maximum on the wire packet size # (adjustment significant at sub 12Mbit/s rates, else negligible) -latency=$(uci -q get sqm.${INTERFACE}.delay_thr_ms) -[ -z "$latency" ] && latency="$(($(ping -B -w 5 -c 5 -I ${ul_if} 1.1.1.1 | cut -d '/' -s -f6 | cut -d '.' -f1 | tr -d '\n' 2>/dev/null)+30))" -[ -z "$latency" ] && latency="100" -logger -t "sqm" "latency $INTERFACE: $latency" -dl_delay_thr_ms="$latency" # (milliseconds) -ul_delay_thr_ms="$latency" # (milliseconds) +dl_delay_thr_ms=$(uci -q get sqm.${INTERFACE}.delay_thr_ms) || $(($(ping -B -w 5 -c 5 -I ${ul_if} 1.1.1.1 | cut -d '/' -s -f6 | cut -d '.' -f1 | tr -d '\n' 2>/dev/null)+30)) || echo 100 # (milliseconds) +ul_delay_thr_ms=${dl_delay_thr_ms} # Set either of the below to 0 to adjust one direction only # or alternatively set both to 0 to simply use cake-autorate to monitor a connection @@ -195,7 +191,7 @@ reflector_misbehaving_detection_thr=3 reflector_replacement_interval_mins=60 # how often to replace a random reflector from the present list reflector_comparison_interval_mins=1 # how often to compare reflectors -reflector_sum_owd_baseline_delta_thr_ms=30 # max increase from min sum owd baselines before reflector rotated +#reflector_sum_owd_baseline_delta_thr_ms=30 # max increase from min sum owd baselines before reflector rotated reflector_owd_delta_ewma_delta_thr_ms=10 # mac increase from min delta ewma before reflector rotated # stall is detected when the following two conditions are met: diff --git a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_defaults.sh b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/defaults.sh similarity index 99% rename from luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_defaults.sh rename to luci-app-sqm-autorate/root/usr/share/sqm-autorate/defaults.sh index 06dc9970b..1ef1af429 100755 --- a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_defaults.sh +++ b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/defaults.sh @@ -7,6 +7,8 @@ # Author: @Lynx (OpenWrt forum) # Inspiration taken from: @moeller0 (OpenWrt forum) +INTERFACE="" + # *** OUTPUT AND LOGGING OPTIONS *** output_processing_stats=1 # enable (1) or disable (0) output monitoring lines showing processing stats diff --git a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_launcher.sh b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/launcher.sh similarity index 77% rename from luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_launcher.sh rename to luci-app-sqm-autorate/root/usr/share/sqm-autorate/launcher.sh index f708f328a..7cb3567df 100755 --- a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_launcher.sh +++ b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/launcher.sh @@ -1,6 +1,6 @@ #!/bin/bash -cake_instances=(/usr/share/sqm-autorate/cake-autorate_config*sh) +cake_instances=(/root/cake-autorate/config.*.sh) cake_instance_pids=() trap kill_cake_instances INT TERM EXIT @@ -20,7 +20,7 @@ kill_cake_instances() for cake_instance in "${cake_instances[@]}" do - /usr/share/sqm-autorate/cake-autorate.sh "${cake_instance}" & + /root/cake-autorate/cake-autorate.sh "${cake_instance}" & cake_instance_pids+=(${!}) done wait diff --git a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_lib.sh b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/lib.sh similarity index 66% rename from luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_lib.sh rename to luci-app-sqm-autorate/root/usr/share/sqm-autorate/lib.sh index 7743b5467..19141fc74 100755 --- a/luci-app-sqm-autorate/root/usr/share/sqm-autorate/cake-autorate_lib.sh +++ b/luci-app-sqm-autorate/root/usr/share/sqm-autorate/lib.sh @@ -1,14 +1,63 @@ #!/bin/bash -# cake-autorate_lib.sh -- common functions for use by cake-autorate.sh + +# lib.sh -- common functions for use by cake-autorate.sh +# # This file is part of cake-autorate. __set_e=0 -if [[ ! ${-} =~ e ]]; then +if [[ ! ${-} =~ e ]] +then set -e __set_e=1 fi -exec {__sleep_fd}<> <(:) || true +if [[ -z "${__sleep_fd:-}" ]] +then + exec {__sleep_fd}<> <(:) +fi + +typeof() { + # typeof -- returns the type of a variable + + local type_sig + type_sig=$(declare -p "${1}" 2>/dev/null) + if [[ "${type_sig}" =~ "declare --" ]] + then + str_type "${1}" + elif [[ "${type_sig}" =~ "declare -a" ]] + then + printf "array" + elif [[ "${type_sig}" =~ "declare -A" ]] + then + printf "map" + else + printf "none" + fi +} + +str_type() { + # str_type -- returns the type of a string + + local -n str="${1}" + + if [[ "${str}" =~ ^[0-9]+$ ]] + then + printf "integer" + elif [[ "${str}" =~ ^[0-9]*\.[0-9]+$ ]] + then + printf "float" + elif [[ "${str}" =~ ^-[0-9]+$ ]] + then + printf "negative-integer" + elif [[ "${str}" =~ ^-[0-9]*\.[0-9]+$ ]] + then + printf "negative-float" + else + # technically not validated, user is just trusted to call + # this function with valid strings + printf "string" + fi +} sleep_s() { @@ -25,7 +74,7 @@ sleep_s() # - https://github.com/lynxthecat/cake-autorate/issues/174#issuecomment-1460074498 local sleep_duration_s=${1} # (seconds, e.g. 0.5, 1 or 1.5) - read -r -t "${sleep_duration_s}" -u "${__sleep_fd}" || : + read -r -t "${sleep_duration_s}" -u "${__sleep_fd}" || true } sleep_us() @@ -52,21 +101,10 @@ sleep_remaining_tick_time() fi } -get_remaining_tick_time() -{ - # updates sleep_duration_s remaining to end of tick duration - - local t_start_us=${1} # (microseconds) - local tick_duration_us=${2} # (microseconds) - - sleep_duration_us=$(( t_start_us + tick_duration_us - ${EPOCHREALTIME/./} )) - ((sleep_duration_us<0)) && sleep_duration_us=0 - sleep_duration_s=000000${sleep_duration_us} - sleep_duration_s=$((10#${sleep_duration_s::-6})).${sleep_duration_s: -6} -} - randomize_array() { + # randomize the order of the elements of an array + local -n array=${1} subset=("${array[@]}") @@ -80,23 +118,6 @@ randomize_array() done } -lock() -{ - local path=${1} - - while true; do - ( set -o noclobber; echo "$$" > "${path:?}" ) 2> /dev/null && return 0 - sleep_us 100000 - done -} - -unlock() -{ - local path=${1} - - rm -f "${path:?}" -} - terminate() { # Send regular kill to processes and monitor terminations; @@ -105,7 +126,7 @@ terminate() # and, finally, call wait on all processes to reap any zombie processes. local pids=("${@:-}") - + kill "${pids[@]}" 2> /dev/null for((i=0; i<10; i++)) @@ -121,8 +142,8 @@ terminate() kill -9 "${pids[@]}" 2> /dev/null } - -if (( __set_e == 1 )); then +if (( __set_e == 1 )) +then set +e fi unset __set_e From 63fe792617e0129834b2cc6b3b7fddb8309dfef5 Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Sun, 9 Jul 2023 01:56:34 +0800 Subject: [PATCH 19/20] fix zero --- luci-app-zerotier-master/.gitattributes | 2 + luci-app-zerotier-master/.gitignore | 2 + .../Makefile | 6 +- luci-app-zerotier-master/README.md | 4 + .../luasrc/controller/zerotier.lua | 24 +++ .../luasrc/model/cbi/zerotier/info.lua | 15 ++ .../luasrc/model/cbi/zerotier/manual.lua | 25 +++ .../luasrc/model/cbi/zerotier/settings.lua | 34 ++++ .../luasrc/view/zerotier/zerotier_status.htm | 22 +++ luci-app-zerotier-master/po/zh-cn/zerotier.po | 28 +++ .../root/etc/config/zero/local.conf | 5 + .../root/etc/init.d/zerotier | 163 ++++++++++++++++++ .../root/etc/uci-defaults/40_luci-zerotier | 7 - .../root/etc/zerotier/zerotier.log | 0 .../luasrc/controller/zerotier.lua | 24 --- .../luasrc/model/cbi/zerotier/info.lua | 15 -- .../luasrc/model/cbi/zerotier/manual.lua | 26 --- .../luasrc/model/cbi/zerotier/settings.lua | 37 ---- .../luasrc/view/zerotier/zerotier_status.htm | 29 ---- luci-app-zerotier/po/zh-cn/zerotier.po | 35 ---- luci-app-zerotier/po/zh_Hans | 1 - luci-app-zerotier/root/etc/init.d/zerotier | 113 ------------ luci-app-zerotier/root/etc/zerotier.start | 28 --- luci-app-zerotier/root/etc/zerotier.stop | 15 -- 24 files changed, 327 insertions(+), 333 deletions(-) create mode 100644 luci-app-zerotier-master/.gitattributes create mode 100644 luci-app-zerotier-master/.gitignore rename {luci-app-zerotier => luci-app-zerotier-master}/Makefile (88%) mode change 100755 => 100644 create mode 100644 luci-app-zerotier-master/README.md create mode 100644 luci-app-zerotier-master/luasrc/controller/zerotier.lua create mode 100644 luci-app-zerotier-master/luasrc/model/cbi/zerotier/info.lua create mode 100644 luci-app-zerotier-master/luasrc/model/cbi/zerotier/manual.lua create mode 100644 luci-app-zerotier-master/luasrc/model/cbi/zerotier/settings.lua create mode 100644 luci-app-zerotier-master/luasrc/view/zerotier/zerotier_status.htm create mode 100644 luci-app-zerotier-master/po/zh-cn/zerotier.po create mode 100644 luci-app-zerotier-master/root/etc/config/zero/local.conf create mode 100755 luci-app-zerotier-master/root/etc/init.d/zerotier rename {luci-app-zerotier => luci-app-zerotier-master}/root/etc/uci-defaults/40_luci-zerotier (50%) rename {luci-app-zerotier => luci-app-zerotier-master}/root/etc/zerotier/zerotier.log (100%) mode change 100755 => 100644 delete mode 100755 luci-app-zerotier/luasrc/controller/zerotier.lua delete mode 100755 luci-app-zerotier/luasrc/model/cbi/zerotier/info.lua delete mode 100755 luci-app-zerotier/luasrc/model/cbi/zerotier/manual.lua delete mode 100755 luci-app-zerotier/luasrc/model/cbi/zerotier/settings.lua delete mode 100755 luci-app-zerotier/luasrc/view/zerotier/zerotier_status.htm delete mode 100755 luci-app-zerotier/po/zh-cn/zerotier.po delete mode 100755 luci-app-zerotier/po/zh_Hans delete mode 100755 luci-app-zerotier/root/etc/init.d/zerotier delete mode 100755 luci-app-zerotier/root/etc/zerotier.start delete mode 100755 luci-app-zerotier/root/etc/zerotier.stop diff --git a/luci-app-zerotier-master/.gitattributes b/luci-app-zerotier-master/.gitattributes new file mode 100644 index 000000000..dfe077042 --- /dev/null +++ b/luci-app-zerotier-master/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +* text=auto diff --git a/luci-app-zerotier-master/.gitignore b/luci-app-zerotier-master/.gitignore new file mode 100644 index 000000000..5b9bd8749 --- /dev/null +++ b/luci-app-zerotier-master/.gitignore @@ -0,0 +1,2 @@ + +*.bak diff --git a/luci-app-zerotier/Makefile b/luci-app-zerotier-master/Makefile old mode 100755 new mode 100644 similarity index 88% rename from luci-app-zerotier/Makefile rename to luci-app-zerotier-master/Makefile index 5c070ef7c..d557df631 --- a/luci-app-zerotier/Makefile +++ b/luci-app-zerotier-master/Makefile @@ -9,11 +9,11 @@ include $(TOPDIR)/rules.mk LUCI_TITLE:=LuCI for Zerotier LUCI_DEPENDS:=+zerotier LUCI_PKGARCH:=all - -PKG_NAME:=luci-app-zerotier PKG_VERSION:=1.0 -PKG_RELEASE:=21 +PKG_RELEASE:=17 include $(TOPDIR)/feeds/luci/luci.mk # call BuildPackage - OpenWrt buildroot signature + + diff --git a/luci-app-zerotier-master/README.md b/luci-app-zerotier-master/README.md new file mode 100644 index 000000000..bd9822cdd --- /dev/null +++ b/luci-app-zerotier-master/README.md @@ -0,0 +1,4 @@ +# luci-app-zerotier + +你不在乎网络安全,可我在乎
+与lean原版相比使用了op自带的防火墙,并增添了流量权限控制 \ No newline at end of file diff --git a/luci-app-zerotier-master/luasrc/controller/zerotier.lua b/luci-app-zerotier-master/luasrc/controller/zerotier.lua new file mode 100644 index 000000000..04559fb42 --- /dev/null +++ b/luci-app-zerotier-master/luasrc/controller/zerotier.lua @@ -0,0 +1,24 @@ +module("luci.controller.zerotier",package.seeall) + +function index() + if not nixio.fs.access("/etc/config/zerotier")then +return +end + +entry({"admin","vpn"}, firstchild(), "VPN", 45).dependent = false + +entry({"admin", "vpn", "zerotier"},firstchild(), _("ZeroTier")).dependent = false + +entry({"admin", "vpn", "zerotier", "general"},cbi("zerotier/settings"), _("Base Setting"), 1) +entry({"admin", "vpn", "zerotier", "log"},form("zerotier/info"), _("Interface Info"), 2) +entry({"admin", "vpn", "zerotier", "manual"},cbi("zerotier/manual"), _("Manual Config"), 3) + +entry({"admin","vpn","zerotier","status"},call("act_status")) +end + +function act_status() +local e={} + e.running=luci.sys.call("pgrep /usr/bin/zerotier-one >/dev/null")==0 + luci.http.prepare_content("application/json") + luci.http.write_json(e) +end diff --git a/luci-app-zerotier-master/luasrc/model/cbi/zerotier/info.lua b/luci-app-zerotier-master/luasrc/model/cbi/zerotier/info.lua new file mode 100644 index 000000000..9bc3824cf --- /dev/null +++ b/luci-app-zerotier-master/luasrc/model/cbi/zerotier/info.lua @@ -0,0 +1,15 @@ +local fs = require "nixio.fs" +local conffile = "/tmp/zero.info" + +f = SimpleForm("logview") + +t = f:field(TextValue, "conf") +t.rmempty = true +t.rows = 15 +function t.cfgvalue() + luci.sys.exec("ifconfig $(ifconfig | grep zt | awk '{print $1}') > /tmp/zero.info") + return fs.readfile(conffile) or "" +end +t.readonly="readonly" + +return f \ No newline at end of file diff --git a/luci-app-zerotier-master/luasrc/model/cbi/zerotier/manual.lua b/luci-app-zerotier-master/luasrc/model/cbi/zerotier/manual.lua new file mode 100644 index 000000000..13a72d7c0 --- /dev/null +++ b/luci-app-zerotier-master/luasrc/model/cbi/zerotier/manual.lua @@ -0,0 +1,25 @@ +local m, s, o +local fs = require "nixio.fs" +local jsonc = require "luci.jsonc" or nil +m = Map("zerotier") +s=m:section(NamedSection,"sample_config","zerotier") +s.anonymous=true +s.addremove=false +o = s:option(TextValue, "manualconfig") +o.rows = 20 +o.wrap = "soft" +o.rmempty = true +o.cfgvalue = function(self, section) + return fs.readfile("/etc/config/zero/local.conf") +end +o.write = function(self, section, value) + fs.writefile("/etc/config/zero/local.conf", value:gsub("\r\n", "\n")) +end +o.validate=function(self, value) + if jsonc == nil or jsonc.parse(value)~=nil then + return value + end + return nil +end +o.description='https://www.zerotier.com/manual/
https://github.com/zerotier/ZeroTierOne/blob/db813db7e875c257e42c41ab8091c3df1e9300a5/service/README.md' +return m \ No newline at end of file diff --git a/luci-app-zerotier-master/luasrc/model/cbi/zerotier/settings.lua b/luci-app-zerotier-master/luasrc/model/cbi/zerotier/settings.lua new file mode 100644 index 000000000..7131f6728 --- /dev/null +++ b/luci-app-zerotier-master/luasrc/model/cbi/zerotier/settings.lua @@ -0,0 +1,34 @@ + +a=Map("zerotier",translate("ZeroTier"),translate("Zerotier is an open source, cross-platform and easy to use virtual LAN")) +a:section(SimpleSection).template = "zerotier/zerotier_status" + +t=a:section(NamedSection,"sample_config","zerotier") +t.anonymous=true +t.addremove=false + +e=t:option(Flag,"enabled",translate("Enable")) +e.default=0 +e.rmempty=false + +e=t:option(DynamicList,"join",translate('ZeroTier Network ID')) +e.password=true +e.rmempty=false + +e=t:option(Flag,"nat",translate("Auto NAT Clients")) +e.default=0 +e.rmempty=false + +e = t:option(MultiValue, "access", translate("Zerotier access control")) +e.default="lanfwzt ztfwwan ztfwlan" +e.rmempty=false +e:value("lanfwzt",translate("lan access zerotier")) +e:value("wanfwzt",translate("wan access zerotier")) +e:value("ztfwwan",translate("remote access wan")) +e:value("ztfwlan",translate("remote access lan")) +e.widget = "checkbox" + +e=t:option(DummyValue,"opennewwindow" , + translate("")) +e.description = translate("Create or manage your zerotier network, and auth clients who could access") + +return a diff --git a/luci-app-zerotier-master/luasrc/view/zerotier/zerotier_status.htm b/luci-app-zerotier-master/luasrc/view/zerotier/zerotier_status.htm new file mode 100644 index 000000000..9d216c5d9 --- /dev/null +++ b/luci-app-zerotier-master/luasrc/view/zerotier/zerotier_status.htm @@ -0,0 +1,22 @@ + + +
+

+ <%:Collecting data...%> +

+
diff --git a/luci-app-zerotier-master/po/zh-cn/zerotier.po b/luci-app-zerotier-master/po/zh-cn/zerotier.po new file mode 100644 index 000000000..2fb491ed4 --- /dev/null +++ b/luci-app-zerotier-master/po/zh-cn/zerotier.po @@ -0,0 +1,28 @@ +msgid "" +msgstr "" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Gtranslator 2.91.7\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Zerotier is an open source, cross-platform and easy to use virtual LAN" +msgstr "Zerotier是一个开源,跨平台,而且适合内网穿透互联的傻瓜配置虚拟 VPN LAN" + +msgid "Auto NAT Clients" +msgstr "自动允许客户端NAT" + +msgid "Allow zerotier clients access your LAN network" +msgstr "允许Zerotier的拨入客户端访问路由器LAN资源(需要在 Zerotier管理页面设定到LAN网段的路由表)" + +msgid "Create or manage your zerotier network, and auth clients who could access" +msgstr "点击跳转到Zerotier官网管理平台,新建或者管理网络,并允许客户端接入访问你私人网路(新接入的节点默认不允许访问)" + +msgid "Interface Info" +msgstr "接口信息" + +msgid "Zerotier access control" +msgstr "Zerotier 准入控制" + +msgid "Manual Config" +msgstr "手动设置" diff --git a/luci-app-zerotier-master/root/etc/config/zero/local.conf b/luci-app-zerotier-master/root/etc/config/zero/local.conf new file mode 100644 index 000000000..2214f7cc1 --- /dev/null +++ b/luci-app-zerotier-master/root/etc/config/zero/local.conf @@ -0,0 +1,5 @@ +{ +"settings": { + "multipathMode": 2 + } + } \ No newline at end of file diff --git a/luci-app-zerotier-master/root/etc/init.d/zerotier b/luci-app-zerotier-master/root/etc/init.d/zerotier new file mode 100755 index 000000000..60cebbdc0 --- /dev/null +++ b/luci-app-zerotier-master/root/etc/init.d/zerotier @@ -0,0 +1,163 @@ +#!/bin/sh /etc/rc.common + +START=90 + +USE_PROCD=1 + +PROG=/usr/bin/zerotier-one +CONFIG_PATH=/var/lib/zerotier-one + +section_enabled() { + config_get_bool enabled "$1" 'enabled' 0 + [ $enabled -gt 0 ] +} +service_triggers() { + procd_add_reload_trigger zerotier +} +start_instance() { + local cfg="$1" + local port secret config_path + local ARGS="" + + if ! section_enabled "$cfg"; then + echo "disabled in config" + return 1 + fi + + [ -d /etc/config/zero ] || mkdir -p /etc/config/zero + config_path=/etc/config/zero + + config_get_bool port $cfg 'port' + config_get secret $cfg 'secret' + + # Remove existing link or folder + rm -rf $CONFIG_PATH + + # Create link from CONFIG_PATH to config_path + if [ -n "$config_path" -a "$config_path" != $CONFIG_PATH ]; then + if [ ! -d "$config_path" ]; then + echo "ZeroTier config_path does not exist: $config_path" + return + fi + + ln -s $config_path $CONFIG_PATH + fi + + mkdir -p $CONFIG_PATH/networks.d + + if [ -n "$port" ]; then + ARGS="$ARGS -p$port" + fi + + if [ "$secret" = "generate" ]; then + echo "Generate secret - please wait..." + local sf="/tmp/zt.$cfg.secret" + + zerotier-idtool generate "$sf" > /dev/null + [ $? -ne 0 ] && return 1 + + secret="$(cat $sf)" + rm "$sf" + + uci set zerotier.$cfg.secret="$secret" + uci commit zerotier + fi + + if [ -n "$secret" ]; then + echo "$secret" > $CONFIG_PATH/identity.secret + # make sure there is not previous identity.public + rm -f $CONFIG_PATH/identity.public + fi + + add_join() { + # an (empty) config file will cause ZT to join a network + touch $CONFIG_PATH/networks.d/$1.conf + } + + config_list_foreach $cfg 'join' add_join + + procd_open_instance + procd_set_param command $PROG $ARGS $CONFIG_PATH + procd_set_param stderr 1 + procd_close_instance + ( + [ -f "/var/run/zerotier.wait.pid" ] && return + touch /var/run/zerotier.wait.pid + while [ "$(ifconfig | grep zt | awk '{print $1}')" = "" ] + do + sleep 1 + done + zt0=$(ifconfig | grep zt | awk '{print $1}') + echo "zt interface $zt0 is started!" + if [ -z "$(uci get network.zerotier)" ]; then + uci set network.zerotier=interface + uci set network.zerotier.proto='static' + fi + config_get nat $cfg 'nat' + if [ "$nat" == "1" ]; then + if [ -z "$(uci get firewall.ztzone)" ]; then + uci set firewall.ztzone=zone + uci set firewall.ztzone.input='ACCEPT' + uci set firewall.ztzone.output='ACCEPT' + uci set firewall.ztzone.forward='REJECT' + uci set firewall.ztzone.masq='1' + uci set firewall.ztzone.name='zerotier' + uci set firewall.ztzone.network='zerotier' + fi + else + uci delete firewall.ztzone + fi + config_get access $cfg 'access' + if [ "${access//ztfwlan/}" != "$access" ]; then + uci set firewall.ztfwlan=forwarding + uci set firewall.ztfwlan.dest='lan' + uci set firewall.ztfwlan.src='zerotier' + else + uci delete firewall.ztfwlan + fi + if [ "${access//ztfwwan/}" != "$access" ]; then + uci set firewall.ztfwwan=forwarding + uci set firewall.ztfwwan.dest='wan' + uci set firewall.ztfwwan.src='zerotier' + else + uci delete firewall.ztfwwan + fi + if [ "${access//lanfwzt/}" != "$access" ]; then + uci set firewall.lanfwzt=forwarding + uci set firewall.lanfwzt.dest='zerotier' + uci set firewall.lanfwzt.src='lan' + else + uci delete firewall.lanfwzt + fi + if [ "${access//wanfwzt/}" != "$access" ]; then + uci set firewall.wanfwzt=forwarding + uci set firewall.wanfwzt.dest='zerotier' + uci set firewall.wanfwzt.src='wan' + else + uci delete firewall.wanfwzt + fi + uci set network.zerotier.ifname="$zt0" + [ -n "$(uci changes network)" ] && uci commit network && /etc/init.d/network reload + [ -n "$(uci changes firewall)" ] && uci commit firewall && /etc/init.d/firewall reload + rm /var/run/zerotier.wait.pid + ) & +} + +start_service() { + config_load 'zerotier' + config_foreach start_instance 'zerotier' +} + +stop_instance() { + rm -f /tmp/zero.log + local cfg="$1" + + # Remove existing link or folder + rm -rf $CONFIG_PATH +} + +stop_service() { + config_load 'zerotier' + config_foreach stop_instance 'zerotier' +} + diff --git a/luci-app-zerotier/root/etc/uci-defaults/40_luci-zerotier b/luci-app-zerotier-master/root/etc/uci-defaults/40_luci-zerotier similarity index 50% rename from luci-app-zerotier/root/etc/uci-defaults/40_luci-zerotier rename to luci-app-zerotier-master/root/etc/uci-defaults/40_luci-zerotier index 616824562..06f02e802 100755 --- a/luci-app-zerotier/root/etc/uci-defaults/40_luci-zerotier +++ b/luci-app-zerotier-master/root/etc/uci-defaults/40_luci-zerotier @@ -5,13 +5,6 @@ uci -q batch <<-EOF >/dev/null add ucitrack zerotier set ucitrack.@zerotier[-1].init=zerotier commit ucitrack - - delete firewall.zerotier - set firewall.zerotier=include - set firewall.zerotier.type=script - set firewall.zerotier.path=/etc/zerotier.start - set firewall.zerotier.reload=1 - commit firewall EOF rm -f /tmp/luci-indexcache diff --git a/luci-app-zerotier/root/etc/zerotier/zerotier.log b/luci-app-zerotier-master/root/etc/zerotier/zerotier.log old mode 100755 new mode 100644 similarity index 100% rename from luci-app-zerotier/root/etc/zerotier/zerotier.log rename to luci-app-zerotier-master/root/etc/zerotier/zerotier.log diff --git a/luci-app-zerotier/luasrc/controller/zerotier.lua b/luci-app-zerotier/luasrc/controller/zerotier.lua deleted file mode 100755 index f2973c65e..000000000 --- a/luci-app-zerotier/luasrc/controller/zerotier.lua +++ /dev/null @@ -1,24 +0,0 @@ -module("luci.controller.zerotier", package.seeall) - -function index() - if not nixio.fs.access("/etc/config/zerotier") then - return - end - - entry({"admin", "vpn"}, firstchild(), "VPN", 45).dependent = false - - entry({"admin", "vpn", "zerotier"}, alias("admin", "vpn", "zerotier", "general"), _("ZeroTier"), 99) - - entry({"admin", "vpn", "zerotier", "general"}, cbi("zerotier/settings"), _("Base Setting"), 1) - entry({"admin", "vpn", "zerotier", "log"}, form("zerotier/info"), _("Interface Info"), 2) - entry({"admin", "vpn", "zerotier", "manual"}, cbi("zerotier/manual"), _("Manual Config"), 3) - - entry({"admin", "vpn", "zerotier", "status"}, call("act_status")) -end - -function act_status() - local e = {} - e.running = luci.sys.call("pgrep /usr/bin/zerotier-one >/dev/null") == 0 - luci.http.prepare_content("application/json") - luci.http.write_json(e) -end diff --git a/luci-app-zerotier/luasrc/model/cbi/zerotier/info.lua b/luci-app-zerotier/luasrc/model/cbi/zerotier/info.lua deleted file mode 100755 index bb8fc3769..000000000 --- a/luci-app-zerotier/luasrc/model/cbi/zerotier/info.lua +++ /dev/null @@ -1,15 +0,0 @@ -local fs = require "nixio.fs" -local conffile = "/tmp/zero.info" - -f = SimpleForm("logview") - -t = f:field(TextValue, "conf") -t.rmempty = true -t.rows = 19 -function t.cfgvalue() - luci.sys.exec("for i in $(ifconfig | grep 'zt' | awk '{print $1}'); do ifconfig $i; done > /tmp/zero.info") - return fs.readfile(conffile) or "" -end -t.readonly = "readonly" - -return f diff --git a/luci-app-zerotier/luasrc/model/cbi/zerotier/manual.lua b/luci-app-zerotier/luasrc/model/cbi/zerotier/manual.lua deleted file mode 100755 index 71ae2bb37..000000000 --- a/luci-app-zerotier/luasrc/model/cbi/zerotier/manual.lua +++ /dev/null @@ -1,26 +0,0 @@ -local m, s, o -local fs = require "nixio.fs" -local jsonc = require "luci.jsonc" or nil -m = Map("zerotier") -s = m:section(NamedSection, "sample_config", "zerotier") -s.anonymous = true -s.addremove = false -o = s:option(TextValue, "manualconfig") -o.rows = 20 -o.wrap = "soft" -o.rmempty = true -o.cfgvalue = function(self, section) - return fs.readfile("/etc/config/zero/local.conf") -end -o.write = function(self, section, value) - fs.writefile("/etc/config/zero/local.conf", value:gsub("\r\n", "\n")) -end -o.validate = function(self, value) - if jsonc == nil or jsonc.parse(value) ~= nil then - return value - end - return nil -end -o.description = - 'https://www.zerotier.com/manual/
https://github.com/zerotier/ZeroTierOne/blob/dev/service/README.md' -return m diff --git a/luci-app-zerotier/luasrc/model/cbi/zerotier/settings.lua b/luci-app-zerotier/luasrc/model/cbi/zerotier/settings.lua deleted file mode 100755 index fc70a8581..000000000 --- a/luci-app-zerotier/luasrc/model/cbi/zerotier/settings.lua +++ /dev/null @@ -1,37 +0,0 @@ -a = Map("zerotier") -a.title = translate("ZeroTier") -a.description = translate("Zerotier is an open source, cross-platform and easy to use virtual LAN") - -a:section(SimpleSection).template = "zerotier/zerotier_status" - -t = a:section(NamedSection, "sample_config", "zerotier") -t.anonymous = true -t.addremove = false - -e = t:option(Flag, "enabled", translate("Enable")) -e.default = 0 -e.rmempty = false - -e = t:option(DynamicList, "join", translate('ZeroTier Network ID')) -e.password = true -e.rmempty = false - -e = t:option(Flag, "nat", translate("Auto NAT Clients")) -e.description = translate("Allow zerotier clients access your LAN network") -e.default = 0 -e.rmempty = false - -e = t:option(MultiValue, "access", translate("Zerotier Access Control")) -e.default = "lanfwzt ztfwwan ztfwlan" -e.rmempty = false -e:value("lanfwzt", translate("LAN Access Zerotier")) -e:value("wanfwzt", translate("WAN Access Zerotier")) -e:value("ztfwwan", translate("Remote Access WAN")) -e:value("ztfwlan", translate("Remote Access LAN")) -e.widget = "checkbox" - -e = t:option(DummyValue, "opennewwindow", translate( - "")) -e.description = translate("Create or manage your zerotier network, and auth clients who could access") - -return a diff --git a/luci-app-zerotier/luasrc/view/zerotier/zerotier_status.htm b/luci-app-zerotier/luasrc/view/zerotier/zerotier_status.htm deleted file mode 100755 index b2faf8e44..000000000 --- a/luci-app-zerotier/luasrc/view/zerotier/zerotier_status.htm +++ /dev/null @@ -1,29 +0,0 @@ - - -
-

- - <%:Collecting data...%> - -

-
\ No newline at end of file diff --git a/luci-app-zerotier/po/zh-cn/zerotier.po b/luci-app-zerotier/po/zh-cn/zerotier.po deleted file mode 100755 index 07adfeabc..000000000 --- a/luci-app-zerotier/po/zh-cn/zerotier.po +++ /dev/null @@ -1,35 +0,0 @@ -msgid "Zerotier is an open source, cross-platform and easy to use virtual LAN" -msgstr "Zerotier 是一个开源,跨平台,而且适合内网穿透互联的傻瓜配置虚拟 VPN LAN" - -msgid "Auto NAT Clients" -msgstr "自动允许客户端 NAT" - -msgid "Allow zerotier clients access your LAN network" -msgstr "允许 Zerotier 的拨入客户端访问路由器 LAN 资源(需要在 Zerotier 管理页面设定到 LAN 网段的路由表)" - -msgid "Create or manage your zerotier network, and auth clients who could access" -msgstr "点击跳转到 Zerotier 官网管理平台,新建或者管理网络,并允许客户端接入访问你私人网路(新接入的节点默认不允许访问)" - -msgid "Base Setting" -msgstr "基本设置" - -msgid "Interface Info" -msgstr "接口信息" - -msgid "Zerotier Access Control" -msgstr "Zerotier 准入控制" - -msgid "LAN Access Zerotier" -msgstr "LAN 可接入 Zerotier" - -msgid "WAN Access Zerotier" -msgstr "WAN 可接入 Zerotier" - -msgid "Remote Access WAN" -msgstr "外部访问可接入 WAN" - -msgid "Remote Access LAN" -msgstr "外部访问可接入 LAN" - -msgid "Manual Config" -msgstr "手动设置" diff --git a/luci-app-zerotier/po/zh_Hans b/luci-app-zerotier/po/zh_Hans deleted file mode 100755 index 41451e4a1..000000000 --- a/luci-app-zerotier/po/zh_Hans +++ /dev/null @@ -1 +0,0 @@ -zh-cn \ No newline at end of file diff --git a/luci-app-zerotier/root/etc/init.d/zerotier b/luci-app-zerotier/root/etc/init.d/zerotier deleted file mode 100755 index 666d67533..000000000 --- a/luci-app-zerotier/root/etc/init.d/zerotier +++ /dev/null @@ -1,113 +0,0 @@ -#!/bin/sh /etc/rc.common - -START=99 - -USE_PROCD=1 - -PROG=/usr/bin/zerotier-one -CONFIG_PATH=/var/lib/zerotier-one - -service_triggers() { - procd_add_reload_trigger "zerotier" - procd_add_interface_trigger "interface.*.up" wan /etc/init.d/zerotier restart -} - -section_enabled() { - config_get_bool enabled "$1" 'enabled' 0 - [ $enabled -gt 0 ] -} - -start_instance() { - local cfg="$1" - local port secret config_path - local ARGS="" - - if ! section_enabled "$cfg"; then - echo "disabled in config" - return 1 - fi - - [ -d /etc/config/zero ] || mkdir -p /etc/config/zero - config_path=/etc/config/zero - - config_get_bool port $cfg 'port' - config_get secret $cfg 'secret' - - # Remove existing link or folder - rm -rf $CONFIG_PATH - - # Create link from CONFIG_PATH to config_path - if [ -n "$config_path" -a "$config_path" != $CONFIG_PATH ]; then - if [ ! -d "$config_path" ]; then - echo "ZeroTier config_path does not exist: $config_path" - return - fi - - ln -s $config_path $CONFIG_PATH - fi - - mkdir -p $CONFIG_PATH/networks.d - - if [ -n "$port" ]; then - ARGS="$ARGS -p$port" - fi - - if [ "$secret" = "generate" ]; then - echo "Generate secret - please wait..." - local sf="/tmp/zt.$cfg.secret" - - zerotier-idtool generate "$sf" > /dev/null - [ $? -ne 0 ] && return 1 - - secret="$(cat $sf)" - rm "$sf" - - uci set zerotier.$cfg.secret="$secret" - uci commit zerotier - fi - - if [ -n "$secret" ]; then - echo "$secret" > $CONFIG_PATH/identity.secret - # make sure there is not previous identity.public - rm -f $CONFIG_PATH/identity.public - fi - - add_join() { - # an (empty) config file will cause ZT to join a network - touch $CONFIG_PATH/networks.d/$1.conf - } - - config_list_foreach $cfg 'join' add_join - - procd_open_instance - procd_set_param command $PROG $ARGS $CONFIG_PATH - procd_set_param stderr 1 - procd_close_instance -} - -start_service() { - config_load 'zerotier' - config_foreach start_instance 'zerotier' - touch /tmp/zero.log && /etc/zerotier.start > /tmp/zero.log 2>&1 & -} - -stop_instance() { - rm -f /tmp/zero.log - local cfg="$1" - - /etc/zerotier.stop > /tmp/zero.log 2>&1 & - - # Remove existing link or folder - rm -f $CONFIG_PATH/networks.d/*.conf - rm -rf $CONFIG_PATH -} - -stop_service() { - config_load 'zerotier' - config_foreach stop_instance 'zerotier' -} - -reload_service() { - stop - start -} diff --git a/luci-app-zerotier/root/etc/zerotier.start b/luci-app-zerotier/root/etc/zerotier.start deleted file mode 100755 index b43e5f974..000000000 --- a/luci-app-zerotier/root/etc/zerotier.start +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/sh - -zero_enable="$(uci get zerotier.sample_config.enabled)" - -[ "${zero_enable}" -ne "1" ] && exit 0 - -[ -f "/tmp/zero.log" ] && { - while [ "$(ifconfig | grep 'zt' | awk '{print $1}')" = "" ] - do - sleep 1 - done -} - -nat_enable="$(uci get zerotier.sample_config.nat)" -zt0="$(ifconfig | grep 'zt' | awk '{print $1}')" -echo "${zt0}" > "/tmp/zt.nif" - -[ "${nat_enable}" -eq "1" ] && { - for i in ${zt0} - do - ip_segment="" - iptables -I FORWARD -i "$i" -j ACCEPT - iptables -I FORWARD -o "$i" -j ACCEPT - iptables -t nat -I POSTROUTING -o "$i" -j MASQUERADE - ip_segment="$(ip route | grep "dev $i proto kernel" | awk '{print $1}')" - iptables -t nat -I POSTROUTING -s "${ip_segment}" -j MASQUERADE - done -} diff --git a/luci-app-zerotier/root/etc/zerotier.stop b/luci-app-zerotier/root/etc/zerotier.stop deleted file mode 100755 index cbe7ec4b6..000000000 --- a/luci-app-zerotier/root/etc/zerotier.stop +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh - -zt0="$(ifconfig | grep 'zt' | awk '{print $1}')" -[ -z "${zt0}" ] && zt0="$(cat "/tmp/zt.nif")" - -for i in ${zt0} -do - ip_segment="" - iptables -D FORWARD -i "$i" -j ACCEPT 2>/dev/null - iptables -D FORWARD -o "$i" -j ACCEPT 2>/dev/null - iptables -t nat -D POSTROUTING -o "$i" -j MASQUERADE 2>/dev/null - ip_segment="$(ip route | grep "dev $i proto" | awk '{print $1}')" - iptables -t nat -D POSTROUTING -s "${ip_segment}" -j MASQUERADE 2>/dev/null - echo "zt interface $i is stopped!" -done From 39435ef52b835f6a479c783475f9173d97abe2a4 Mon Sep 17 00:00:00 2001 From: suyuan <175338101@qq.com> Date: Wed, 12 Jul 2023 01:23:54 +0800 Subject: [PATCH 20/20] add ouad --- luci-app-ouad/LICENSE | 622 ++++ luci-app-ouad/Makefile | 20 + luci-app-ouad/README.md | 80 + luci-app-ouad/luasrc/controller/oled.lua | 17 + .../luasrc/model/cbi/oled/setting.lua | 84 + luci-app-ouad/luasrc/view/oled/status.htm | 22 + luci-app-ouad/po/zh_Hans/oled.po | 154 + luci-app-ouad/po/zh_Hant/oled.po | 135 + luci-app-ouad/root/etc/config/oled | 27 + luci-app-ouad/root/etc/init.d/oled | 138 + luci-app-ouad/root/etc/uci-defaults/oled | 25 + luci-app-ouad/root/usr/sbin/netspeed | 20 + .../usr/share/rpcd/acl.d/luci-app-oled.json | 11 + luci-app-ouad/src/Example_Code/Main.c | 238 ++ luci-app-ouad/src/Example_Code/example_app.c | 650 ++++ luci-app-ouad/src/Example_Code/example_app.h | 30 + luci-app-ouad/src/I2C_Library/I2C.c | 281 ++ luci-app-ouad/src/I2C_Library/I2C.h | 69 + luci-app-ouad/src/LICENSE | 21 + luci-app-ouad/src/Makefile | 19 + luci-app-ouad/src/README.md | 21 + .../src/SSD1306_OLED_Library/SSD1306_OLED.c | 2761 +++++++++++++++++ .../src/SSD1306_OLED_Library/SSD1306_OLED.h | 204 ++ .../src/SSD1306_OLED_Library/gfxfont.h | 18 + 24 files changed, 5667 insertions(+) create mode 100644 luci-app-ouad/LICENSE create mode 100644 luci-app-ouad/Makefile create mode 100644 luci-app-ouad/README.md create mode 100644 luci-app-ouad/luasrc/controller/oled.lua create mode 100644 luci-app-ouad/luasrc/model/cbi/oled/setting.lua create mode 100644 luci-app-ouad/luasrc/view/oled/status.htm create mode 100644 luci-app-ouad/po/zh_Hans/oled.po create mode 100644 luci-app-ouad/po/zh_Hant/oled.po create mode 100644 luci-app-ouad/root/etc/config/oled create mode 100755 luci-app-ouad/root/etc/init.d/oled create mode 100644 luci-app-ouad/root/etc/uci-defaults/oled create mode 100755 luci-app-ouad/root/usr/sbin/netspeed create mode 100644 luci-app-ouad/root/usr/share/rpcd/acl.d/luci-app-oled.json create mode 100644 luci-app-ouad/src/Example_Code/Main.c create mode 100644 luci-app-ouad/src/Example_Code/example_app.c create mode 100644 luci-app-ouad/src/Example_Code/example_app.h create mode 100644 luci-app-ouad/src/I2C_Library/I2C.c create mode 100644 luci-app-ouad/src/I2C_Library/I2C.h create mode 100644 luci-app-ouad/src/LICENSE create mode 100644 luci-app-ouad/src/Makefile create mode 100644 luci-app-ouad/src/README.md create mode 100644 luci-app-ouad/src/SSD1306_OLED_Library/SSD1306_OLED.c create mode 100644 luci-app-ouad/src/SSD1306_OLED_Library/SSD1306_OLED.h create mode 100644 luci-app-ouad/src/SSD1306_OLED_Library/gfxfont.h diff --git a/luci-app-ouad/LICENSE b/luci-app-ouad/LICENSE new file mode 100644 index 000000000..e963df829 --- /dev/null +++ b/luci-app-ouad/LICENSE @@ -0,0 +1,622 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + diff --git a/luci-app-ouad/Makefile b/luci-app-ouad/Makefile new file mode 100644 index 000000000..7f855b068 --- /dev/null +++ b/luci-app-ouad/Makefile @@ -0,0 +1,20 @@ +# +# Copyright (C) 2020 Nate Ding +# +# This is free software, licensed under the GUN General Public License v3. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +LUCI_Title:=LuCI support for ssd1306 0.91\' 138x32 display +LUCI_DEPENDS:=+i2c-tools +coreutils-nohup +libuci +LUCI_PKGARCH:=all + +PKG_LICENSE:=GPLv3 +PKG_LINCESE_FILES:=LICENSE +PKF_MAINTAINER:=natelol + +include $(TOPDIR)/feeds/luci/luci.mk + +# call BuildPackage - OpenWrt buildroot signature diff --git a/luci-app-ouad/README.md b/luci-app-ouad/README.md new file mode 100644 index 000000000..8f78c1d2b --- /dev/null +++ b/luci-app-ouad/README.md @@ -0,0 +1,80 @@ +# luci-app-oled + +This is the LuCI app written for openwrt (**tested ~~only~~ on NanoPi R2S**) which supports ssd 1306 0.91' oled display. + +**Raspberry Pi CM4** + +This has been tested on Raspberry Pi CM4 as described in issue [#10](https://github.com/NateLol/luci-app-oled/issues/10#issuecomment-922245476). +You can find what revisions you need to make to have it work on your device. +Enjoy! + +## Features|功能 +--- +### Dispaly Info|显示信息 + +**0. Enable|开启** + +开启oled显示。 + +**1. Autoswitch|定时开关** + +由于夜间oled的显示屏太亮,并且也几乎不会看它,所以应邀提供定时开关的功能,选中autoswitch之后,可以设置**显示**的起始和结束时间。 + +**2. Time|时间** + +显示时间。 + +**3. IP|IP地址** + +显示LAN口的IP地址,记得LAN口不可以去除**桥接**选项,否则失效。由于使用的是`br-lan`,因为不同固件可能会交换`eth0`和`eth1`。 + +**4. CPU Temp|CPU温度** + +显示CPU温度。 + +**5. CPU Freq|CPU频率** + +显示实时CPU频率 + +**6. Network Speed|网速** + +提供不同接口的选择,`eth0`和`eth1`,个人可以按需修改。网速单位基准为字节(Byte)而不是一般的位(bit),[MB/s, KB/s, B/s]这样显示的数字能够比较小,不至于过长。 + +**7. Display Interval|显示间隔** + +为了延缓oled的光衰,提供屏保服务,每隔设定的时间运行一次屏保程序。 + +--- +### Screensavers|屏保 + +屏保提供不同的选择,默认推荐的是`Scroll Text|文字滚动`,其他的选择自行探索。 + +## Q&A + +Q0. 如何使用该程序?|在那里找到luci界面? + +A0. 该程序安装位置在luci界面的`services|服务`下的`OLED`,点击即可找到。 + +--- + +Q1. 是否会支持其他oled屏幕,例如同系列的0.96'的? + +A1. 由于开发者身边并没有相应的屏幕去调试,所以是暂时不考虑吧。如果你想贡献代码,非常欢迎,请开PR。 + +--- + + +Q2. 为什么我的IP地址显示错误? + +A2. 很大原因是你修改了LAN接口的属性,例如去除了该接口的**桥接**属性。 + +--- + + +Q3. 为什么我的oled不显示? + +A3. 很有可能是您的固件内核驱动不完整,该程序的运行需要在内核驱动中加上**kmod-i2c-xxx**,见issue [#10](https://github.com/NateLol/luci-app-oled/issues/10)。 + +--- + +如果你在使用过程中还遇到问题,请开issue。 diff --git a/luci-app-ouad/luasrc/controller/oled.lua b/luci-app-ouad/luasrc/controller/oled.lua new file mode 100644 index 000000000..554ceadd8 --- /dev/null +++ b/luci-app-ouad/luasrc/controller/oled.lua @@ -0,0 +1,17 @@ +module("luci.controller.oled", package.seeall) + +function index() + if not nixio.fs.access("/etc/config/oled") then + return + end + entry({"admin", "services", "oled"}, alias("admin", "services", "oled", "setting"),_("OLED"), 90).dependent = true + entry({"admin", "services", "oled", "status"}, call("act_status")) + entry({"admin", "services", "oled", "setting"}, cbi("oled/setting"),_("Setting"),30).leaf = true +end + +function act_status() + local e={} + e.running = luci.sys.call("pgrep -f /usr/bin/oled > /dev/null")==0 + luci.http.prepare_content("application/json") + luci.http.write_json(e) +end diff --git a/luci-app-ouad/luasrc/model/cbi/oled/setting.lua b/luci-app-ouad/luasrc/model/cbi/oled/setting.lua new file mode 100644 index 000000000..7204bc017 --- /dev/null +++ b/luci-app-ouad/luasrc/model/cbi/oled/setting.lua @@ -0,0 +1,84 @@ +m = Map("oled", translate("OLED"), translate("A LuCI app that helps you config your oled display (SSD1306, 0.91', 128X32) with screensavers!

Any issues, please go to: ")..[[luci-app-oled]]) + +--m.chain("luci") + +m:section(SimpleSection).template="oled/status" + +s = m:section(TypedSection, "oled", translate("")) +s.anonymous=true +s.addremove=false + +--OPTIONS +s:tab("info", translate("Info Display")) +s:tab("screensaver", translate("screensaver")) + +o = s:taboption("info", Flag, "enable", translate("Enable")) +o.default=0 +o = s:taboption("info", Value, "path", translate("I2C PATH")) +o.default='/dev/i2c-0' +o = s:taboption("info", Flag, "rotate", translate("180 degree rotation")) +o.default=0 +o = s:taboption("info", Flag, "autoswitch", translate("Enable Auto switch")) +o.default=0 +from = s:taboption("info", ListValue, "from", translate("From")) +to = s:taboption("info", ListValue, "to", translate("To")) +for i=0,23 do + for j=0,30,30 do + from:value(i*60+j,string.format("%02d:%02d",i,j)) + to:value(i*60+j,string.format("%02d:%02d",i,j)) + end +end +from:value(1440,"24:00") +to:value(1440,"24:00") +from:depends("autoswitch",'1') +to:depends("autoswitch",'1') +from.default=0 +to.default=1440 + +--informtion options---- +o = s:taboption("info", Flag, "date", translate("Date"), translate('Format YYYY-MM-DD HH:MM:SS')) +o.default=0 +o = s:taboption("info", Flag, "lanip", translate("IP"), translate("LAN IP address")) +o.default=0 +o = s:taboption("info", Flag, "cputemp", translate("CPU temperature")) +o.default=0 +o = s:taboption("info", Flag, "cpufreq", translate("CPU frequency")) +o.default=0 +o = s:taboption("info", Flag, "netspeed", translate("Network speed"), translate("1Mbps(m/s)=1,000Kbps(k/s)=1,000,000bps(b/s)")) +o.default=0 +o = s:taboption("info", Value, "netsource", translate("which eth to monitor")) +o:depends("netspeed",'1') +o.default='eth0' +o = s:taboption("info", Value, "time", translate("Display interval(s)"), translate('Screensaver will activate in set seconds')) +o.default=0 + +--screensaver options-- +o = s:taboption("screensaver", Flag, "scroll", translate("Scroll Text")) +o.default=1 +o = s:taboption("screensaver", Value, "text", translate("Text you want to scroll")) +o:depends("scroll",'1') +o.default='OPENWRT' +o = s:taboption("screensaver", Flag, "drawline", translate("Draw Many Lines")) +o.default=0 +o = s:taboption("screensaver", Flag, "drawrect", translate("Draw Rectangles")) +o.default=0 +o = s:taboption("screensaver", Flag, "fillrect", translate("Draw Multiple Rectangles")) +o.default=0 +o = s:taboption("screensaver", Flag, "drawcircle", translate("Draw Multiple Circles")) +o.default=0 +o = s:taboption("screensaver", Flag, "drawroundrect", translate("Draw a white circle, 10 pixel radius")) +o.default=0 +o = s:taboption("screensaver", Flag, "fillroundrect", translate("Fill the Round Rectangles")) +o.default=0 +o = s:taboption("screensaver", Flag, "drawtriangle", translate("Draw Triangles")) +o.default=0 +o = s:taboption("screensaver", Flag, "filltriangle", translate("Fill Triangles")) +o.default=0 +o = s:taboption("screensaver", Flag, "displaybitmap", translate("Display miniature bitmap")) +o.default=0 +o = s:taboption("screensaver", Flag, "displayinvertnormal", translate("Invert Display Normalize it")) +o.default=0 +o = s:taboption("screensaver", Flag, "drawbitmapeg", translate("Draw a bitmap and animate")) +o.default=0 + +return m diff --git a/luci-app-ouad/luasrc/view/oled/status.htm b/luci-app-ouad/luasrc/view/oled/status.htm new file mode 100644 index 000000000..0da0c6426 --- /dev/null +++ b/luci-app-ouad/luasrc/view/oled/status.htm @@ -0,0 +1,22 @@ + + +
+

+ <%:Collecting data...%> +

+
diff --git a/luci-app-ouad/po/zh_Hans/oled.po b/luci-app-ouad/po/zh_Hans/oled.po new file mode 100644 index 000000000..ae01eab33 --- /dev/null +++ b/luci-app-ouad/po/zh_Hans/oled.po @@ -0,0 +1,154 @@ +msgid "" +msgstr "Content-Type: text/plain; charset=UTF-8" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:1 +msgid "" +"A LuCI app that helps you config your oled display (SSD1306, 0.91', 128X32) " +"with screensavers!

Any issues, please go to:" +msgstr "" +"这是一款支持在ssd1306,0.91寸,128x32像素的oled显示屏上显示你要的信息,包含屏" +"保的程序。

任何问题请到:" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:24 +msgid "CPU frequency" +msgstr "CPU 频率" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:22 +msgid "CPU temperature" +msgstr "CPU 温度" + +msgid "Scroll Text" +msgstr "文字滚动" + +msgid "Enable Auto switch" +msgstr "启用定时开关" + +msgid "From" +msgstr "起始时间" + +msgid "To" +msgstr "结束时间" + +msgid "Text you want to scroll" +msgstr "你想要显示的文字" + +msgid "which eth to monitor" +msgstr "选择监控哪个网口" + +#: ../../package/new/luci-app-oled/luasrc/view/oled/status.htm:20 +msgid "Collecting data..." +msgstr "" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:18 +msgid "Date" +msgstr "时间" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:48 +msgid "Display miniature bitmap" +msgstr "小图案" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:28 +msgid "Display interval(s)" +msgstr "信息显示间隔(秒)" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:28 +msgid "Screensaver will activate in set seconds" +msgstr "屏保每间隔设置的时间运行一次" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:32 +msgid "Draw Many Lines" +msgstr "直线" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:38 +msgid "Draw Multiple Circles" +msgstr "多圆" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:36 +msgid "Draw Multiple Rectangles" +msgstr "多方块" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:34 +msgid "Draw Rectangles" +msgstr "方块" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:44 +msgid "Draw Triangles" +msgstr "三角形" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:54 +msgid "Draw a bitmap and animate" +msgstr "动图" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:52 +msgid "Draw a bitmap and animate movement" +msgstr "变化图" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:40 +msgid "Draw a white circle, 10 pixel radius" +msgstr "实心圆" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:15 +msgid "Enable" +msgstr "启用" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:46 +msgid "Fill Triangles" +msgstr "三角填充" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:42 +msgid "Fill the Round Rectangles" +msgstr "方形填充" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:18 +msgid "Format YYYY-MM-DD HH:MM:SS" +msgstr "日期格式 YYYY-MM-DD HH:MM:SS" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:17 +msgid "I2C PATH" +msgstr "I2C 路径" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:20 +msgid "IP" +msgstr "" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:12 +msgid "Info Display" +msgstr "显示信息" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:50 +msgid "Invert Display Normalize it" +msgstr "反转" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:20 +msgid "LAN IP address" +msgstr "LAN 地址" + +#: ../../package/new/luci-app-oled/luasrc/view/oled/status.htm:10 +msgid "NOT RUNNING" +msgstr "" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:26 +msgid "Network speed" +msgstr "网速" + +#: ../../package/new/luci-app-oled/luasrc/controller/oled.lua:7 +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:1 +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:7 +msgid "OLED" +msgstr "" + +#: ../../package/new/luci-app-oled/luasrc/view/oled/status.htm:7 +msgid "RUNNING" +msgstr "" + +#: ../../package/new/luci-app-oled/luasrc/controller/oled.lua:9 +msgid "Setting" +msgstr "设置" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:13 +msgid "screensaver" +msgstr "屏保" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:19 +msgid "180 degree rotation" +msgstr "180 度旋转" diff --git a/luci-app-ouad/po/zh_Hant/oled.po b/luci-app-ouad/po/zh_Hant/oled.po new file mode 100644 index 000000000..4a24e35fb --- /dev/null +++ b/luci-app-ouad/po/zh_Hant/oled.po @@ -0,0 +1,135 @@ +msgid "" +msgstr "Content-Type: text/plain; charset=UTF-8" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:1 +msgid "" +"A LuCI app that helps you config your oled display (SSD1306, 0.91', 128X32) " +"with screensavers!

Any issues, please go to:" +msgstr "這是壹款支持在ssd1306,0.91寸,128x32像素的oled顯示屏上顯示妳要的信息,包含屏保的程序。

任何問題請到:" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:24 +msgid "CPU frequency" +msgstr "CPU頻率" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:22 +msgid "CPU temperature" +msgstr "CPU溫度" + +msgid "Scroll Text" +msgstr "文字滾動" + +msgid "Text you want to scroll" +msgstr "妳想要顯示的文字" + +msgid "which eth to monitor" +msgstr "選擇監控哪個網口" + +#: ../../package/new/luci-app-oled/luasrc/view/oled/status.htm:20 +msgid "Collecting data..." +msgstr "" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:18 +msgid "Date" +msgstr "時間" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:48 +msgid "Display miniature bitmap" +msgstr "小圖案" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:28 +msgid "Display interval(s)" +msgstr "信息顯示間隔(秒)" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:28 +msgid "Screensaver will activate in set seconds" +msgstr "屏保每間隔設置的時間運行壹次" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:32 +msgid "Draw Many Lines" +msgstr "直線" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:38 +msgid "Draw Multiple Circles" +msgstr "多圓" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:36 +msgid "Draw Multiple Rectangles" +msgstr "多方塊" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:34 +msgid "Draw Rectangles" +msgstr "方塊" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:44 +msgid "Draw Triangles" +msgstr "三角形" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:54 +msgid "Draw a bitmap and animate" +msgstr "動圖" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:52 +msgid "Draw a bitmap and animate movement" +msgstr "變化圖" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:40 +msgid "Draw a white circle, 10 pixel radius" +msgstr "實心圓" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:15 +msgid "Enable" +msgstr "啟用" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:46 +msgid "Fill Triangles" +msgstr "三角填充" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:42 +msgid "Fill the Round Rectangles" +msgstr "方形填充" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:18 +msgid "Format YYYY-MM-DD HH:MM:SS" +msgstr "日期格式 YYYY-MM-DD HH:MM:SS" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:20 +msgid "IP" +msgstr "" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:12 +msgid "Info Display" +msgstr "顯示信息" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:50 +msgid "Invert Display Normalize it" +msgstr "反轉" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:20 +msgid "LAN IP address" +msgstr "LAN地址" + +#: ../../package/new/luci-app-oled/luasrc/view/oled/status.htm:10 +msgid "NOT RUNNING" +msgstr "" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:26 +msgid "Network speed" +msgstr "網速" + +#: ../../package/new/luci-app-oled/luasrc/controller/oled.lua:7 +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:1 +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:7 +msgid "OLED" +msgstr "" + +#: ../../package/new/luci-app-oled/luasrc/view/oled/status.htm:7 +msgid "RUNNING" +msgstr "" + +#: ../../package/new/luci-app-oled/luasrc/controller/oled.lua:9 +msgid "Setting" +msgstr "設置" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:13 +msgid "screensaver" +msgstr "屏保" diff --git a/luci-app-ouad/root/etc/config/oled b/luci-app-ouad/root/etc/config/oled new file mode 100644 index 000000000..e89ab41aa --- /dev/null +++ b/luci-app-ouad/root/etc/config/oled @@ -0,0 +1,27 @@ +config oled + option enable '0' + option drawline '0' + option drawrect '0' + option fillrect '0' + option drawcircle '0' + option drawroundrect '0' + option fillroundrect '0' + option drawtriangle '0' + option filltriangle '0' + option displaybitmap '0' + option displayinvertnormal '0' + option drawbitmapeg '0' + option date '1' + option netspeed '0' + option lanip '1' + option cpufreq '1' + option cputemp '1' + option time '60' + option from '0' + option to '1440' + option autoswitch '0' + option rotate '0' + option scroll '0' + option text 'OPENWRT' + option netsource 'eth0' + option path '/dev/i2c-0' diff --git a/luci-app-ouad/root/etc/init.d/oled b/luci-app-ouad/root/etc/init.d/oled new file mode 100755 index 000000000..6f61278f8 --- /dev/null +++ b/luci-app-ouad/root/etc/init.d/oled @@ -0,0 +1,138 @@ +#!/bin/sh /etc/rc.common +START=88 + +PROG=/usr/bin/oled + +stop() { + kill -2 $(pgrep /usr/bin/oled) + kill -9 $(pgrep -f /usr/sbin/netspeed) + echo "oled exit..." +} + +start() { + enabled=$(uci get oled.@oled[0].enable) + if [ $enabled -eq 0 ]; then + exit 0 + fi + + autoswitch=$(uci get oled.@oled[0].autoswitch) + from=$(uci get oled.@oled[0].from) + to=$(uci get oled.@oled[0].to) + + if [ ${autoswitch} -eq 1 ]; then + hour=$(date +"%H") + min=$(date +"%M") + ihour=`expr $hour + 0` + imin=`expr $min + 0` + now=$(($ihour*60+$imin)) + if [[ $now -lt $from || $now -gt $to ]]; then + stop + exit 0 + fi + fi + + #crontab daemon + if ! grep "/etc/init.d/oled \+restart" /etc/crontabs/root >/dev/null 2>&1; then + echo "*/5 * * * * /etc/init.d/oled restart >/dev/null 2>&1" >> /etc/crontabs/root + fi + + date=$(uci get oled.@oled[0].date) + lanip=$(uci get oled.@oled[0].lanip) + cputemp=$(uci get oled.@oled[0].cputemp) + cpufreq=$(uci get oled.@oled[0].cpufreq) + netspeed=$(uci get oled.@oled[0].netspeed) + time=$(uci get oled.@oled[0].time) + drawline=$(uci get oled.@oled[0].drawline) + drawrect=$(uci get oled.@oled[0].drawrect) + fillrect=$(uci get oled.@oled[0].fillrect) + drawcircle=$(uci get oled.@oled[0].drawcircle) + drawroundrect=$(uci get oled.@oled[0].drawroundrect) + fillroundrect=$(uci get oled.@oled[0].fillroundrect) + drawtriangle=$(uci get oled.@oled[0].drawtriangle) + filltriangle=$(uci get oled.@oled[0].filltriangle) + displaybitmap=$(uci get oled.@oled[0].displaybitmap) + displayinvertnormal=$(uci get oled.@oled[0].displayinvertnormal) + drawbitmapeg=$(uci get oled.@oled[0].drawbitmapeg) + rotate=$(uci get oled.@oled[0].rotate) + scroll=$(uci get oled.@oled[0].scroll) + text=$(uci get oled.@oled[0].text) + netsource=$(uci get oled.@oled[0].netsource) + path=$(uci get oled.@oled[0].path) + + if [ ${netspeed} -eq 1 ]; then + nohup /usr/sbin/netspeed ${netsource} >/dev/null 2>&1 & + else + kill -9 $(pgrep -f /usr/sbin/netspeed) + rm -f /tmp/netspeed + fi + nohup ${PROG} ${date} ${lanip} ${cputemp} ${cpufreq} ${netspeed} ${time} ${drawline} ${drawrect} ${fillrect} ${drawcircle} ${drawroundrect} ${fillroundrect} ${drawtriangle} ${filltriangle} ${displaybitmap} ${displayinvertnormal} ${drawbitmapeg} ${scroll} "${text}" "${netsource}" "${path}" ${rotate} 1 > /dev/null 2>&1 & +} + +restart() { + enabled=$(uci get oled.@oled[0].enable) + pgrep -f ${PROG} >/dev/null + if [ $? -eq 0 ]; then + if [ $enabled -eq 1 ]; then + autoswitch=$(uci get oled.@oled[0].autoswitch) + from=$(uci get oled.@oled[0].from) + to=$(uci get oled.@oled[0].to) + if [ ${autoswitch} -eq 1 ]; then + hour=$(date +"%H") + min=$(date +"%M") + ihour=`expr $hour + 0` + imin=`expr $min + 0` + now=$(($ihour*60+$imin)) + if [[ $now -lt $from || $now -gt $to ]]; then + stop + exit 0 + fi + fi + + date=$(uci get oled.@oled[0].date) + lanip=$(uci get oled.@oled[0].lanip) + cputemp=$(uci get oled.@oled[0].cputemp) + cpufreq=$(uci get oled.@oled[0].cpufreq) + netspeed=$(uci get oled.@oled[0].netspeed) + time=$(uci get oled.@oled[0].time) + drawline=$(uci get oled.@oled[0].drawline) + drawrect=$(uci get oled.@oled[0].drawrect) + fillrect=$(uci get oled.@oled[0].fillrect) + drawcircle=$(uci get oled.@oled[0].drawcircle) + drawroundrect=$(uci get oled.@oled[0].drawroundrect) + fillroundrect=$(uci get oled.@oled[0].fillroundrect) + drawtriangle=$(uci get oled.@oled[0].drawtriangle) + filltriangle=$(uci get oled.@oled[0].filltriangle) + displaybitmap=$(uci get oled.@oled[0].displaybitmap) + displayinvertnormal=$(uci get oled.@oled[0].displayinvertnormal) + drawbitmapeg=$(uci get oled.@oled[0].drawbitmapeg) + rotate=$(uci get oled.@oled[0].rotate) + scroll=$(uci get oled.@oled[0].scroll) + text=$(uci get oled.@oled[0].text) + netsource=$(uci get oled.@oled[0].netsource) + path=$(uci get oled.@oled[0].path) + + kill -9 $(pgrep /usr/bin/oled) + kill -9 $(pgrep -f /usr/sbin/netspeed) + + if [ ${netspeed} -eq 1 ]; then + nohup /usr/sbin/netspeed ${netsource} >/dev/null 2>&1 & + else + kill -9 $(pgrep -f /usr/sbin/netspeed) + rm -f /tmp/netspeed + fi + nohup ${PROG} ${date} ${lanip} ${cputemp} ${cpufreq} ${netspeed} ${time} ${drawline} ${drawrect} ${fillrect} ${drawcircle} ${drawroundrect} ${fillroundrect} ${drawtriangle} ${filltriangle} ${displaybitmap} ${displayinvertnormal} ${drawbitmapeg} ${scroll} "${text}" "${netsource}" "${path}" ${rotate} 0 > /dev/null 2>&1 & + else + stop + fi + else + if [ $enabled -eq 1 ]; then + start + else + exit 0 + fi + fi +} + +boot() { + start +} diff --git a/luci-app-ouad/root/etc/uci-defaults/oled b/luci-app-ouad/root/etc/uci-defaults/oled new file mode 100644 index 000000000..2e6ae5c01 --- /dev/null +++ b/luci-app-ouad/root/etc/uci-defaults/oled @@ -0,0 +1,25 @@ +#!/bin/sh + +uci_write_config() { + uci -q set oled.@oled[0].path="$1" + uci -q set oled.@oled[0].rotate="$2" + uci -q commit oled +} + +. /lib/functions/system.sh + +case "$(board_name)" in +hinlink,opc-h69k) + uci_write_config '/dev/i2c-5' 1 + ;; +esac + +uci -q batch <<-EOF >/dev/null + delete ucitrack.@oled[-1] + add ucitrack oled + set ucitrack.@oled[-1].init=oled + commit ucitrack +EOF + +rm -rf /tmp/luci-* +exit 0 diff --git a/luci-app-ouad/root/usr/sbin/netspeed b/luci-app-ouad/root/usr/sbin/netspeed new file mode 100755 index 000000000..6be8ca48d --- /dev/null +++ b/luci-app-ouad/root/usr/sbin/netspeed @@ -0,0 +1,20 @@ +#!/bin/ash +IF=$1 +if [ -z "$IF" ]; then + IF=`ls -1 /sys/class/net/ | head -1` +fi +RXPREV=-1 +TXPREV=-1 +echo "Listening $IF..." +while [ 1 == 1 ] ; do + RX=`cat /sys/class/net/${IF}/statistics/rx_bytes` + TX=`cat /sys/class/net/${IF}/statistics/tx_bytes` + if [ $RXPREV -ne -1 ] ; then + let BWRX=$RX-$RXPREV + let BWTX=$TX-$TXPREV + echo "$BWRX $BWTX">/tmp/netspeed + fi + RXPREV=$RX + TXPREV=$TX + sleep 1 +done diff --git a/luci-app-ouad/root/usr/share/rpcd/acl.d/luci-app-oled.json b/luci-app-ouad/root/usr/share/rpcd/acl.d/luci-app-oled.json new file mode 100644 index 000000000..7c436b871 --- /dev/null +++ b/luci-app-ouad/root/usr/share/rpcd/acl.d/luci-app-oled.json @@ -0,0 +1,11 @@ +{ + "luci-app-oled": { + "description": "Grant UCI access for luci-app-oled", + "read": { + "uci": [ "oled" ] + }, + "write": { + "uci": [ "oled" ] + } + } +} diff --git a/luci-app-ouad/src/Example_Code/Main.c b/luci-app-ouad/src/Example_Code/Main.c new file mode 100644 index 000000000..2ec3e610e --- /dev/null +++ b/luci-app-ouad/src/Example_Code/Main.c @@ -0,0 +1,238 @@ +/* + * Main.c + * + * Created on : Sep 6, 2017 + * Author : Vinay Divakar + * Description : Example usage of the SSD1306 Driver API's + * Website : www.deeplyembedded.org + */ + +/* Lib Includes */ +#include +#include +#include +#include +#include + +/* Header Files */ +#include "I2C.h" +#include "SSD1306_OLED.h" +#include "example_app.h" + +/* Oh Compiler-Please leave me as is */ +volatile unsigned char flag = 0; + +/* Alarm Signal Handler */ +void ALARMhandler(int sig) +{ + /* Set flag */ + flag = 5; +} + +void BreakDeal(int sig) +{ + clearDisplay(); + usleep(1000000); + Display(); + exit(0); +} + +int main(int argc, char* argv[]) +{ + int date=atoi(argv[1]); + int lanip=atoi(argv[2]); + int cputemp=atoi(argv[3]); + int cpufreq=atoi(argv[4]); + int netspeed=atoi(argv[5]); + int time=atoi(argv[6]); + int drawline=atoi(argv[7]); + int drawrect=atoi(argv[8]); + int fillrect=atoi(argv[9]); + int drawcircle=atoi(argv[10]); + int drawroundcircle=atoi(argv[11]); + int fillroundcircle=atoi(argv[12]); + int drawtriangle=atoi(argv[13]); + int filltriangle=atoi(argv[14]); + int displaybitmap=atoi(argv[15]); + int displayinvertnormal=atoi(argv[16]); + int drawbitmapeg=atoi(argv[17]); + int scroll=atoi(argv[18]); + char *text=argv[19]; + char *eth=argv[20]; + char *path=argv[21]; + int rotate=atoi(argv[22]); + int needinit=atoi(argv[23]); + + if(path == NULL) + path = I2C_DEV0_PATH; + + /* Initialize I2C bus and connect to the I2C Device */ + if(init_i2c_dev(path, SSD1306_OLED_ADDR) == 0) + { + printf("I2C: Bus Connected to SSD1306\r\n"); + } + else + { + printf("I2C: OOPS! Something Went Wrong\r\n"); + exit(1); + } + + /* Register the Alarm Handler */ + signal(SIGALRM, ALARMhandler); + signal(SIGINT, BreakDeal); + //signal(SIGTERM, BreakDeal); + + /* Run SDD1306 Initialization Sequence */ + if (needinit==1) + display_Init_seq(); + + if (rotate==1) + display_rotate(); + else + display_normal(); + + /* Clear display */ + clearDisplay(); + + // draw a single pixel +// drawPixel(0, 1, WHITE); +// Display(); +// usleep(1000000); +// clearDisplay(); + + // draw many lines + while(1){ + if(scroll){ + testscrolltext(text); + usleep(1000000); + clearDisplay(); + } + + if(drawline){ + testdrawline(); + usleep(1000000); + clearDisplay(); + } + + // draw rectangles + if(drawrect){ + testdrawrect(); + usleep(1000000); + clearDisplay(); + } + + // draw multiple rectangles + if(fillrect){ + testfillrect(); + usleep(1000000); + clearDisplay(); + } + + // draw mulitple circles + if(drawcircle){ + testdrawcircle(); + usleep(1000000); + clearDisplay(); + } + + // draw a white circle, 10 pixel radius + if(drawroundcircle){ + testdrawroundrect(); + usleep(1000000); + clearDisplay(); + } + + // Fill the round rectangle + if(fillroundcircle){ + testfillroundrect(); + usleep(1000000); + clearDisplay(); + } + + // Draw triangles + if(drawtriangle){ + testdrawtriangle(); + usleep(1000000); + clearDisplay(); + } + // Fill triangles + if(filltriangle){ + testfilltriangle(); + usleep(1000000); + clearDisplay(); + } + + // Display miniature bitmap + if(displaybitmap){ + display_bitmap(); + Display(); + usleep(1000000); + }; + + // Display Inverted image and normalize it back + if(displayinvertnormal){ + display_invert_normal(); + clearDisplay(); + usleep(1000000); + Display(); + } + + // Generate Signal after 20 Seconds + + // draw a bitmap icon and 'animate' movement + if(drawbitmapeg){ + alarm(10); + flag=0; + testdrawbitmap_eg(); + clearDisplay(); + usleep(1000000); + Display(); + } + + //setCursor(0,0); + setTextColor(WHITE); + + // info display + int sum = date+lanip+cpufreq+cputemp+netspeed; + if (sum == 0) { + clearDisplay(); + return 0; + } + + for(int i = 1; i < time; i++){ + if (sum == 1){//only one item for display + if (date) testdate(CENTER, 8); + if (lanip) testlanip(CENTER, 8); + if (cpufreq) testcpufreq(CENTER, 8); + if (cputemp) testcputemp(CENTER, 8); + if (netspeed) testnetspeed(SPLIT,0); + Display(); + usleep(1000000); + clearDisplay(); + }else if (sum == 2){//two items for display + if(date) {testdate(CENTER, 16*(date-1));} + if(lanip) {testlanip(CENTER, 16*(date+lanip-1));} + if(cpufreq) {testcpufreq(CENTER, 16*(date+lanip+cpufreq-1));} + if(cputemp) {testcputemp(CENTER, 16*(date+lanip+cpufreq+cputemp-1));} + if(netspeed) {testnetspeed(MERGE, 16*(date+lanip+cpufreq+cputemp+netspeed-1));} + Display(); + usleep(1000000); + clearDisplay(); + }else{//more than two items for display + if(date) {testdate(FULL, 8*(date-1));} + if(lanip) {testlanip(FULL, 8*(date+lanip-1));} + if(cpufreq && cputemp) { + testcpu(8*(date+lanip)); + if(netspeed) {testnetspeed(FULL, 8*(date+lanip+1+netspeed-1));} + }else{ + if(cpufreq) {testcpufreq(FULL, 8*(date+lanip+cpufreq-1));} + if(cputemp) {testcputemp(FULL, 8*(date+lanip+cpufreq+cputemp-1));} + if(netspeed) {testnetspeed(FULL, 8*(date+lanip+cpufreq+cputemp+netspeed-1));} + } + Display(); + usleep(1000000); + clearDisplay(); + } + } + } +} diff --git a/luci-app-ouad/src/Example_Code/example_app.c b/luci-app-ouad/src/Example_Code/example_app.c new file mode 100644 index 000000000..9ce62d025 --- /dev/null +++ b/luci-app-ouad/src/Example_Code/example_app.c @@ -0,0 +1,650 @@ +/* + * MIT License + +Copyright (c) 2017 DeeplyEmbedded + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + * example_app.c + * + * Created on : Sep 6, 2017 + * Author : Vinay Divakar + * Website : www.deeplyembedded.org + */ + +/* Lib Includes */ +#include +#include +#include +#include +#include +#include +#include +#include "SSD1306_OLED.h" +#include "example_app.h" + +#define BUFMAX SSD1306_LCDWIDTH*SSD1306_LCDHEIGHT + +/* MACRO's */ +#define LOGO16_GLCD_HEIGHT 16 +#define LOGO16_GLCD_WIDTH 16 +#define NUMFLAKES 10 +#define XPOS 0 +#define YPOS 1 +#define DELTAY 2 + + + +#define TIMESIZE 64 +//temperature +#define TEMPPATH "/sys/class/thermal/thermal_zone0/temp" +#define TEMPSIZE 5 +//cpu +#define FREQSIZE 8 +#define FREQPATH "cat /sys/devices/system/cpu/cpu[04]/cpufreq/cpuinfo_cur_freq" +//ip +#define IPPATH "ifconfig br-lan|grep 'inet addr:'|cut -d: -f2|awk '{print $1}'" +#define IPSIZE 20 +//netspeed +#define NETPATH "cat /tmp/netspeed" + +/* Extern volatile */ +extern volatile unsigned char flag; + +/* Bit Map - Taken from Adafruit SSD1306 OLED Library */ +static const unsigned char logo16_glcd_bmp[] = +{ + 0b00000000, 0b11000000, + 0b00000001, 0b11000000, + 0b00000001, 0b11000000, + 0b00000011, 0b11100000, + 0b11110011, 0b11100000, + 0b11111110, 0b11111000, + 0b01111110, 0b11111111, + 0b00110011, 0b10011111, + 0b00011111, 0b11111100, + 0b00001101, 0b01110000, + 0b00011011, 0b10100000, + 0b00111111, 0b11100000, + 0b00111111, 0b11110000, + 0b01111100, 0b11110000, + 0b01110000, 0b01110000, + 0b00000000, 0b00110000 +}; + +FILE *fp; +char content_buff[BUFMAX]; +char buf[BUFMAX]; +int display_offset =7; +/* draw many lines */ +void testdrawline() +{ + short i = 0; + for (i=0; i=0; i-=4) + { + drawLine(0, SSD1306_LCDHEIGHT-1, SSD1306_LCDWIDTH-1, i, WHITE); + Display(); + usleep(1000); + } + usleep(250000); + + clearDisplay(); + for (i=SSD1306_LCDWIDTH-1; i>=0; i-=4) + { + drawLine(SSD1306_LCDWIDTH-1, SSD1306_LCDHEIGHT-1, i, 0, WHITE); + Display(); + usleep(1000); + } + for (i=SSD1306_LCDHEIGHT-1; i>=0; i-=4) + { + drawLine(SSD1306_LCDWIDTH-1, SSD1306_LCDHEIGHT-1, 0, i, WHITE); + Display(); + usleep(1000); + } + usleep(250000); + + clearDisplay(); + for (i=0; i0; i-=5) + { + fillTriangle(SSD1306_LCDWIDTH/2, SSD1306_LCDHEIGHT/2-i, + SSD1306_LCDWIDTH/2-i, SSD1306_LCDHEIGHT/2+i, + SSD1306_LCDWIDTH/2+i, SSD1306_LCDHEIGHT/2+i, WHITE); + if (color == WHITE) + color = BLACK; + else + color = WHITE; + Display(); + usleep(1000); + } +} + +/* Display a bunch of characters and emoticons */ +void testdrawchar() +{ + unsigned char i = 0; + setTextSize(1); + setTextColor(WHITE); + setCursor(0,0); + + for (i=0; i < 168; i++) + { + if (i == '\n') + continue; + oled_write(i); + if ((i > 0) && (i % 21 == 0)) + println(); + } + Display(); + usleep(1000); +} + +/* Display "scroll" and scroll around */ +void testscrolltext(char* str) +{ + setTextSize(2); + setTextColor(WHITE); + setCursor(10,8); + sprintf(buf,"%s",str); + print_strln(buf); + Display(); + usleep(1000); + startscrollright(0x00, 0x0F); + usleep(5000000); + stopscroll(); + usleep(1000000); + startscrollleft(0x00, 0x0F); + usleep(5000000); + stopscroll(); + usleep(1000000); + startscrolldiagright(0x00, 0x07); + usleep(5000000); + startscrolldiagleft(0x00, 0x07); + usleep(5000000); + stopscroll(); +} + + + +/* Display Texts */ +void display_texts() +{ + setTextSize(1); + setTextColor(WHITE); + setCursor(10,0); + print_str("HELLO FELLAS!"); + println(); + printFloat_ln(3.141592, 4); //Print 4 No's after the decimal Pt. + printNumber_L_ln(-1234, DEC); + printNumber_UC_ln(170, BIN); + setTextSize(2); + setTextColor(WHITE); + print_str("0x"); + printNumber_UL_ln(0xDEADBEEF, HEX); +} + +/* Display miniature bitmap */ +void display_bitmap() +{ + drawBitmap(30, 16, logo16_glcd_bmp, 16, 16, 1); +} + +/* Invert Display and Normalize it */ +void display_invert_normal() +{ + invertDisplay(SSD1306_INVERT_DISPLAY); + usleep(1000000); + invertDisplay(SSD1306_NORMALIZE_DISPLAY); + usleep(1000000); +} + +/* Draw a bitmap and 'animate' movement */ +void testdrawbitmap(const unsigned char *bitmap, unsigned char w, unsigned char h) +{ + unsigned char icons[NUMFLAKES][3], f = 0; + + // initialize + for (f=0; f< NUMFLAKES; f++) + { + icons[f][XPOS] = rand() % SSD1306_LCDWIDTH; + icons[f][YPOS] = 0; + icons[f][DELTAY] = (rand() % 5) + 1; + + /* Looks kinna ugly to me - Un-Comment if you need it */ + //print_str("x: "); + //printNumber_UC(icons[f][XPOS], DEC); + //print_str("y: "); + //printNumber_UC(icons[f][YPOS], DEC); + //print_str("dy: "); + //printNumber_UC(icons[f][DELTAY], DEC); + } + + while (flag != 5) + { + // draw each icon + for (f=0; f< NUMFLAKES; f++) + { + drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, WHITE); + } + Display(); + usleep(200000); + + // then erase it + move it + for (f=0; f< NUMFLAKES; f++) + { + drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, BLACK); + + // move it + icons[f][YPOS] += icons[f][DELTAY]; + + // if its gone, reinit + if (icons[f][YPOS] > SSD1306_LCDHEIGHT) + { + icons[f][XPOS] = rand() % SSD1306_LCDWIDTH; + icons[f][YPOS] = 0; + icons[f][DELTAY] = (rand() % 5) + 1; + } + } + } +} + +/* Draw bitmap and animate */ +void testdrawbitmap_eg() +{ + setTextSize(1); + setTextColor(WHITE); + setCursor(10,0); + testdrawbitmap(logo16_glcd_bmp, LOGO16_GLCD_HEIGHT, LOGO16_GLCD_WIDTH); +} + +/* Intro */ +void deeplyembedded_credits() +{ + setTextSize(1); + setTextColor(WHITE); + setCursor(1,0); + print_strln("deeplyembedded.org"); + println(); + print_strln("Author:Vinay Divakar"); + println(); + println(); + print_strln("THANK YOU"); +} + + +void testdate(int mode, int y) +{ + time_t rawtime; + time_t curtime; + uint8_t timebuff[TIMESIZE]; + curtime = time(NULL); + time(&rawtime); + switch (mode) + { + case CENTER: + setTextSize(2); + strftime(timebuff,80,"%H:%M",localtime(&rawtime)); + sprintf(buf,"%s",timebuff); + setCursor((127-strlen(buf)*11)/2-4, y); + break; + case FULL: + setTextSize(1); + strftime(timebuff,80,"%Y-%m-%d %H:%M:%S",localtime(&rawtime)); + sprintf(buf,"%s",timebuff); + setCursor(display_offset, y); + } + print_strln(buf); +} + + +void testlanip(int mode, int y) +{ + setTextSize(1); + if((fp=popen(IPPATH,"r"))!=NULL) + { + fscanf(fp,"%s",content_buff); + fclose(fp); + //ipbuff[strlen(ipbuff)-1]=32; + switch(mode) + { + case CENTER: + setTextSize(1); + sprintf(buf,"%s",content_buff); + setCursor((127-strlen(buf)*6)/2, y+4); + break; + + case FULL: + setTextSize(1); + sprintf(buf,"IP:%s",content_buff); + setCursor(display_offset, y); + } + print_strln(buf); + } + +} + + +void testcputemp(int mode, int y) +{ + if((fp=fopen(TEMPPATH,"r"))!=NULL) + { + fgets(content_buff,TEMPSIZE,fp); + fclose(fp); + switch (mode) + { + case CENTER: + setTextSize(2); + sprintf(buf, "%.2f",atoi(content_buff)/100.0); + setCursor((127-(strlen(buf)+2)*11)/2-4, y); + print_str(buf); + oled_write(0); + oled_write(67); + drawCircle(getCursorX()-16, getCursorY()+3, 2, WHITE); + break; + case FULL: + setTextSize(1); + sprintf(buf,"CPU TEMP:%.2f",atoi(content_buff)/100.0); + setCursor(display_offset, y); + print_str(buf); + oled_write(0); + oled_write(67); + drawCircle(getCursorX()-8, getCursorY()+1, 1, WHITE); + } + + } + +} + + +void testcpufreq(int mode, int y) +{ + if((fp=popen(FREQPATH,"r")) != NULL) + { + fgets(content_buff,FREQSIZE,fp); + fclose(fp); + switch(mode) + { + case CENTER: + setTextSize(2); + sprintf(buf,"%4dMHz",atoi(content_buff)/1000); + setCursor((127-strlen(buf)*11)/2-4, y); + break; + case FULL: + setTextSize(1); + sprintf(buf,"CPU FREQ:%4dMHz",atoi(content_buff)/1000); + setCursor(display_offset, y); + } + print_strln(buf); + } + +} + +void testnetspeed(int mode, int y) +{ + int rx,tx; + if((fp=popen(NETPATH,"r")) != NULL) + { + fscanf(fp,"%d %d", &rx, &tx); + fclose(fp); + rx = rx; + tx = tx; + switch(mode) + { + case SPLIT: + setTextSize(2); + if (tx < 1000) sprintf(buf, "%03dB", tx); + else if (tx > 1000000) sprintf(buf, "%03dM", tx/1000000); + else sprintf(buf, "%03dK", tx/1000); + setCursor((127-(strlen(buf)+1)*11)/2,0); + oled_write(24); + print_str(buf); + + if (rx < 1000) sprintf(buf, "%03dB", rx); + else if (rx > 1000000) sprintf(buf, "%03dM", rx/1000000); + else sprintf(buf, "%03dK", rx/1000); + setCursor((127-(strlen(buf)+1)*11)/2,16); + oled_write(25); + print_str(buf); + break; + case MERGE: + setTextSize(1); + if (tx < 1000) sprintf(buf, "%03dB ", tx); + else if (tx > 1000000) sprintf(buf, "%03dM", tx/1000000); + else sprintf(buf, "%03dK ", tx/1000); + setCursor((127-(2*strlen(buf)-1)*6)/2-4, y+4); + oled_write(24); + print_str(buf); + + if (rx < 1000) sprintf(buf, "%03dB", rx); + else if (rx > 1000000) sprintf(buf, "%03dM", rx/1000000); + else sprintf(buf, "%03dK", rx/1000); + oled_write(25); + print_str(buf); + break; + case FULL: + setTextSize(1); + setCursor(display_offset, y); + oled_write(24); + if (tx < 1000) sprintf(buf, "%03dB ", tx); + else if (tx > 1000000) sprintf(buf, "%03dM", tx/1000000); + else sprintf(buf, "%03dK ", tx/1000); + print_str(buf); + + oled_write(25); + if (rx < 1000) sprintf(buf, "%03dB", rx); + else if (rx > 1000000) sprintf(buf, "%03dM", rx/1000000); + else sprintf(buf, "%03dK", rx/1000); + print_str(buf); + } + } +} +void testcpu(int y) +{ +//freq + setTextSize(1); + setCursor(display_offset, y); + if((fp=popen(FREQPATH,"r")) != NULL) + { + fgets(content_buff,FREQSIZE,fp); + fclose(fp); + sprintf(buf,"CPU:%4dMHz ", atoi(content_buff)/1000); + print_str(buf); + } + + +//temp + if((fp=fopen(TEMPPATH,"r"))!=NULL) + { + fgets(content_buff,TEMPSIZE,fp); + fclose(fp); + sprintf(buf, "%.2f",atoi(content_buff)/100.0); + print_str(buf); + oled_write(0); + oled_write(67); + drawCircle(getCursorX()-8, getCursorY()+1, 1, WHITE); + } +} + +void testprintinfo() +{ + setTextSize(1); + setTextColor(WHITE); + setCursor(0,0); +//DATE + + time_t rawtime; + time_t curtime; + uint8_t timebuff[TIMESIZE]; + curtime = time(NULL); + time(&rawtime); + strftime(timebuff,80,"%Y-%m-%d_%w %H:%M:%S",localtime(&rawtime)); + sprintf(buf,"%s",timebuff); + print_strln(buf); + + //br-lan ip + if((fp=popen(IPPATH,"r"))!=NULL) + { + fscanf(fp,"%s",content_buff); + fclose(fp); + //ipbuff[strlen(ipbuff)-1]=32; + sprintf(buf,"IP:%s",content_buff); + print_strln(buf); + } + + //CPU temp + if((fp=popen(FREQPATH,"r")) != NULL) + { + fgets(content_buff,FREQSIZE,fp); + fclose(fp); + sprintf(buf,"CPU freq:%d MHz ",atoi(content_buff)/1000); + print_strln(buf); + } + + //cpu freq + if((fp=fopen(TEMPPATH,"r"))!=NULL) + { + fgets(content_buff,TEMPSIZE,fp); + fclose(fp); + sprintf(buf,"CPU temp:%.2f C",atoi(content_buff)/100.0); + print_strln(buf); + } + + + +} + diff --git a/luci-app-ouad/src/Example_Code/example_app.h b/luci-app-ouad/src/Example_Code/example_app.h new file mode 100644 index 000000000..eb0435826 --- /dev/null +++ b/luci-app-ouad/src/Example_Code/example_app.h @@ -0,0 +1,30 @@ +#define CENTER 0 //single item display +#define SPLIT 1 //two items +#define MERGE 2 +#define FULL 3 + +void testdrawline(); +void testdrawrect(); +void testfillrect(); +void testdrawcircle(); +void testdrawroundrect(); +void testfillroundrect(); +void testdrawtriangle(); +void testfilltriangle(); +void testdrawchar(); +void testscrolltext(char *str); +void display_texts(); +void display_bitmap(); +void display_invert_normal(); +void testdrawbitmap(const unsigned char *bitmap, unsigned char w, unsigned char h); +void testdrawbitmap_eg(); +void deeplyembedded_credits(); +void testprintinfo(); +void testdate(int mode, int y); +void testlanip(int mode, int y); +void testcpufreq(int mode, int y); +void testcputemp(int mode, int y); +void testnetspeed(int mode, int y); +void testcpu(int y); + + diff --git a/luci-app-ouad/src/I2C_Library/I2C.c b/luci-app-ouad/src/I2C_Library/I2C.c new file mode 100644 index 000000000..7177f8424 --- /dev/null +++ b/luci-app-ouad/src/I2C_Library/I2C.c @@ -0,0 +1,281 @@ +/* + * MIT License + +Copyright (c) 2017 DeeplyEmbedded + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + * I2C.c + * + * Created on : September 19, 2017 + * Author : Vinay Divakar + * Description : This is an I2C Library for the BeagleBone that consists of the API's to support the standard + * I2C operations. + * Website : www.deeplyembedded.org + */ + +/*Libs Includes*/ +#include +#include +#include +#include +#include +// heuristic to guess what version of i2c-dev.h we have: +// the one installed with `apt-get install libi2c-dev` +// would conflict with linux/i2c.h, while the stock +// one requires linus/i2c.h +#ifndef I2C_SMBUS_BLOCK_MAX +// If this is not defined, we have the "stock" i2c-dev.h +// so we include linux/i2c.h +#include +typedef unsigned char i2c_char_t; +#else +typedef char i2c_char_t; +#endif + +/* Header Files */ +#include "I2C.h" + + +/* Exposed objects for i2c-x */ +I2C_DeviceT I2C_DEV_2; + +/**************************************************************** + * Function Name : Open_device + * Description : Opens the I2C device to use + * Returns : 0 on success, -1 on failure + * Params @i2c_dev_path: Path to the I2C device + * @fd: Variable to store the file handler + ****************************************************************/ +int Open_device(char *i2c_dev_path, int *fd) +{ + if((*fd = open(i2c_dev_path, O_RDWR))<0) + return -1; + else + return 0; +} + + +/**************************************************************** + * Function Name : Close_device + * Description : Closes the I2C device in use + * Returns : 0 on success, -1 on failure + * Params : @fd: file descriptor + ****************************************************************/ +int Close_device(int fd) +{ + if(close(fd) == -1) + return -1; + else + return 0; +} + + +/**************************************************************** + * Function Name : Set_slave_addr + * Description : Connect to the Slave device + * Returns : 0 on success, -1 on failure + * Params @fd: File descriptor + * @slave_addr: Address of the slave device to + * talk to. + ****************************************************************/ +int Set_slave_addr(int fd, unsigned char slave_addr) +{ + if(ioctl(fd, I2C_SLAVE, slave_addr) < 0) + return -1; + else + return 0; +} + + +/**************************************************************** + * Function Name : i2c_write + * Description : Write a byte on SDA + * Returns : No. of bytes written on success, -1 on failure + * Params @fd: File descriptor + * @data: data to write on SDA + ****************************************************************/ +int i2c_write(int fd, unsigned char data) +{ + int ret = 0; + ret = write(fd, &data, I2C_ONE_BYTE); + if((ret == -1) || (ret != 1)) + return -1; + else + return(ret); +} + + +/**************************************************************** + * Function Name : i2c_read + * Description : Read a byte on SDA + * Returns : No. of bytes read on success, -1 on failure + * Params @fd: File descriptor + * @read_data: Points to the variable that stores + * the read data byte + ****************************************************************/ +int i2c_read(int fd, unsigned char *read_data) +{ + int ret = 0; + ret = read(fd, &read_data, I2C_ONE_BYTE); + if(ret == -1) + perror("I2C: Failed to read |"); + if(ret == 0) + perror("I2C: End of FILE |"); + return(ret); +} + + +/**************************************************************** + * Function Name : i2c_read_register + * Description : Read a single register of the slave device + * Returns : No. of bytes read on success, -1 on failure + * Params @fd: File descriptor + * @read_addr: Register address to be read + * @read_data: Points to the variable that stores + * the read data byte + ****************************************************************/ +int i2c_read_register(int fd, unsigned char read_addr, unsigned char *read_data) +{ + int ret = 0; + if(i2c_write(fd, read_addr) == -1) + { + perror("I2C: Failed to write |"); + return -1; + } + ret = read(fd, &read_data, I2C_ONE_BYTE); + if(ret == -1) + perror("I2C: Failed to read |"); + if(ret == 0) + perror("I2C: End of FILE |"); + return(ret); +} + + +/**************************************************************** + * Function Name : i2c_read_registers + * Description : Read a multiple registers on the slave device + * from starting address + * Returns : No. of bytes read on success, -1 on failure + * Params @fd: File descriptor + * @num: Number of registers/bytes to read from. + * @starting_addr: Starting address to read from + * @buff_Ptr: Buffer to store the read bytes + ****************************************************************/ +int i2c_read_registers(int fd, int num, unsigned char starting_addr, + unsigned char *buff_Ptr) +{ + int ret = 0; + if(i2c_write(fd, starting_addr) == -1) + { + perror("I2C: Failed to write |"); + return -1; + } + ret = read(fd, buff_Ptr, num); + if(ret == -1) + perror("I2C: Failed to read |"); + if(ret == 0) + perror("I2C: End of FILE |"); + return(ret); +} + + +/**************************************************************** + * Function Name : i2c_multiple_writes + * Description : Write multiple bytes on SDA + * Returns : No. of bytes written on success, -1 on failure + * Params @fd: file descriptor + * @num: No. of bytes to write + * @Ptr_buff: Pointer to the buffer containing the + * bytes to be written on the SDA + ****************************************************************/ +int i2c_multiple_writes(int fd, int num, unsigned char *Ptr_buff) +{ + int ret = 0; + ret = write(fd, Ptr_buff, num); + if((ret == -1) || (ret != num)) + return -1; + else + return(ret); +} + + +/**************************************************************** + * Function Name : i2c_write_register + * Description : Write a control byte or byte to a register + * Returns : No. of bytes written on success, -1 on failure + * Params @fd: file descriptor + * @reg_addr_or_cntrl: Control byte or Register + * address to be written + * @val: Command or value to be written in the + * addressed register + ****************************************************************/ +int i2c_write_register(int fd, unsigned char reg_addr_or_cntrl, unsigned char val) +{ + unsigned char buff[2]; + int ret = 0; + buff[0] = reg_addr_or_cntrl; + buff[1] = val; + ret = write(fd, buff, I2C_TWO_BYTES); + if((ret == -1) || (ret != I2C_TWO_BYTES)) + return -1; + else + return(ret); +} + + +/**************************************************************** + * Function Name : config_i2c_struct + * Description : Initialize the I2C device structure + * Returns : NONE + * Params @i2c_dev_path: Device path + * @slave_addr: Slave device address + * @i2c_dev: Pointer to the device structure + ****************************************************************/ +void config_i2c_struct(char *i2c_dev_path, unsigned char slave_addr, I2C_DevicePtr i2c_dev) +{ + i2c_dev->i2c_dev_path = i2c_dev_path; + i2c_dev->fd_i2c = 0; + i2c_dev->i2c_slave_addr = slave_addr; +} + + +/**************************************************************** + * Function Name : init_i2c_dev + * Description : Connect the i2c bus to the slave device + * Returns : 0 on success, -1 on failure + * Params @i2c_path: the path to the device + * @slave_addr: Slave device address + ****************************************************************/ +int init_i2c_dev(const char* i2c_path, unsigned char slave_address) +{ + config_i2c_struct((char*)i2c_path, slave_address, &I2C_DEV_2); + if(Open_device(I2C_DEV_2.i2c_dev_path, &I2C_DEV_2.fd_i2c) == -1) + { + perror("I2C: Failed to open device |"); + return -1; + } + if(Set_slave_addr(I2C_DEV_2.fd_i2c, I2C_DEV_2.i2c_slave_addr) == -1) + { + perror("I2C: Failed to connect to slave device |"); + return -1; + } + + return 0; +} diff --git a/luci-app-ouad/src/I2C_Library/I2C.h b/luci-app-ouad/src/I2C_Library/I2C.h new file mode 100644 index 000000000..ffcc45933 --- /dev/null +++ b/luci-app-ouad/src/I2C_Library/I2C.h @@ -0,0 +1,69 @@ +/* + * MIT License + +Copyright (c) 2017 DeeplyEmbedded + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + * I2C.h + * + * Created on : Sep 4, 2017 + * Author : Vinay Divakar + * Website : www.deeplyembedded.org + */ + +#ifndef I2C_H_ +#define I2C_H_ + +#include + +/* No. of bytes per transaction */ +#define I2C_ONE_BYTE 1 +#define I2C_TWO_BYTES 2 +#define I2C_THREE_BYTES 3 + +/*Definitions specific to i2c-x */ +#define I2C_DEV0_PATH "/dev/i2c-0" +#define I2C_DEV1_PATH "/dev/i2c-1" +#define I2C_DEV2_PATH "/dev/i2c-2" + +/*I2C device configuration structure*/ +typedef struct{ + char* i2c_dev_path; + int fd_i2c; + unsigned char i2c_slave_addr; +}I2C_DeviceT, *I2C_DevicePtr; + +/* Exposed Generic I2C Functions */ +extern int Open_device(char *i2c_dev_path, int *fd); +extern int Close_device(int fd); +extern int Set_slave_addr(int fd, unsigned char slave_addr); +extern int i2c_write(int fd, unsigned char data); +extern int i2c_read(int fd, unsigned char *read_data); +extern int i2c_read_register(int fd, unsigned char read_addr, unsigned char *read_data); +extern int i2c_read_registers(int fd, int num, unsigned char starting_addr, + unsigned char *buff_Ptr); +extern void config_i2c_struct(char *i2c_dev_path, unsigned char slave_addr, I2C_DevicePtr i2c_dev); +extern int i2c_multiple_writes(int fd, int num, unsigned char *Ptr_buff); +extern int i2c_write_register(int fd, unsigned char reg_addr_or_cntrl, unsigned char val); + +/* Exposed I2C-x Specific Functions */ +extern int init_i2c_dev(const char* i2c_path, unsigned char slave_address); + +#endif /* I2C_H_ */ diff --git a/luci-app-ouad/src/LICENSE b/luci-app-ouad/src/LICENSE new file mode 100644 index 000000000..e99e91b40 --- /dev/null +++ b/luci-app-ouad/src/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 DeeplyEmbedded + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/luci-app-ouad/src/Makefile b/luci-app-ouad/src/Makefile new file mode 100644 index 000000000..0f1b25559 --- /dev/null +++ b/luci-app-ouad/src/Makefile @@ -0,0 +1,19 @@ +CC = gcc +LD = gcc + +SOURCES = SSD1306_OLED_Library/SSD1306_OLED.c Example_Code/Main.c Example_Code/example_app.c I2C_Library/I2C.c +OBJS := $(SOURCES:.c=.o) +CPPFLAGS := -I SSD1306_OLED_Library -I I2C_Library +CFLAGS := -g + +oled: $(OBJS) + $(CC) $^ -o $@ + +clean: + rm -rf oled $(OBJS) + +compile: oled + +install: compile + mkdir -p $(DESTDIR)/usr/bin + cp oled $(DESTDIR)/usr/bin/oled diff --git a/luci-app-ouad/src/README.md b/luci-app-ouad/src/README.md new file mode 100644 index 000000000..080474f06 --- /dev/null +++ b/luci-app-ouad/src/README.md @@ -0,0 +1,21 @@ +# SSD1306-OLED-display-driver-for-BeagleBone +This is a SSD1306 OLED Display Library fully compatible with the BeagleBone. + +The Library has 3 components: +1. I2C component for enabling communication between the BeagleBone and display. +2. Control component for sending I2C commands to configure and control the display. +3. Graphics component for drawing geometrical figures, bitmaps, texts, characters, emoticons and numbers. + +Author: Vinay Divakar + +References: +1. https://github.com/adafruit/Adafruit_SSD1306 +2. https://github.com/adafruit/Adafruit-GFX-Library + +Youtube demo: https://youtu.be/sDKf6zW6Pyg + +MIT license, check LICENSE file for more information + +This Library is written in C. To use it, just include the I2C and SSD1306 Libraries in your project. + +Enjoy :) diff --git a/luci-app-ouad/src/SSD1306_OLED_Library/SSD1306_OLED.c b/luci-app-ouad/src/SSD1306_OLED_Library/SSD1306_OLED.c new file mode 100644 index 000000000..b15660356 --- /dev/null +++ b/luci-app-ouad/src/SSD1306_OLED_Library/SSD1306_OLED.c @@ -0,0 +1,2761 @@ +/* + * MIT License + +Copyright (c) 2017 DeeplyEmbedded + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + * SSD1306_OLED.c + * + * Created on : Sep 26, 2017 + * Author : Vinay Divakar + * Description : SSD1306 OLED Driver, Graphics API's. + * Website : www.deeplyembedded.org + */ + +/* Lib Includes */ +#include +#include +#include +#include +#include +#include "I2C.h" +#include "SSD1306_OLED.h" +#include "gfxfont.h" + +/* Enable or Disable DEBUG Prints */ +//#define SSD1306_DBG + +/* MACROS */ +#define SWAP(x,y) {short temp; temp = x; x = y; y = temp;} +#define pgm_read_byte(addr) (*(const unsigned char *)(addr)) +#define pgm_read_word(addr) (*(const unsigned long *)(addr)) +#define pgm_read_dword(addr) (*(const unsigned long *)(addr)) +#define pgm_read_pointer(addr) ((void *)pgm_read_word(addr)) + +/* static Variables */ +static unsigned char _rotation = 0,textsize = 0; +static short _width = SSD1306_LCDWIDTH; +static short _height = SSD1306_LCDHEIGHT; +static short cursor_x = 0, cursor_y = 0, textcolor = 0, textbgcolor = 0; +static bool _cp437 = false, wrap = true; + +/* static struct objects */ +static GFXfontPtr gfxFont; + +/* Externs - I2C.c */ +extern I2C_DeviceT I2C_DEV_2; + +/* Chunk Buffer */ +static unsigned char chunk[17] = {0}; + +/* Memory buffer for displaying data on LCD - This is an Apple - Fruit */ +static unsigned char screen[DISPLAY_BUFF_SIZE] ={0}; + +/* Static Functions */ +static void transfer(); +static void drawFastVLine(short x, short y,short h, short color); +static void writeFastVLine(short x, short y, short h, short color); +static void drawFastHLine(short x, short y,short w, short color); +static void writeFastHLine(short x, short y, short w, short color); +static short print(const unsigned char *buffer, short size); + +// Standard ASCII 5x7 font +static const unsigned char ssd1306_font5x7[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, //space + 0x3E, 0x5B, 0x4F, 0x5B, 0x3E, + 0x3E, 0x6B, 0x4F, 0x6B, 0x3E, + 0x1C, 0x3E, 0x7C, 0x3E, 0x1C, + 0x18, 0x3C, 0x7E, 0x3C, 0x18, + 0x1C, 0x57, 0x7D, 0x57, 0x1C, + 0x1C, 0x5E, 0x7F, 0x5E, 0x1C, + 0x00, 0x18, 0x3C, 0x18, 0x00, + 0xFF, 0xE7, 0xC3, 0xE7, 0xFF, + 0x00, 0x18, 0x24, 0x18, 0x00, + 0xFF, 0xE7, 0xDB, 0xE7, 0xFF, + 0x30, 0x48, 0x3A, 0x06, 0x0E, + 0x26, 0x29, 0x79, 0x29, 0x26, + 0x40, 0x7F, 0x05, 0x05, 0x07, + 0x40, 0x7F, 0x05, 0x25, 0x3F, + 0x5A, 0x3C, 0xE7, 0x3C, 0x5A, + 0x7F, 0x3E, 0x1C, 0x1C, 0x08, + 0x08, 0x1C, 0x1C, 0x3E, 0x7F, + 0x14, 0x22, 0x7F, 0x22, 0x14, + 0x5F, 0x5F, 0x00, 0x5F, 0x5F, + 0x06, 0x09, 0x7F, 0x01, 0x7F, + 0x00, 0x66, 0x89, 0x95, 0x6A, + 0x60, 0x60, 0x60, 0x60, 0x60, + 0x94, 0xA2, 0xFF, 0xA2, 0x94, + 0x08, 0x04, 0x7E, 0x04, 0x08,//up INDEX 24 + 0x10, 0x20, 0x7E, 0x20, 0x10,//down INDEX 25 + 0x08, 0x08, 0x2A, 0x1C, 0x08, + 0x08, 0x1C, 0x2A, 0x08, 0x08, + 0x1E, 0x10, 0x10, 0x10, 0x10, + 0x0C, 0x1E, 0x0C, 0x1E, 0x0C, + 0x30, 0x38, 0x3E, 0x38, 0x30, + 0x06, 0x0E, 0x3E, 0x0E, 0x06, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x5F, 0x00, 0x00, + 0x00, 0x07, 0x00, 0x07, 0x00, + 0x14, 0x7F, 0x14, 0x7F, 0x14, + 0x24, 0x2A, 0x7F, 0x2A, 0x12, + 0x23, 0x13, 0x08, 0x64, 0x62, + 0x36, 0x49, 0x56, 0x20, 0x50, + 0x00, 0x08, 0x07, 0x03, 0x00, + 0x00, 0x1C, 0x22, 0x41, 0x00, + 0x00, 0x41, 0x22, 0x1C, 0x00, + 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, + 0x08, 0x08, 0x3E, 0x08, 0x08, + 0x00, 0x80, 0x70, 0x30, 0x00, + 0x08, 0x08, 0x08, 0x08, 0x08, + 0x00, 0x00, 0x60, 0x60, 0x00, + 0x20, 0x10, 0x08, 0x04, 0x02, + 0x3E, 0x51, 0x49, 0x45, 0x3E, + 0x00, 0x42, 0x7F, 0x40, 0x00, + 0x72, 0x49, 0x49, 0x49, 0x46, + 0x21, 0x41, 0x49, 0x4D, 0x33, + 0x18, 0x14, 0x12, 0x7F, 0x10, + 0x27, 0x45, 0x45, 0x45, 0x39, + 0x3C, 0x4A, 0x49, 0x49, 0x31, + 0x41, 0x21, 0x11, 0x09, 0x07, + 0x36, 0x49, 0x49, 0x49, 0x36, + 0x46, 0x49, 0x49, 0x29, 0x1E, + 0x00, 0x00, 0x14, 0x00, 0x00, + 0x00, 0x40, 0x34, 0x00, 0x00, + 0x00, 0x08, 0x14, 0x22, 0x41, + 0x14, 0x14, 0x14, 0x14, 0x14, + 0x00, 0x41, 0x22, 0x14, 0x08, + 0x02, 0x01, 0x59, 0x09, 0x06, + 0x3E, 0x41, 0x5D, 0x59, 0x4E, + 0x7C, 0x12, 0x11, 0x12, 0x7C, + 0x7F, 0x49, 0x49, 0x49, 0x36, + 0x3E, 0x41, 0x41, 0x41, 0x22,//C + 0x7F, 0x41, 0x41, 0x41, 0x3E,//D + 0x7F, 0x49, 0x49, 0x49, 0x41,//E + 0x7F, 0x09, 0x09, 0x09, 0x01,//F + 0x3E, 0x41, 0x41, 0x51, 0x73, + 0x7F, 0x08, 0x08, 0x08, 0x7F, + 0x00, 0x41, 0x7F, 0x41, 0x00, + 0x20, 0x40, 0x41, 0x3F, 0x01, + 0x7F, 0x08, 0x14, 0x22, 0x41, + 0x7F, 0x40, 0x40, 0x40, 0x40, + 0x7F, 0x02, 0x1C, 0x02, 0x7F, + 0x7F, 0x04, 0x08, 0x10, 0x7F, + 0x3E, 0x41, 0x41, 0x41, 0x3E, + 0x7F, 0x09, 0x09, 0x09, 0x06, + 0x3E, 0x41, 0x51, 0x21, 0x5E, + 0x7F, 0x09, 0x19, 0x29, 0x46, + 0x26, 0x49, 0x49, 0x49, 0x32, + 0x03, 0x01, 0x7F, 0x01, 0x03, + 0x3F, 0x40, 0x40, 0x40, 0x3F, + 0x1F, 0x20, 0x40, 0x20, 0x1F, + 0x3F, 0x40, 0x38, 0x40, 0x3F, + 0x63, 0x14, 0x08, 0x14, 0x63, + 0x03, 0x04, 0x78, 0x04, 0x03, + 0x61, 0x59, 0x49, 0x4D, 0x43, + 0x00, 0x7F, 0x41, 0x41, 0x41, + 0x02, 0x04, 0x08, 0x10, 0x20, + 0x00, 0x41, 0x41, 0x41, 0x7F, + 0x04, 0x02, 0x01, 0x02, 0x04, + 0x40, 0x40, 0x40, 0x40, 0x40, + 0x00, 0x03, 0x07, 0x08, 0x00, + 0x20, 0x54, 0x54, 0x78, 0x40, + 0x7F, 0x28, 0x44, 0x44, 0x38, + 0x38, 0x44, 0x44, 0x44, 0x28, + 0x38, 0x44, 0x44, 0x28, 0x7F, + 0x38, 0x54, 0x54, 0x54, 0x18, + 0x00, 0x08, 0x7E, 0x09, 0x02, + 0x18, 0xA4, 0xA4, 0x9C, 0x78, + 0x7F, 0x08, 0x04, 0x04, 0x78, + 0x00, 0x44, 0x7D, 0x40, 0x00, + 0x20, 0x40, 0x40, 0x3D, 0x00, + 0x7F, 0x10, 0x28, 0x44, 0x00, + 0x00, 0x41, 0x7F, 0x40, 0x00, + 0x7C, 0x04, 0x78, 0x04, 0x78, + 0x7C, 0x08, 0x04, 0x04, 0x78, + 0x38, 0x44, 0x44, 0x44, 0x38, + 0xFC, 0x18, 0x24, 0x24, 0x18, + 0x18, 0x24, 0x24, 0x18, 0xFC, + 0x7C, 0x08, 0x04, 0x04, 0x08, + 0x48, 0x54, 0x54, 0x54, 0x24, + 0x04, 0x04, 0x3F, 0x44, 0x24, + 0x3C, 0x40, 0x40, 0x20, 0x7C, + 0x1C, 0x20, 0x40, 0x20, 0x1C, + 0x3C, 0x40, 0x30, 0x40, 0x3C, + 0x44, 0x28, 0x10, 0x28, 0x44, + 0x4C, 0x90, 0x90, 0x90, 0x7C, + 0x44, 0x64, 0x54, 0x4C, 0x44, + 0x00, 0x08, 0x36, 0x41, 0x00, + 0x00, 0x00, 0x77, 0x00, 0x00, + 0x00, 0x41, 0x36, 0x08, 0x00, + 0x02, 0x01, 0x02, 0x04, 0x02, + 0x3C, 0x26, 0x23, 0x26, 0x3C, + 0x1E, 0xA1, 0xA1, 0x61, 0x12, + 0x3A, 0x40, 0x40, 0x20, 0x7A, + 0x38, 0x54, 0x54, 0x55, 0x59, + 0x21, 0x55, 0x55, 0x79, 0x41, + 0x22, 0x54, 0x54, 0x78, 0x42, // a-umlaut + 0x21, 0x55, 0x54, 0x78, 0x40, + 0x20, 0x54, 0x55, 0x79, 0x40, + 0x0C, 0x1E, 0x52, 0x72, 0x12, + 0x39, 0x55, 0x55, 0x55, 0x59, + 0x39, 0x54, 0x54, 0x54, 0x59, + 0x39, 0x55, 0x54, 0x54, 0x58, + 0x00, 0x00, 0x45, 0x7C, 0x41, + 0x00, 0x02, 0x45, 0x7D, 0x42, + 0x00, 0x01, 0x45, 0x7C, 0x40, + 0x7D, 0x12, 0x11, 0x12, 0x7D, // A-umlaut + 0xF0, 0x28, 0x25, 0x28, 0xF0, + 0x7C, 0x54, 0x55, 0x45, 0x00, + 0x20, 0x54, 0x54, 0x7C, 0x54, + 0x7C, 0x0A, 0x09, 0x7F, 0x49, + 0x32, 0x49, 0x49, 0x49, 0x32, + 0x3A, 0x44, 0x44, 0x44, 0x3A, // o-umlaut + 0x32, 0x4A, 0x48, 0x48, 0x30, + 0x3A, 0x41, 0x41, 0x21, 0x7A, + 0x3A, 0x42, 0x40, 0x20, 0x78, + 0x00, 0x9D, 0xA0, 0xA0, 0x7D, + 0x3D, 0x42, 0x42, 0x42, 0x3D, // O-umlaut + 0x3D, 0x40, 0x40, 0x40, 0x3D, + 0x3C, 0x24, 0xFF, 0x24, 0x24, + 0x48, 0x7E, 0x49, 0x43, 0x66, + 0x2B, 0x2F, 0xFC, 0x2F, 0x2B, + 0xFF, 0x09, 0x29, 0xF6, 0x20, + 0xC0, 0x88, 0x7E, 0x09, 0x03, + 0x20, 0x54, 0x54, 0x79, 0x41, + 0x00, 0x00, 0x44, 0x7D, 0x41, + 0x30, 0x48, 0x48, 0x4A, 0x32, + 0x38, 0x40, 0x40, 0x22, 0x7A, + 0x00, 0x7A, 0x0A, 0x0A, 0x72, + 0x7D, 0x0D, 0x19, 0x31, 0x7D, + 0x26, 0x29, 0x29, 0x2F, 0x28, + 0x26, 0x29, 0x29, 0x29, 0x26, + 0x30, 0x48, 0x4D, 0x40, 0x20, + 0x38, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x38, + 0x2F, 0x10, 0xC8, 0xAC, 0xBA, + 0x2F, 0x10, 0x28, 0x34, 0xFA, + 0x00, 0x00, 0x7B, 0x00, 0x00, + 0x08, 0x14, 0x2A, 0x14, 0x22, + 0x22, 0x14, 0x2A, 0x14, 0x08, + 0x55, 0x00, 0x55, 0x00, 0x55, // #176 (25% block) missing in old code + 0xAA, 0x55, 0xAA, 0x55, 0xAA, // 50% block + 0xFF, 0x55, 0xFF, 0x55, 0xFF, // 75% block + 0x00, 0x00, 0x00, 0xFF, 0x00, + 0x10, 0x10, 0x10, 0xFF, 0x00, + 0x14, 0x14, 0x14, 0xFF, 0x00, + 0x10, 0x10, 0xFF, 0x00, 0xFF, + 0x10, 0x10, 0xF0, 0x10, 0xF0, + 0x14, 0x14, 0x14, 0xFC, 0x00, + 0x14, 0x14, 0xF7, 0x00, 0xFF, + 0x00, 0x00, 0xFF, 0x00, 0xFF, + 0x14, 0x14, 0xF4, 0x04, 0xFC, + 0x14, 0x14, 0x17, 0x10, 0x1F, + 0x10, 0x10, 0x1F, 0x10, 0x1F, + 0x14, 0x14, 0x14, 0x1F, 0x00, + 0x10, 0x10, 0x10, 0xF0, 0x00, + 0x00, 0x00, 0x00, 0x1F, 0x10, + 0x10, 0x10, 0x10, 0x1F, 0x10, + 0x10, 0x10, 0x10, 0xF0, 0x10, + 0x00, 0x00, 0x00, 0xFF, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0xFF, 0x10, + 0x00, 0x00, 0x00, 0xFF, 0x14, + 0x00, 0x00, 0xFF, 0x00, 0xFF, + 0x00, 0x00, 0x1F, 0x10, 0x17, + 0x00, 0x00, 0xFC, 0x04, 0xF4, + 0x14, 0x14, 0x17, 0x10, 0x17, + 0x14, 0x14, 0xF4, 0x04, 0xF4, + 0x00, 0x00, 0xFF, 0x00, 0xF7, + 0x14, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x14, 0xF7, 0x00, 0xF7, + 0x14, 0x14, 0x14, 0x17, 0x14, + 0x10, 0x10, 0x1F, 0x10, 0x1F, + 0x14, 0x14, 0x14, 0xF4, 0x14, + 0x10, 0x10, 0xF0, 0x10, 0xF0, + 0x00, 0x00, 0x1F, 0x10, 0x1F, + 0x00, 0x00, 0x00, 0x1F, 0x14, + 0x00, 0x00, 0x00, 0xFC, 0x14, + 0x00, 0x00, 0xF0, 0x10, 0xF0, + 0x10, 0x10, 0xFF, 0x10, 0xFF, + 0x14, 0x14, 0x14, 0xFF, 0x14, + 0x10, 0x10, 0x10, 0x1F, 0x00, + 0x00, 0x00, 0x00, 0xF0, 0x10, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, + 0xFF, 0xFF, 0xFF, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xFF, 0xFF, + 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, + 0x38, 0x44, 0x44, 0x38, 0x44, + 0xFC, 0x4A, 0x4A, 0x4A, 0x34, // sharp-s or beta + 0x7E, 0x02, 0x02, 0x06, 0x06, + 0x02, 0x7E, 0x02, 0x7E, 0x02, + 0x63, 0x55, 0x49, 0x41, 0x63, + 0x38, 0x44, 0x44, 0x3C, 0x04, + 0x40, 0x7E, 0x20, 0x1E, 0x20, + 0x06, 0x02, 0x7E, 0x02, 0x02, + 0x99, 0xA5, 0xE7, 0xA5, 0x99, + 0x1C, 0x2A, 0x49, 0x2A, 0x1C, + 0x4C, 0x72, 0x01, 0x72, 0x4C, + 0x30, 0x4A, 0x4D, 0x4D, 0x30, + 0x30, 0x48, 0x78, 0x48, 0x30, + 0xBC, 0x62, 0x5A, 0x46, 0x3D, + 0x3E, 0x49, 0x49, 0x49, 0x00, + 0x7E, 0x01, 0x01, 0x01, 0x7E, + 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, + 0x44, 0x44, 0x5F, 0x44, 0x44, + 0x40, 0x51, 0x4A, 0x44, 0x40, + 0x40, 0x44, 0x4A, 0x51, 0x40, + 0x00, 0x00, 0xFF, 0x01, 0x03, + 0xE0, 0x80, 0xFF, 0x00, 0x00, + 0x08, 0x08, 0x6B, 0x6B, 0x08, + 0x36, 0x12, 0x36, 0x24, 0x36, + 0x06, 0x0F, 0x09, 0x0F, 0x06, + 0x00, 0x00, 0x18, 0x18, 0x00, + 0x00, 0x00, 0x10, 0x10, 0x00, + 0x30, 0x40, 0xFF, 0x01, 0x01, + 0x00, 0x1F, 0x01, 0x01, 0x1E, + 0x00, 0x19, 0x1D, 0x17, 0x12, + 0x00, 0x3C, 0x3C, 0x3C, 0x3C, + 0x00, 0x00, 0x00, 0x00, 0x00 // #255 NBSP +}; + +/**************************************************************** + * Function Name : clearDisplay + * Description : Clear the display memory buffer + * Returns : NONE. + * Params : NONE. + ****************************************************************/ +void clearDisplay() +{ + memset(screen, 0x00, DISPLAY_BUFF_SIZE); +} + +/**************************************************************** + * Function Name : display_Init_seq + * Description : Performs SSD1306 OLED Initialization Sequence + * Returns : NONE. + * Params : NONE. + ****************************************************************/ +void display_Init_seq() +{ + /* Add the reset code, If needed */ + + /* Send display OFF command */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_DISPLAY_OFF) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display OFF Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display OFF Command Failed\r\n"); +#endif + exit(1); + } + + /* Set display clock frequency */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_DISP_CLK) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display CLK Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display CLK Command Failed\r\n"); +#endif + exit(1); + } + + /* Send display CLK command parameter */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_DISPCLK_DIV) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display CLK Command Parameter Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display CLK Command Parameter Failed\r\n"); +#endif + exit(1); + } + + /* Set display multiplex */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_MULTIPLEX) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display MULT Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display MULT Command Failed\r\n"); +#endif + exit(1); + } + + /* Send display MULT command parameter */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_MULT_DAT) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display MULT Command Parameter Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display MULT Command Parameter Failed\r\n"); +#endif + exit(1); + } + + /* Set display OFFSET */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_DISP_OFFSET) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display OFFSET Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display OFFSET Command Failed\r\n"); +#endif + exit(1); + } + + /* Send display OFFSET command parameter */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_DISP_OFFSET_VAL) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display OFFSET Command Parameter Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display OFFSET Command Parameter Failed\r\n"); +#endif + exit(1); + } + + /* Set display START LINE - Check this command if something weird happens */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_DISP_START_LINE) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display START LINE Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display START LINE Command Failed\r\n"); +#endif + exit(1); + } + + /* Enable CHARGEPUMP*/ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_CONFIG_CHARGE_PUMP) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display CHARGEPUMP Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display CHARGEPUMP Command Failed\r\n"); +#endif + exit(1); + } + + /* Send display CHARGEPUMP command parameter */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_CHARGE_PUMP_EN) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display CHARGEPUMP Command Parameter Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display CHARGEPUMP Command Parameter Failed\r\n"); +#endif + exit(1); + } + + /* Set display MEMORYMODE */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_MEM_ADDR_MODE) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display MEMORYMODE Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display MEMORYMODE Command Failed\r\n"); +#endif + exit(1); + } + + /* Send display HORIZONTAL MEMORY ADDR MODE command parameter */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_HOR_MM) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display HORIZONTAL MEMORY ADDR MODE Command Parameter Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display HORIZONTAL MEMORY ADDR MODE Command Parameter Failed\r\n"); +#endif + exit(1); + } + + /* Set display COM */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_COMPINS) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display COM Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display COM Command Failed\r\n"); +#endif + exit(1); + } + + /* Send display COM command parameter */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_CONFIG_COM_PINS) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display COM Command Parameter Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display COM Command Parameter Failed\r\n"); +#endif + exit(1); + } + + /* Set display CONTRAST */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_CONTRAST) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display CONTRAST Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display CONTRAST Command Failed\r\n"); +#endif + exit(1); + } + + /* Send display CONTRAST command parameter */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_CONTRAST_VAL) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display CONTRAST Command Parameter Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display CONTRAST Command Parameter Failed\r\n"); +#endif + exit(1); + } + + /* Set display PRECHARGE */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_PRECHARGE) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display PRECHARGE Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display PRECHARGE Command Failed\r\n"); +#endif + exit(1); + } + + /* Send display PRECHARGE command parameter */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_PRECHARGE_VAL) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display PRECHARGE Command Parameter Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display PRECHARGE Command Parameter Failed\r\n"); +#endif + exit(1); + } + + /* Set display VCOMH */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_VCOMDETECT) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display VCOMH Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display VCOMH Command Failed\r\n"); +#endif + exit(1); + } + + /* Send display VCOMH command parameter */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_VCOMH_VAL) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display VCOMH Command Parameter Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display VCOMH Command Parameter Failed\r\n"); +#endif + exit(1); + } + + /* Set display ALL-ON */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_DISPLAYALLON_RESUME) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display ALL-ON Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display ALL-ON Command Failed\r\n"); +#endif + exit(1); + } + + /* Set display to NORMAL-DISPLAY */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_NORMAL_DISPLAY) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display NORMAL-DISPLAY Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display NORMAL-DISPLAY Command Failed\r\n"); +#endif + exit(1); + } + + /* Set display to DEACTIVATE_SCROLL */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_DEACTIVATE_SCROLL) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display DEACTIVATE_SCROLL Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display DEACTIVATE_SCROLL Command Failed\r\n"); +#endif + exit(1); + } + + /* Set display to TURN-ON */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_DISPLAYON) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display TURN-ON Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display TURN-ON Command Failed\r\n"); +#endif + exit(1); + } +} + +/**************************************************************** + * Function Name : display_normal + * Description : Normal display + * Returns : NONE. + * Params : NONE. + ****************************************************************/ +void display_normal() +{ + /* Set display SEG_REMAP */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SEG_REMAP) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display SEG_REMAP Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display SEG_REMAP Command Failed\r\n"); +#endif + exit(1); + } + + /* Set display COMSCANDEC */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_COMSCANDEC) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display DIR Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display DIR Command Failed\r\n"); +#endif + exit(1); + } +} + +/**************************************************************** + * Function Name : display_rotate + * Description : 180 degree rotation + * Returns : NONE. + * Params : NONE. + ****************************************************************/ +void display_rotate() +{ + /* Set display SEG_REMAP1 */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SEG_REMAP1) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display SEG_REMAP Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display SEG_REMAP Command Failed\r\n"); +#endif + exit(1); + } + + /* Set display COMSCANDEC1 */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_COMSCANDEC1) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display DIR Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display DIR Command Failed\r\n"); +#endif + exit(1); + } +} + +/**************************************************************** + * Function Name : transfer + * Description : Transfer the frame buffer onto the display + * Returns : NONE. + * Params : NONE. + ****************************************************************/ +void transfer() +{ + short loop_1 = 0, loop_2 = 0; + short index = 0x00; + for (loop_1 = 0; loop_1 < 1024; loop_1++) + { + chunk[0] = 0x40; + for(loop_2 = 1; loop_2 < 17; loop_2++) + chunk[loop_2] = screen[index++]; + if(i2c_multiple_writes(I2C_DEV_2.fd_i2c, 17, chunk) == 17) + { +#ifdef SSD1306_DBG + printf("Chunk written to RAM - Completed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Chunk written to RAM - Failed\r\n"); +#endif + exit(1); + } + + memset(chunk,0x00,17); + if(index == 1024) + break; + } +} + + +/**************************************************************** + * Function Name : Display + * Description : 1. Resets the column and page addresses. + * 2. Displays the contents of the memory buffer. + * Returns : NONE. + * Params : NONE. + * Note : Each new form can be preceded by a clearDisplay. + ****************************************************************/ +void Display() +{ + Init_Col_PG_addrs(SSD1306_COL_START_ADDR,SSD1306_COL_END_ADDR, + SSD1306_PG_START_ADDR,SSD1306_PG_END_ADDR); + transfer(); +} + +/**************************************************************** + * Function Name : Init_Col_PG_addrs + * Description : Sets the column and page, start and + * end addresses. + * Returns : NONE. + * Params : @col_start_addr: Column start address + * @col_end_addr: Column end address + * @pg_start_addr: Page start address + * @pg_end_addr: Page end address + ****************************************************************/ +void Init_Col_PG_addrs(unsigned char col_start_addr, unsigned char col_end_addr, + unsigned char pg_start_addr, unsigned char pg_end_addr) +{ + /* Send COLMN address setting command */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_COL_ADDR) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display COLMN Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display COLMN Command Failed\r\n"); +#endif + exit(1); + } + + /* Set COLMN start address */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, col_start_addr) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display COLMN Start Address param Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display COLMN Start Address param Failed\r\n"); +#endif + exit(1); + } + + /* Set COLMN end address */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, col_end_addr) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display COLMN End Address param Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display COLMN End Address param Failed\r\n"); +#endif + exit(1); + } + + /* Send PAGE address setting command */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_PAGEADDR) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display PAGE Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display PAGE Command Failed\r\n"); +#endif + exit(1); + } + + /* Set PAGE start address */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, pg_start_addr) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display PAGE Start Address param Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display PAGE Start Address param Failed\r\n"); +#endif + exit(1); + } + + /* Set PAGE end address */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, pg_end_addr) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display PAGE End Address param Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display PAGE End Address param Failed\r\n"); +#endif + exit(1); + } +} + +/**************************************************************** + * Function Name : setRotation + * Description : Set the display rotation + * Returns : NONE. + * Params : @x: Display rotation parameter + ****************************************************************/ +void setRotation(unsigned char x) +{ + _rotation = x & 3; + switch(_rotation) + { + case 0: + case 2: + _width = SSD1306_LCDWIDTH; + _height = SSD1306_LCDHEIGHT; + break; + case 1: + case 3: + _width = SSD1306_LCDHEIGHT; + _height = SSD1306_LCDWIDTH; + break; + } +} + +/**************************************************************** + * Function Name : startscrollright + * Description : Activate a right handed scroll for rows start + * through stop + * Returns : NONE. + * Params : @start: Start location + * @stop: Stop location + * HINT. : the display is 16 rows tall. To scroll the whole + * display, run: display.scrollright(0x00, 0x0F) + ****************************************************************/ +void startscrollright(unsigned char start, unsigned char stop) +{ + /* Send SCROLL horizontal right command */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_RIGHT_HORIZONTAL_SCROLL) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display HORIZONTAL SCROLL RIGHT Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display HORIZONTAL SCROLL RIGHT Command Failed\r\n"); +#endif + exit(1); + } + + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x00) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("HORI_SR Param_1 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("HORI_SR Param_1 Failed\r\n"); +#endif + exit(1); + } + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, start) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("HORI_SR Param_2 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("HORI_SR Param_2 Passed\r\n"); +#endif + exit(1); + } + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x00) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("HORI_SR Param_3 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("HORI_SR Param_3 Failed\r\n"); +#endif + exit(1); + } + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, stop) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("HORI_SR Param_4 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("HORI_SR Param_4 Passed\r\n"); +#endif + exit(1); + } + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x00) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("HORI_SR Param_5 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("HORI_SR Param_5 Failed\r\n"); +#endif + exit(1); + } + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0xFF) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("HORI_SR Param_6 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("HORI_SR Param_6 Passed\r\n"); +#endif + exit(1); + } + /* Send SCROLL Activate command */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_ACTIVATE_SCROLL) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("SCROLL Activate Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("SCROLL Activate Command Failed\r\n"); +#endif + exit(1); + } +} + +/**************************************************************** + * Function Name : startscrollleft + * Description : Activate a left handed scroll for rows start + * through stop + * Returns : NONE. + * Params : @start: Start location + * @stop: Stop location + * HINT. : the display is 16 rows tall. To scroll the whole + * display, run: display.scrollright(0x00, 0x0F) + ****************************************************************/ +void startscrollleft(unsigned char start, unsigned char stop) +{ + /* Send SCROLL horizontal left command */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_LEFT_HORIZONTAL_SCROLL) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display HORIZONTAL SCROLL LEFT Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display HORIZONTAL SCROLL LEFT Command Failed\r\n"); +#endif + exit(1); + } + + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x00) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("HORI_SR Param_1 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("HORI_SR Param_1 Failed\r\n"); +#endif + exit(1); + } + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, start) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("HORI_SR Param_2 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("HORI_SR Param_2 Passed\r\n"); +#endif + exit(1); + } + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x00) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("HORI_SR Param_3 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("HORI_SR Param_3 Failed\r\n"); +#endif + exit(1); + } + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, stop) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("HORI_SR Param_4 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("HORI_SR Param_4 Passed\r\n"); +#endif + exit(1); + } + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x00) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("HORI_SR Param_5 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("HORI_SR Param_5 Failed\r\n"); +#endif + exit(1); + } + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0xFF) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("HORI_SR Param_6 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("HORI_SR Param_6 Passed\r\n"); +#endif + exit(1); + } + /* Send SCROLL Activate command */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_ACTIVATE_SCROLL) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("SCROLL Activate Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("SCROLL Activate Command Failed\r\n"); +#endif + exit(1); + } +} + +/**************************************************************** + * Function Name : startscrolldiagright + * Description : Activate a diagonal scroll for rows start + * through stop + * Returns : NONE. + * Params : @start: Start location + * @stop: Stop location + * HINT. : the display is 16 rows tall. To scroll the whole + * display, run: display.scrollright(0x00, 0x0F) + ****************************************************************/ +void startscrolldiagright(unsigned char start, unsigned char stop) +{ + /* Send SCROLL diagonal right command */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_VERTICAL_SCROLL_AREA) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display DIAGONAL SCROLL RIGHT Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display DIAGONAL SCROLL RIGHT Command Failed\r\n"); +#endif + exit(1); + } + + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x00) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_1 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_1 Failed\r\n"); +#endif + exit(1); + } + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_LCDHEIGHT) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_2 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_2 Failed\r\n"); +#endif + exit(1); + } + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Cmd Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Cmd Failed\r\n"); +#endif + exit(1); + } + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x00) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_3 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_3 Failed\r\n"); +#endif + exit(1); + } + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, start) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_4 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_4 Failed\r\n"); +#endif + exit(1); + } + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x00) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_5 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_5 Failed\r\n"); +#endif + exit(1); + } + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, stop) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_6 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_6 Failed\r\n"); +#endif + exit(1); + } + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x01) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_5 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_5 Failed\r\n"); +#endif + exit(1); + } + + /* Send SCROLL Activate command */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_ACTIVATE_SCROLL) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("SCROLL Activate Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("SCROLL Activate Command Failed\r\n"); +#endif + exit(1); + } +} + +/**************************************************************** + * Function Name : startscrolldiagleft + * Description : Activate a diagonal scroll for rows start + * through stop + * Returns : NONE. + * Params : @start: Start location + * @stop: Stop location + * HINT. : the display is 16 rows tall. To scroll the whole + * display, run: display.scrollright(0x00, 0x0F) + ****************************************************************/ +void startscrolldiagleft(unsigned char start, unsigned char stop) +{ + /* Send SCROLL diagonal right command */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_VERTICAL_SCROLL_AREA) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display DIAGONAL SCROLL RIGHT Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display DIAGONAL SCROLL RIGHT Command Failed\r\n"); +#endif + exit(1); + } + + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x00) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_1 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_1 Failed\r\n"); +#endif + exit(1); + } + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_LCDHEIGHT) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_2 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_2 Failed\r\n"); +#endif + exit(1); + } + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Cmd Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Cmd Failed\r\n"); +#endif + exit(1); + } + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x00) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_3 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_3 Failed\r\n"); +#endif + exit(1); + } + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, start) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_4 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_4 Failed\r\n"); +#endif + exit(1); + } + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x00) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_5 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_5 Failed\r\n"); +#endif + exit(1); + } + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, stop) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_6 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_6 Failed\r\n"); +#endif + exit(1); + } + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x01) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_5 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_5 Failed\r\n"); +#endif + exit(1); + } + + /* Send SCROLL Activate command */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_ACTIVATE_SCROLL) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("SCROLL Activate Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("SCROLL Activate Command Failed\r\n"); +#endif + exit(1); + } +} + +/**************************************************************** + * Function Name : stopscroll + * Description : Stop scrolling + * Returns : NONE. + * Params : NONE. + ****************************************************************/ +void stopscroll() +{ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_DEACTIVATE_SCROLL) == I2C_TWO_BYTES) + { + printf("De-activate SCROLL Command Passed\r\n"); + } + else + { + printf("De-activate SCROLL Command Passed Failed\r\n"); + exit(1); + } +} + +/**************************************************************** + * Function Name : invertDisplay + * Description : Invert or Normalize the display + * Returns : NONE. + * Params : @i: 0x00 to Normal and 0x01 for Inverting + ****************************************************************/ +void invertDisplay(unsigned char i) +{ + if (i) + { + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_INVERTDISPLAY) == I2C_TWO_BYTES) + { + printf("Display Inverted - Passed\r\n"); + } + else + { + printf("Display Inverted - Failed\r\n"); + exit(1); + } + } + else + { + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_NORMAL_DISPLAY) == I2C_TWO_BYTES) + { + printf("Display Normal - Passed\r\n"); + } + else + { + printf("Display Normal - Failed\r\n"); + exit(1); + } + } +} + +/**************************************************************** + * Function Name : drawPixel + * Description : Draw a pixel + * Returns : -1 on error and 0 on success + * Params : @x: X - Co-ordinate + * @y: Y - Co-ordinate + * @color: Color + ****************************************************************/ +signed char drawPixel(short x, short y, short color) +{ + /* Return if co-ordinates are out of display dimension's range */ + if ((x < 0) || (x >= _width) || (y < 0) || (y >= _height)) + return -1; + switch(_rotation) + { + case 1: + SWAP(x,y); + x = _width - x - 1; + break; + case 2: + x = _width - x - 1; + y = _height - y - 1; + break; + case 3: + SWAP(x,y); + y = _height - y - 1; + break; + } + + /* x is the column */ + switch(color) + { + case WHITE: screen[x+ (y/8)*SSD1306_LCDWIDTH] |= (1 << (y&7)); break; + case BLACK: screen[x+ (y/8)*SSD1306_LCDWIDTH] &= ~(1 << (y&7)); break; + case INVERSE: screen[x+ (y/8)*SSD1306_LCDWIDTH] ^= (1 << (y&7)); break; + } + return 0; +} + +/**************************************************************** + * Function Name : writeLine + * Description : Bresenham's algorithm + * Returns : NONE + * Params : @x0: X0 Co-ordinate + * @y0: Y0 Co-ordinate + * @x1: X1 Co-ordinate + * @y1: Y1 Co-ordinate + * @color: Pixel color + ****************************************************************/ +void writeLine(short x0, short y0, short x1, short y1, short color) +{ + short steep = 0, dx = 0, dy = 0, err = 0, ystep = 0; + steep = abs(y1 - y0) > abs(x1 - x0); + if (steep) + { + SWAP(x0, y0); + SWAP(x1, y1); + } + + if (x0 > x1) + { + SWAP(x0, x1); + SWAP(y0, y1); + } + dx = x1 - x0; + dy = abs(y1 - y0); + + err = dx / 2; + + if (y0 < y1) + { + ystep = 1; + } else + { + ystep = -1; + } + + for (; x0<=x1; x0++) + { + if (steep) + { + drawPixel(y0, x0, color); + } else + { + drawPixel(x0, y0, color); + } + err -= dy; + if (err < 0) + { + y0 += ystep; + err += dx; + } + } +} + +/* (x,y) is topmost point; if unsure, calling function +should sort endpoints or call writeLine() instead */ +void drawFastVLine(short x, short y,short h, short color) +{ + //startWrite(); + writeLine(x, y, x, y+h-1, color); + //endWrite(); +} + +/* (x,y) is topmost point; if unsure, calling function +should sort endpoints or call writeLine() instead */ +void writeFastVLine(short x, short y, short h, short color) +{ + drawFastVLine(x, y, h, color); +} + +/* (x,y) is leftmost point; if unsure, calling function + should sort endpoints or call writeLine() instead */ +void drawFastHLine(short x, short y,short w, short color) +{ + //startWrite(); + writeLine(x, y, x+w-1, y, color); + //endWrite(); +} + +// (x,y) is leftmost point; if unsure, calling function +// should sort endpoints or call writeLine() instead +void writeFastHLine(short x, short y, short w, short color) +{ + drawFastHLine(x, y, w, color); +} + +/**************************************************************** + * Function Name : drawCircleHelper + * Description : Draw a.... + * Returns : NONE + * Params : @x: X Co-ordinate + * @y: Y Co-ordinate + * @w: Width + * @h: height + * @r: Corner radius + * @color: Pixel color + ****************************************************************/ +void drawCircleHelper( short x0, short y0, short r, unsigned char cornername, short color) +{ + short f = 1 - r; + short ddF_x = 1; + short ddF_y = -2 * r; + short x = 0; + short y = r; + + while (x= 0) + { + y--; + ddF_y += 2; + f += ddF_y; + } + x++; + ddF_x += 2; + f += ddF_x; + if (cornername & 0x4) + { + drawPixel(x0 + x, y0 + y, color); + drawPixel(x0 + y, y0 + x, color); + } + if (cornername & 0x2) + { + drawPixel(x0 + x, y0 - y, color); + drawPixel(x0 + y, y0 - x, color); + } + if (cornername & 0x8) + { + drawPixel(x0 - y, y0 + x, color); + drawPixel(x0 - x, y0 + y, color); + } + if (cornername & 0x1) + { + drawPixel(x0 - y, y0 - x, color); + drawPixel(x0 - x, y0 - y, color); + } + } +} + +/**************************************************************** + * Function Name : drawLine + * Description : Draw line between two points + * Returns : NONE + * Params : @x0: X0 Starting X Co-ordinate + * @y0: Y0 Starting Y Co-ordinate + * @x1: X1 Ending X Co-ordinate + * @y1: Y1 Ending Y Co-ordinate + * @color: Pixel color + ****************************************************************/ +void drawLine(short x0, short y0, short x1, short y1, short color) +{ + if(x0 == x1) + { + if(y0 > y1) + SWAP(y0, y1); + drawFastVLine(x0, y0, y1 - y0 + 1, color); + } + else if(y0 == y1) + { + if(x0 > x1) SWAP(x0, x1); + drawFastHLine(x0, y0, x1 - x0 + 1, color); + } + else + { + //startWrite(); + writeLine(x0, y0, x1, y1, color); + //endWrite(); + } +} + +/**************************************************************** + * Function Name : drawRect + * Description : Draw a rectangle + * Returns : NONE + * Params : @x: Corner X Co-ordinate + * @y: Corner Y Co-ordinate + * @w: Width in pixels + * @h: Height in pixels + * @color: Pixel color + ****************************************************************/ +void drawRect(short x, short y, short w, short h, short color) +{ + //startWrite(); + writeFastHLine(x, y, w, color); + writeFastHLine(x, y+h-1, w, color); + writeFastVLine(x, y, h, color); + writeFastVLine(x+w-1, y, h, color); + //endWrite(); +} + +/**************************************************************** + * Function Name : fillRect + * Description : Fill the rectangle + * Returns : NONE + * Params : @x: Starting X Co-ordinate + * @y: Starting Y Co-ordinate + * @w: Width in pixels + * @h: Height in pixels + * @color: Pixel color + ****************************************************************/ +void fillRect(short x, short y, short w, short h, short color) +{ + short i = 0; + //startWrite(); + for (i=x; i= 0) + { + y--; + ddF_y += 2; + f += ddF_y; + } + x++; + ddF_x += 2; + f += ddF_x; + + drawPixel(x0 + x, y0 + y, color); + drawPixel(x0 - x, y0 + y, color); + drawPixel(x0 + x, y0 - y, color); + drawPixel(x0 - x, y0 - y, color); + drawPixel(x0 + y, y0 + x, color); + drawPixel(x0 - y, y0 + x, color); + drawPixel(x0 + y, y0 - x, color); + drawPixel(x0 - y, y0 - x, color); + } + //endWrite(); +} + +/**************************************************************** + * Function Name : fillCircleHelper + * Description : Used to do circles and roundrects + * Returns : NONE + * Params : @x: Center X Co-ordinate + * @y: Center Y Co-ordinate + * @r: Radius in pixels + * @cornername: Corner radius in pixels + * @color: Pixel color + ****************************************************************/ +void fillCircleHelper(short x0, short y0, short r, unsigned char cornername, short delta, short color) +{ + + short f = 1 - r; + short ddF_x = 1; + short ddF_y = -2 * r; + short x = 0; + short y = r; + + while (x= 0) + { + y--; + ddF_y += 2; + f += ddF_y; + } + x++; + ddF_x += 2; + f += ddF_x; + + if (cornername & 0x1) + { + writeFastVLine(x0+x, y0-y, 2*y+1+delta, color); + writeFastVLine(x0+y, y0-x, 2*x+1+delta, color); + } + if (cornername & 0x2) + { + writeFastVLine(x0-x, y0-y, 2*y+1+delta, color); + writeFastVLine(x0-y, y0-x, 2*x+1+delta, color); + } + } +} + +/**************************************************************** + * Function Name : fillCircle + * Description : Fill the circle + * Returns : NONE + * Params : @x0: Center X Co-ordinate + * @y0: Center Y Co-ordinate + * @r: Radius in pixels + * @color: Pixel color + ****************************************************************/ +void fillCircle(short x0, short y0, short r, short color) +{ + //startWrite(); + writeFastVLine(x0, y0-r, 2*r+1, color); + fillCircleHelper(x0, y0, r, 3, 0, color); + //endWrite(); +} + +/**************************************************************** + * Function Name : drawTriangle + * Description : Draw a triangle + * Returns : NONE + * Params : @x0: Corner-1 X Co-ordinate + * @y0: Corner-1 Y Co-ordinate + * @x1: Corner-2 X Co-ordinate + * @y1: Corner-2 Y Co-ordinate + * @x2: Corner-3 X Co-ordinate + * @y2: Corner-3 Y Co-ordinate + * @color: Pixel color + ****************************************************************/ +void drawTriangle(short x0, short y0, short x1, short y1, short x2, short y2, short color) +{ + drawLine(x0, y0, x1, y1, color); + drawLine(x1, y1, x2, y2, color); + drawLine(x2, y2, x0, y0, color); +} + +/**************************************************************** + * Function Name : fillTriangle + * Description : Fill a triangle + * Returns : NONE + * Params : @x0: Corner-1 X Co-ordinate + * @y0: Corner-1 Y Co-ordinate + * @x1: Corner-2 X Co-ordinate + * @y1: Corner-2 Y Co-ordinate + * @x2: Corner-3 X Co-ordinate + * @y2: Corner-3 Y Co-ordinate + * @color: Pixel color + ****************************************************************/ +void fillTriangle(short x0, short y0, short x1, short y1, short x2, short y2, short color) +{ + short a, b, y, last, dx01, dy01, dx02, dy02, dx12, dy12; + int sa, sb; + + // Sort coordinates by Y order (y2 >= y1 >= y0) + if (y0 > y1) + { + SWAP(y0, y1); + SWAP(x0, x1); + } + if (y1 > y2) + { + SWAP(y2, y1); + SWAP(x2, x1); + } + if (y0 > y1) + { + SWAP(y0, y1); + SWAP(x0, x1); + } + + //startWrite(); + if(y0 == y2) + { // Handle awkward all-on-same-line case as its own thing + a = b = x0; + if(x1 < a) + a = x1; + else if(x1 > b) + b = x1; + if(x2 < a) + a = x2; + else if(x2 > b) + b = x2; + writeFastHLine(a, y0, b-a+1, color); + // endWrite(); + return; + } + + dx01 = x1 - x0; + dy01 = y1 - y0; + dx02 = x2 - x0; + dy02 = y2 - y0; + dx12 = x2 - x1; + dy12 = y2 - y1; + sa = 0; + sb = 0; + + // For upper part of triangle, find scanline crossings for segments + // 0-1 and 0-2. If y1=y2 (flat-bottomed triangle), the scanline y1 + // is included here (and second loop will be skipped, avoiding a /0 + // error there), otherwise scanline y1 is skipped here and handled + // in the second loop...which also avoids a /0 error here if y0=y1 + // (flat-topped triangle). + if(y1 == y2) + last = y1; // Include y1 scanline + else + last = y1-1; // Skip it + + for(y=y0; y<=last; y++) + { + a = x0 + sa / dy01; + b = x0 + sb / dy02; + sa += dx01; + sb += dx02; + /* longhand: + a = x0 + (x1 - x0) * (y - y0) / (y1 - y0); + b = x0 + (x2 - x0) * (y - y0) / (y2 - y0); + */ + if(a > b) + SWAP(a,b); + writeFastHLine(a, y, b-a+1, color); + } + + // For lower part of triangle, find scanline crossings for segments + // 0-2 and 1-2. This loop is skipped if y1=y2. + sa = dx12 * (y - y1); + sb = dx02 * (y - y0); + for(; y<=y2; y++) + { + a = x1 + sa / dy12; + b = x0 + sb / dy02; + sa += dx12; + sb += dx02; + /* longhand: + a = x1 + (x2 - x1) * (y - y1) / (y2 - y1); + b = x0 + (x2 - x0) * (y - y0) / (y2 - y0); + */ + if(a > b) + SWAP(a,b); + writeFastHLine(a, y, b-a+1, color); + } + //endWrite(); +} + +/**************************************************************** + * Function Name : drawRoundRect + * Description : Draw a rounded rectangle + * Returns : NONE + * Params : @x: X Co-ordinate + * @y: Y Co-ordinate + * @w: Width + * @h: height + * @r: Corner radius + * @color: Pixel color + ****************************************************************/ +void drawRoundRect(short x, short y, short w, short h, short r, short color) +{ + // smarter version + //startWrite(); + writeFastHLine(x+r , y , w-2*r, color); // Top + writeFastHLine(x+r , y+h-1, w-2*r, color); // Bottom + writeFastVLine(x , y+r , h-2*r, color); // Left + writeFastVLine(x+w-1, y+r , h-2*r, color); // Right + // draw four corners + drawCircleHelper(x+r , y+r , r, 1, color); + drawCircleHelper(x+w-r-1, y+r , r, 2, color); + drawCircleHelper(x+w-r-1, y+h-r-1, r, 4, color); + drawCircleHelper(x+r , y+h-r-1, r, 8, color); + //endWrite(); +} + +/**************************************************************** + * Function Name : fillRoundRect + * Description : Fill a rounded rectangle + * Returns : NONE + * Params : @x: X Co-ordinate + * @y: Y Co-ordinate + * @w: Width + * @h: height + * @r: Corner radius + * @color: Pixel color + ****************************************************************/ +void fillRoundRect(short x, short y, short w, short h, short r, short color) +{ + // smarter version + //startWrite(); + fillRect(x+r, y, w-2*r, h, color); + + // draw four corners + fillCircleHelper(x+w-r-1, y+r, r, 1, h-2*r-1, color); + fillCircleHelper(x+r , y+r, r, 2, h-2*r-1, color); + //endWrite(); +} + +/*---------------------------------------------------------------------------- + * BITMAP API's + ----------------------------------------------------------------------------*/ + +/**************************************************************** + * Function Name : drawBitmap + * Description : Draw a bitmap + * Returns : NONE + * Params : @x: X Co-ordinate + * @y: Y Co-ordinate + * @bitmap: bitmap to display + * @w: Width + * @h: height + * @color: Pixel color + ****************************************************************/ +void drawBitmap(short x, short y, const unsigned char bitmap[], short w, short h, short color) +{ + short byteWidth = 0, j = 0, i = 0; + unsigned char byte = 0; + byteWidth = (w + 7) / 8; // Bitmap scanline pad = whole byte + + for(j=0; j 0) ? s : 1; +} + +/**************************************************************** + * Function Name : setTextColor + * Description : Set text color + * Returns : @c - Color + ****************************************************************/ +void setTextColor(short c) +{ + // For 'transparent' background, we'll set the bg + // to the same as fg instead of using a flag + textcolor = textbgcolor = c; +} + +/**************************************************************** + * Function Name : setTextWrap + * Description : Wraps the text + * Returns : @w - enable or disbale wrap + ****************************************************************/ +void setTextWrap(bool w) +{ + wrap = w; +} + +/**************************************************************** + * Function Name : getRotation + * Description : Get the rotation value + * Returns : NONE. + ****************************************************************/ +unsigned char getRotation() +{ + return _rotation; +} + +/**************************************************************** + * Function Name : drawBitmap + * Description : Draw a character + * Returns : NONE + * Params : @x: X Co-ordinate + * @y: Y Co-ordinate + * @c: Character + * @size: Scaling factor + * @bg: Background color + * @color: Pixel color + ****************************************************************/ +void drawChar(short x, short y, unsigned char c, short color, short bg, unsigned char size) +{ + unsigned char line = 0, *bitmap = NULL, w = 0, h = 0, xx = 0, yy = 0, bits = 0, bit = 0; + char i = 0, j = 0, xo = 0, yo = 0; + short bo = 0, xo16 = 0, yo16 = 0; + GFXglyphPtr glyph; + if(!gfxFont) + { + // 'Classic' built-in font + if((x >= _width) || (y >= _height) || ((x + 6 * size - 1) < 0) || ((y + 8 * size - 1) < 0)) + return; + + // Handle 'classic' charset behavior + if(!_cp437 && (c >= 176)) + c++; + + // Char bitmap = 5 columns + for(i=0; i<5; i++ ) + { + line = pgm_read_byte(&ssd1306_font5x7[c * 5 + i]); + for(j=0; j<8; j++, line >>= 1) + { + if(line & 1) + { + if(size == 1) + drawPixel(x+i, y+j, color); + else + fillRect(x+i*size, y+j*size, size, size, color); + } + else if(bg != color) + { + if(size == 1) + drawPixel(x+i, y+j, bg); + else + fillRect(x+i*size, y+j*size, size, size, bg); + } + } + } + + // If opaque, draw vertical line for last column + if(bg != color) + { + if(size == 1) + writeFastVLine(x+5, y, 8, bg); + else + fillRect(x+5*size, y, size, 8*size, bg); + } + + } + // Custom font + else + { + // Character is assumed previously filtered by write() to eliminate + // newlines, returns, non-printable characters, etc. Calling + // drawChar() directly with 'bad' characters of font may cause mayhem! + + c -= (unsigned char)pgm_read_byte(&gfxFont->first); + glyph = &(((GFXglyphT *)pgm_read_pointer(&gfxFont->glyph))[c]); + bitmap = (unsigned char *)pgm_read_pointer(&gfxFont->bitmap); + bo = pgm_read_word(&glyph->bitmapOffset); + w = pgm_read_byte(&glyph->width); + h = pgm_read_byte(&glyph->height); + xo = pgm_read_byte(&glyph->xOffset); + yo = pgm_read_byte(&glyph->yOffset); + + if(size > 1) + { + xo16 = xo; + yo16 = yo; + } + + // Todo: Add character clipping here + + // NOTE: THERE IS NO 'BACKGROUND' COLOR OPTION ON CUSTOM FONTS. + // THIS IS ON PURPOSE AND BY DESIGN. The background color feature + // has typically been used with the 'classic' font to overwrite old + // screen contents with new data. This ONLY works because the + // characters are a uniform size; it's not a sensible thing to do with + // proportionally-spaced fonts with glyphs of varying sizes (and that + // may overlap). To replace previously-drawn text when using a custom + // font, use the getTextBounds() function to determine the smallest + // rectangle encompassing a string, erase the area with fillRect(), + // then draw new text. This WILL unfortunately 'blink' the text, but + // is unavoidable. Drawing 'background' pixels will NOT fix this, + // only creates a new set of problems. Have an idea to work around + // this (a canvas object type for MCUs that can afford the RAM and + // displays supporting setAddrWindow() and pushColors()), but haven't + // implemented this yet. + for(yy=0; yy _width)) + { + // Off right? + cursor_x = 0; // Reset x to zero, + cursor_y += textsize * 8; // advance y one line + } + drawChar(cursor_x, cursor_y, c, textcolor, textbgcolor, textsize); + cursor_x += textsize * 6; // Advance x one char + } + + } + else + { + // Custom font + if(c == '\n') + { + cursor_x = 0; + cursor_y += (short)textsize *(unsigned char)pgm_read_byte(&gfxFont->yAdvance); + } + else if(c != '\r') + { + first = pgm_read_byte(&gfxFont->first); + if((c >= first) && (c <= (unsigned char)pgm_read_byte(&gfxFont->last))) + { + glyph = &(((GFXglyphT*)pgm_read_pointer(&gfxFont->glyph))[c - first]); + w = pgm_read_byte(&glyph->width); + h = pgm_read_byte(&glyph->height); + if((w > 0) && (h > 0)) + { + // Is there an associated bitmap? + xo = (char)pgm_read_byte(&glyph->xOffset); // sic + if(wrap && ((cursor_x + textsize * (xo + w)) > _width)) + { + cursor_x = 0; + cursor_y += (short)textsize *(unsigned char)pgm_read_byte(&gfxFont->yAdvance); + } + drawChar(cursor_x, cursor_y, c, textcolor, textbgcolor, textsize); + } + cursor_x += (unsigned char)pgm_read_byte(&glyph->xAdvance) * (short)textsize; + } + } + } + return 1; +} + +/**************************************************************** + * Function Name : print + * Description : Base function for printing strings + * Returns : No. of characters printed + * Params : @buffer: Ptr to buffer containing the string + * @size: Length of the string. + ****************************************************************/ +short print(const unsigned char *buffer, short size) +{ + short n = 0; + while(size--) + { + if(oled_write(*buffer++)) + n++; + else + break; + } + return (n); +} + +/**************************************************************** + * Function Name : print_str + * Description : Print strings + * Returns : No. of characters printed + * Params : @strPtr: Ptr to buffer containing the string + ****************************************************************/ +short print_str(const unsigned char *strPtr) +{ + return print(strPtr, strlen(strPtr)); +} + +/**************************************************************** + * Function Name : println + * Description : Move to next line + * Returns : No. of characters printed + * Params : NONE. + ****************************************************************/ +short println() +{ + return print_str("\r\n"); +} + +/**************************************************************** + * Function Name : print_strln + * Description : Print strings and move to next line + * Returns : No. of characters printed + * Params : @strPtr: Ptr to buffer containing the string + ****************************************************************/ +short print_strln(const unsigned char *strPtr) +{ + short n = 0; + n = print(strPtr, strlen(strPtr)); + n += print_str("\r\n"); + return (n); +} + +/*---------------------------------------------------------------------------- + * NUMBERS HANDLING API's + ----------------------------------------------------------------------------*/ + +/**************************************************************** + * Function Name : printNumber + * Description : Base function to print unsigned numbers + * Returns : No. of characters printed + * Params : @n: Number + * @base: Base e.g. HEX, BIN... + ****************************************************************/ +short printNumber(unsigned long n, unsigned char base) +{ + unsigned long m = 0; + char c = 0; + char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte. + char *str = &buf[sizeof(buf) - 1]; + + *str = '\0'; + + // prevent crash if called with base == 1 + if(base < 2) + base = 10; + do + { + m = n; + n /= base; + c = m - base * n; + *--str = c < 10 ? c + '0' : c + 'A' - 10; + } + while(n); + //return oled_write((unsigned char)str); + return print_str(str); +} + +/**************************************************************** + * Function Name : printNumber_UL + * Description : Print unsigned long data types + * Returns : No. of characters printed + * Params : @n: Number + * @base: Base e.g. HEX, BIN... + ****************************************************************/ +short printNumber_UL(unsigned long n, int base) +{ + if(base == 0) + return oled_write(n); + else + return printNumber(n, base); +} + +/**************************************************************** + * Function Name : printNumber_UL_ln + * Description : Print unsigned long & advance to next line + * Returns : No. of characters printed + * Params : @n: Number + * @base: Base e.g. HEX, BIN... + ****************************************************************/ +short printNumber_UL_ln(unsigned long num, int base) +{ + short n = 0; + n = printNumber(num, base); + n += println(); + return (n); +} + +/**************************************************************** + * Function Name : printNumber_UI + * Description : Print unsigned int data types + * Returns : No. of characters printed + * Params : @n: Number + * @base: Base e.g. HEX, BIN... + ****************************************************************/ +short printNumber_UI(unsigned int n, int base) +{ + return printNumber((unsigned long) n, base); +} + +/**************************************************************** + * Function Name : printNumber_UI_ln + * Description : Print unsigned int & advance to next line + * Returns : No. of characters printed + * Params : @n: Number + * @base: Base e.g. HEX, BIN... + ****************************************************************/ +short printNumber_UI_ln(unsigned int n, int base) +{ + short a = 0; + a = printNumber((unsigned long) n, base); + a += println(); + return (a); +} + +/**************************************************************** + * Function Name : printNumber_UC + * Description : Print unsigned char data types + * Returns : No. of characters printed + * Params : @n: Number + * @base: Base e.g. HEX, BIN... + ****************************************************************/ +short printNumber_UC(unsigned char b, int base) +{ + return printNumber((unsigned long) b, base); +} + +/**************************************************************** + * Function Name : printNumber_UC_ln + * Description : Print unsigned char & advance to next line + * Returns : No. of characters printed + * Params : @n: Number + * @base: Base e.g. HEX, BIN... + ****************************************************************/ +short printNumber_UC_ln(unsigned char b, int base) +{ + short n = 0; + n = printNumber((unsigned long) b, base); + n += println(); + return (n); +} + +/**************************************************************** + * Function Name : printNumber_L + * Description : Print Long data types + * Returns : No. of characters printed + * Params : @n: Number + * @base: Base e.g. HEX, BIN... + ****************************************************************/ +short printNumber_L(long n, int base) +{ + int t = 0; + if(base == 0) + { + return oled_write(n); + } + else if(base == 10) + { + if(n < 0) + { + t = oled_write('-'); + n = -n; + return printNumber(n, 10) + t; + } + return printNumber(n, 10); + } + else + { + return printNumber(n, base); + } +} + +/**************************************************************** + * Function Name : printNumber_UC_ln + * Description : Print long & advance to next line + * Returns : No. of characters printed + * Params : @n: Number + * @base: Base e.g. HEX, BIN... + ****************************************************************/ +short printNumber_L_ln(long num, int base) +{ + short n = 0; + n = printNumber_L(num, base); + n += println(); + return n; +} + +/**************************************************************** + * Function Name : printNumber_I + * Description : Print int data types + * Returns : No. of characters printed + * Params : @n: Number + * @base: Base e.g. HEX, BIN... + ****************************************************************/ +short printNumber_I(int n, int base) +{ + return printNumber_L((long) n, base); +} + +/**************************************************************** + * Function Name : printNumber_I_ln + * Description : Print int & advance to next line + * Returns : No. of characters printed + * Params : @n: Number + * @base: Base e.g. HEX, BIN... + ****************************************************************/ +short printNumber_I_ln(int n, int base) +{ + short a = 0; + a = printNumber_L((long) n, base); + a += println(); + return a; +} + +/**************************************************************** + * Function Name : printFloat + * Description : Print floating Pt. No's. + * Returns : No. of characters printed + * Params : @n: Number + * @digits: Resolution + ****************************************************************/ +short printFloat(double number, unsigned char digits) +{ + unsigned char i = 0; + short n = 0; + unsigned long int_part = 0; + double remainder = 0.0; + int toPrint = 0; + + // Round correctly so that print(1.999, 2) prints as "2.00" + double rounding = 0.5; + + if(isnan(number)) + return print_str("nan"); + if(isinf(number)) + return print_str("inf"); + if(number > 4294967040.0) + return print_str("ovf"); // constant determined empirically + if(number < -4294967040.0) + return print_str("ovf"); // constant determined empirically + + // Handle negative numbers + if(number < 0.0) + { + n += oled_write('-'); + number = -number; + } + + + for(i = 0; i < digits; ++i) + rounding /= 10.0; + + number += rounding; + + // Extract the integer part of the number and print it + int_part = (unsigned long) number; + remainder = number - (double) int_part; + n += printNumber_UL(int_part,DEC); + + // Print the decimal point, but only if there are digits beyond + if(digits > 0) + { + n += print_str("."); + } + + // Extract digits from the remainder one at a time + while(digits-- > 0) + { + remainder *= 10.0; + toPrint = (int)remainder; + n += printNumber_I(toPrint,DEC); + remainder -= toPrint; + } + return n; +} + +/**************************************************************** + * Function Name : printFloat_ln + * Description : Print floating Pt. No and advance to next line + * Returns : No. of characters printed + * Params : @n: Number + * @digits: Resolution + ****************************************************************/ +short printFloat_ln(double num, int digits) +{ + short n = 0; + n = printFloat(num, digits); + n += println(); + return n; +} diff --git a/luci-app-ouad/src/SSD1306_OLED_Library/SSD1306_OLED.h b/luci-app-ouad/src/SSD1306_OLED_Library/SSD1306_OLED.h new file mode 100644 index 000000000..b7fcf39a1 --- /dev/null +++ b/luci-app-ouad/src/SSD1306_OLED_Library/SSD1306_OLED.h @@ -0,0 +1,204 @@ +/* + * MIT License + +Copyright (c) 2017 DeeplyEmbedded + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + * SSD1306_OLED.h + * + * Created on : Sep 21, 2017 + * Author : Vinay Divakar + * Website : www.deeplyembedded.org + */ + +#ifndef SSD1306_OLED_H_ +#define SSD1306_OLED_H_ + +/* Lib's */ +#include + +/* Find Min and Max - MACROS */ +#define MIN(a,b) (((a)<(b))?(a):(b)) +#define MAX(a,b) (((a)>(b))?(a):(b)) + +/* I2C Address of SSD1306 */ +#define SSD1306_OLED_ADDR 0x3C +#define DISPLAY_BUFF_SIZE (SSD1306_LCDWIDTH*SSD1306_LCDHEIGHT/8) + +/* COLOR MACROS */ +#define WHITE 1 +#define BLACK 0 +#define INVERSE 2 + +/* Number output format */ +#define DEC 10 +#define HEX 16 +#define OCT 8 +#define BIN 2 +#define DEFAULT 0 + +/*D/C# bit is '0' indicating that following + * byte is a command. '1' is for data + */ +#define SSD1306_CNTRL_CMD 0x00 +#define SSD1306_CNTRL_DATA 0x40 + + +/*-----------------------Enable the WxL of the Display ---------------------------*/ +//#define SSD1306_128_64 +#define SSD1306_128_32 +//#define SSD1306_96_16 +/*--------------------------------------------------------------------------------*/ + +/* LCD HxW i.e. 64x128 || WxL i.e. 128x64 */ +#if defined SSD1306_128_64 +#define SSD1306_LCDWIDTH 128 +#define SSD1306_LCDHEIGHT 64 +#endif +#if defined SSD1306_128_32 + #define SSD1306_LCDWIDTH 128 + #define SSD1306_LCDHEIGHT 32 +#endif +#if defined SSD1306_96_16 + #define SSD1306_LCDWIDTH 96 + #define SSD1306_LCDHEIGHT 16 +#endif + +/* SSD1306 Commands */ +#define SSD1306_DISPLAY_OFF 0xAE +#define SSD1306_SET_DISP_CLK 0xD5 +#define SSD1306_SET_MULTIPLEX 0xA8 +#define SSD1306_SET_DISP_OFFSET 0xD3 +#define SSD1306_SET_DISP_START_LINE 0x40 +#define SSD1306_CONFIG_CHARGE_PUMP 0x8D +#define SSD1306_SET_MEM_ADDR_MODE 0x20 +#define SSD1306_SEG_REMAP (0xA0 | 0x01) +#define SSD1306_SEG_REMAP1 0xA0 +#define SSD1306_SET_COMSCANDEC 0xC8 +#define SSD1306_SET_COMSCANDEC1 0xC0 +#define SSD1306_SET_COMPINS 0xDA +#define SSD1306_SET_CONTRAST 0x81 +#define SSD1306_SET_PRECHARGE 0xD9 +#define SSD1306_SET_VCOMDETECT 0xDB +#define SSD1306_DISPLAYALLON_RESUME 0xA4 +#define SSD1306_NORMAL_DISPLAY 0xA6 +#define SSD1306_DISPLAYON 0xAF +#define SSD1306_SET_COL_ADDR 0x21 +#define SSD1306_PAGEADDR 0x22 +#define SSD1306_INVERT_DISPLAY 0x01 +#define SSD1306_NORMALIZE_DISPLAY 0x00 + +/* SDD1306 Scroll Commands */ +#define SSD1306_SET_VERTICAL_SCROLL_AREA 0xA3 +#define SSD1306_ACTIVATE_SCROLL 0x2F +#define SSD1306_DEACTIVATE_SCROLL 0x2E +#define SSD1306_RIGHT_HORIZONTAL_SCROLL 0x26 +#define SSD1306_LEFT_HORIZONTAL_SCROLL 0x27 +#define SSD1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL 0x29 +#define SSD1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL 0x2A +#define SSD1306_INVERTDISPLAY 0xA7 + +/* SSD1306 Configuration Commands */ +#define SSD1306_DISPCLK_DIV 0x80 +#if defined SSD1306_128_64 +#define SSD1306_MULT_64 0x3F +#endif +#if defined SSD1306_128_32 + #define SSD1306_MULT_64 0x1F +#endif +#define SSD1306_MULT_64 0x1F +#define SSD1306_DISP_OFFSET_VAL 0x00 +#define SSD1306_COL_START_ADDR 0x00 //Reset to = 0 +#define SSD1306_COL_END_ADDR (SSD1306_LCDWIDTH - 1) //Reset to = 127 +#define SSD1306_PG_START_ADDR 0x00 +#define SSD1306_PG_END_ADDR 7 +#define SSD1306_CHARGE_PUMP_EN 0x14 +#if defined SSD1306_128_64 +#define SSD1306_CONFIG_COM_PINS 0x12 +#endif +#if defined SSD1306_128_32 + #define SSD1306_CONFIG_COM_PINS 0x02 +#endif +#define SSD1306_CONTRAST_VAL 0xCF //207 +#define SSD1306_PRECHARGE_VAL 0xF1 +#define SSD1306_VCOMH_VAL 0x40 +#define SSD1306_MULT_DAT (SSD1306_LCDHEIGHT - 1) +#define SSD1306_HOR_MM 0x00 + +/*SSD1306 Display API's */ +extern void clearDisplay(); +extern void display_Init_seq(); +extern void Display(); +extern void Init_Col_PG_addrs(unsigned char col_start_addr, unsigned char col_end_addr, + unsigned char pg_start_addr, unsigned char pg_end_addr); +extern void setRotation(unsigned char x); +extern void startscrollright(unsigned char start, unsigned char stop); +extern void startscrollleft(unsigned char start, unsigned char stop); +extern void startscrolldiagright(unsigned char start, unsigned char stop); +extern void startscrolldiagleft(unsigned char start, unsigned char stop); +extern void stopscroll(); +extern void setCursor(short x, short y); +extern short getCursorX(); +extern short getCursorY(); +extern unsigned char getRotation(); +extern void invertDisplay(unsigned char i); + +/*SSD1306 Graphics Handling API's */ +extern signed char drawPixel(short x, short y, short color); +extern void writeLine(short x0, short y0, short x1, short y1, short color); +extern void drawCircleHelper( short x0, short y0, short r, unsigned char cornername, short color); +extern void drawLine(short x0, short y0, short x1, short y1, short color); +extern void drawRect(short x, short y, short w, short h, short color); +extern void fillRect(short x, short y, short w, short h, short color); +extern void drawCircle(short x0, short y0, short r, short color); +extern void fillCircleHelper(short x0, short y0, short r, unsigned char cornername, short delta, short color); +extern void fillCircle(short x0, short y0, short r, short color); +extern void drawTriangle(short x0, short y0, short x1, short y1, short x2, short y2, short color); +extern void fillTriangle(short x0, short y0, short x1, short y1, short x2, short y2, short color); +extern void drawRoundRect(short x, short y, short w, short h, short r, short color); +extern void fillRoundRect(short x, short y, short w, short h, short r, short color); +extern void drawBitmap(short x, short y, const unsigned char bitmap[], short w, short h, short color); +extern short oled_write(unsigned char c); + +/*SSD1306 Text and Character Handling API's */ +extern void setTextSize(unsigned char s); +extern void setTextColor(short c); +extern void setTextWrap(bool w); +extern void drawChar(short x, short y, unsigned char c, short color, short bg, unsigned char size); +extern short print_str(const unsigned char *strPtr); +extern short println(); +extern short print_strln(const unsigned char *strPtr); + +/*SSD1306 Number Handling API's */ +extern short printNumber(unsigned long n, unsigned char base); +extern short printNumber_UL(unsigned long n, int base); +extern short printNumber_UL_ln(unsigned long num, int base); +extern short printNumber_UI(unsigned int n, int base); +extern short printNumber_UI_ln(unsigned int n, int base); +extern short printNumber_UC(unsigned char b, int base); +extern short printNumber_UC_ln(unsigned char b, int base); +extern short printNumber_L(long n, int base); +extern short printNumber_L_ln(long num, int base); +extern short printNumber_I(int n, int base); +extern short printNumber_I_ln(int n, int base); +extern short printFloat(double number, unsigned char digits); +extern short printFloat_ln(double num, int digits); +#endif /* SSD1306_OLED_H_ */ + diff --git a/luci-app-ouad/src/SSD1306_OLED_Library/gfxfont.h b/luci-app-ouad/src/SSD1306_OLED_Library/gfxfont.h new file mode 100644 index 000000000..e66128a88 --- /dev/null +++ b/luci-app-ouad/src/SSD1306_OLED_Library/gfxfont.h @@ -0,0 +1,18 @@ +#ifndef _GFXFONT_H_ +#define _GFXFONT_H_ + +typedef struct { // Data stored PER GLYPH + unsigned short bitmapOffset; // Pointer into GFXfont->bitmap + unsigned char width, height; // Bitmap dimensions in pixels + unsigned char xAdvance; // Distance to advance cursor (x axis) + char xOffset, yOffset; // Dist from cursor pos to UL corner +} GFXglyphT, *GFXglyphPtr; + +typedef struct { // Data stored for FONT AS A WHOLE: + unsigned char *bitmap; // Glyph bitmaps, concatenated + GFXglyphPtr glyph; // Glyph array + unsigned char first, last; // ASCII extents + unsigned char yAdvance; // Newline distance (y axis) +} GFXfontT, *GFXfontPtr; + +#endif // _GFXFONT_H_