summaryrefslogtreecommitdiffhomepage
path: root/contrib
diff options
context:
space:
mode:
Diffstat (limited to 'contrib')
-rw-r--r--contrib/package/ffluci-splash/Makefile43
-rw-r--r--contrib/package/ffluci-splash/ipkg/conffiles1
-rw-r--r--contrib/package/ffluci-splash/src/luci-splash.lua173
-rw-r--r--contrib/package/ffluci-splash/src/luci-splash/htdocs/cgi-bin/index.cgi39
-rw-r--r--contrib/package/ffluci-splash/src/luci-splash/htdocs/index.html10
-rw-r--r--contrib/package/ffluci-splash/src/luci_splash.cron2
-rw-r--r--contrib/package/ffluci-splash/src/luci_splash.init88
-rw-r--r--contrib/package/ffluci-splash/src/luci_splash.uci2
-rw-r--r--contrib/package/ffluci-splash/src/luci_splash_httpd.conf1
-rw-r--r--contrib/package/ffluci-system-addons/Makefile32
-rw-r--r--contrib/package/ffluci-system-addons/src/hotplug.d-20-aliases24
-rw-r--r--contrib/package/ffluci-system-addons/src/root.crontab3
-rw-r--r--contrib/package/ffluci-system-addons/src/run-parts18
-rw-r--r--contrib/package/ffluci/Makefile74
-rw-r--r--contrib/package/ffluci/ipkg/conffiles2
-rwxr-xr-xcontrib/package/ffluci/ipkg/ffluci.postinst9
-rw-r--r--contrib/package/haserl-lua/Makefile40
-rw-r--r--contrib/package/haserl-lua/patches/200-bytecode-header-luci12
-rw-r--r--contrib/package/lua-luci/Makefile151
-rw-r--r--contrib/package/lua-luci/patches/010-lua-5.1.3-lnum-full-260308.patch3806
-rw-r--r--contrib/package/lua-luci/patches/020-shared_liblua.patch139
-rw-r--r--contrib/package/lua-luci/patches/030-archindependent-bytecode.patch113
-rw-r--r--contrib/package/lua-luci/patches/100-no_readline.patch53
-rw-r--r--contrib/package/luaposix/Makefile44
24 files changed, 4879 insertions, 0 deletions
diff --git a/contrib/package/ffluci-splash/Makefile b/contrib/package/ffluci-splash/Makefile
new file mode 100644
index 000000000..d3e98af18
--- /dev/null
+++ b/contrib/package/ffluci-splash/Makefile
@@ -0,0 +1,43 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=ffluci-splash
+PKG_VERSION:=0.1
+PKG_RELEASE:=1
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+PKG_INSTALL_DIR:=$(PKG_BUILD_DIR)/ipkg-install
+PKG_BUILD_DEPENDS:=lua-luci
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/ffluci-splash
+ SECTION:=admin
+ CATEGORY:=Administration
+ SUBMENU:=FFLuCI
+ DEPENDS:=+ffluci +iptables-mod-nat +lua-luci
+ TITLE:=FFLuCI DHCP-Splash
+endef
+
+define Build/Compile
+endef
+
+define Package/ffluci-splash/install
+ $(INSTALL_DIR) $(1)/usr/lib/luci-splash/htdocs/cgi-bin
+ $(INSTALL_DIR) $(1)/etc/config
+ $(INSTALL_DIR) $(1)/etc/cron.minutely
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_DIR) $(1)/usr/sbin
+
+ $(CP) -a ./src/luci-splash/* $(1)/usr/lib/luci-splash/ -R
+ $(INSTALL_BIN) ./src/luci-splash/htdocs/cgi-bin/index.cgi $(1)/usr/lib/luci-splash/htdocs/cgi-bin
+ $(INSTALL_BIN) ./src/luci_splash.init $(1)/etc/init.d/luci_splash
+ $(INSTALL_BIN) ./src/luci-splash.lua $(1)/usr/sbin/luci-splash
+
+ $(INSTALL_BIN) -a ./src/luci_splash.cron $(1)/etc/cron.minutely/luci_splash
+ $(CP) -a ./src/luci_splash.uci $(1)/etc/config/luci_splash
+ $(CP) -a ./src/luci_splash_httpd.conf $(1)/etc/
+
+ $(CP) -a ./ipkg/conffiles $(1)/CONTROL/conffiles
+endef
+
+$(eval $(call BuildPackage,ffluci-splash))
diff --git a/contrib/package/ffluci-splash/ipkg/conffiles b/contrib/package/ffluci-splash/ipkg/conffiles
new file mode 100644
index 000000000..dcbe1ad37
--- /dev/null
+++ b/contrib/package/ffluci-splash/ipkg/conffiles
@@ -0,0 +1 @@
+/etc/config/luci_splash \ No newline at end of file
diff --git a/contrib/package/ffluci-splash/src/luci-splash.lua b/contrib/package/ffluci-splash/src/luci-splash.lua
new file mode 100644
index 000000000..54c32add6
--- /dev/null
+++ b/contrib/package/ffluci-splash/src/luci-splash.lua
@@ -0,0 +1,173 @@
+#!/usr/bin/lua
+package.path = "/usr/lib/lua/?.lua;/usr/lib/lua/?/init.lua;" .. package.path
+package.cpath = "/usr/lib/lua/?.so;" .. package.cpath
+
+require("ffluci.http")
+require("ffluci.sys")
+require("ffluci.model.uci")
+
+-- Init state session
+uci = ffluci.model.uci.Session("/var/state")
+
+
+-- Parse stdin and do something
+function main(argv)
+ local cmd = argv[1]
+ local arg = argv[2]
+
+ if not cmd then
+ print("Usage: " .. argv[0] .. " <status|add|remove|sync> [MAC]")
+ os.exit(1)
+ elseif cmd == "status" then
+ if not arg then
+ os.exit(1)
+ end
+
+ if iswhitelisted(arg) then
+ print("whitelisted")
+ os.exit(0)
+ end
+
+ if haslease(arg) then
+ print("lease")
+ os.exit(0)
+ end
+
+ print("unknown")
+ os.exit(0)
+ elseif cmd == "add" then
+ if not arg then
+ os.exit(1)
+ end
+
+ if not haslease(arg) then
+ add_lease(arg)
+ else
+ print("already leased!")
+ os.exit(2)
+ end
+ os.exit(0)
+ elseif cmd == "remove" then
+ if not cmd[2] then
+ os.exit(1)
+ end
+
+ remove_lease(arg)
+ os.exit(0)
+ elseif cmd == "sync" then
+ sync()
+ os.exit(0)
+ end
+end
+
+-- Add a lease to state and invoke add_rule
+function add_lease(mac)
+ local key = uci:add("luci_splash", "lease")
+ uci:set("luci_splash", key, "mac", mac)
+ uci:set("luci_splash", key, "start", os.time())
+ add_rule(mac)
+end
+
+
+-- Remove a lease from state and invoke remove_rule
+function remove_lease(mac)
+ mac = mac:lower()
+
+ for k, v in pairs(uci:show("luci_splash").luci_splash) do
+ if v.mac:lower() == mac then
+ remove_rule(mac)
+ uci:del("luci_splash", k)
+ end
+ end
+end
+
+
+-- Add an iptables rule
+function add_rule(mac)
+ return os.execute("iptables -t nat -I luci_splash_leases -m mac --mac-source '"..mac.."' -j RETURN")
+end
+
+
+-- Remove an iptables rule
+function remove_rule(mac)
+ return os.execute("iptables -t nat -D luci_splash_leases -m mac --mac-source '"..mac.."' -j RETURN")
+end
+
+
+-- Check whether a MAC-Address is listed in the lease state list
+function haslease(mac)
+ mac = mac:lower()
+
+ for k, v in pairs(uci:show("luci_splash").luci_splash) do
+ if v[".type"] == "lease" and v.mac and v.mac:lower() == mac then
+ return true
+ end
+ end
+
+ return false
+end
+
+
+-- Check whether a MAC-Address is whitelisted
+function iswhitelisted(mac)
+ mac = mac:lower()
+
+ for k, v in pairs(uci:show("luci_splash").luci_splash) do
+ if v[".type"] == "whitelist" and v.mac and v.mac:lower() == mac then
+ return true
+ end
+ end
+
+ return false
+end
+
+
+-- Returns a list of MAC-Addresses for which a rule is existing
+function listrules()
+ local cmd = "iptables -t nat -L luci_splash_leases | grep RETURN |"
+ cmd = cmd .. "egrep -io [0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+"
+ return ffluci.util.split(ffluci.sys.exec(cmd))
+end
+
+
+-- Synchronise leases, remove abandoned rules
+function sync()
+ local written = {}
+ local time = os.time()
+
+ -- Current leases in state files
+ local leases = uci:show("luci_splash").luci_splash
+
+ -- Convert leasetime to seconds
+ local leasetime = tonumber(uci:get("luci_splash", "general", "leasetime")) * 3600
+
+ -- Clean state file
+ uci:revert("luci_splash")
+
+
+ -- For all leases
+ for k, v in pairs(uci:show("luci_splash")) do
+ if v[".type"] == "lease" then
+ if os.difftime(time, tonumber(v.start)) > leasetime then
+ -- Remove expired
+ remove_rule(v.mac)
+ else
+ -- Rewrite state
+ local n = uci:add("luci_splash", "lease")
+ uci:set("luci_splash", n, "mac", v.mac)
+ uci:set("luci_splash", n, "start", v.start)
+ written[v.mac] = 1
+ end
+ end
+ end
+
+
+ -- Delete rules without state
+ for i, r in ipairs(listrules()) do
+ if #r > 0 and not written[r] then
+ remove_rule(r)
+ end
+ end
+end
+
+main(arg) \ No newline at end of file
diff --git a/contrib/package/ffluci-splash/src/luci-splash/htdocs/cgi-bin/index.cgi b/contrib/package/ffluci-splash/src/luci-splash/htdocs/cgi-bin/index.cgi
new file mode 100644
index 000000000..4cbddc0c5
--- /dev/null
+++ b/contrib/package/ffluci-splash/src/luci-splash/htdocs/cgi-bin/index.cgi
@@ -0,0 +1,39 @@
+#!/usr/bin/haserl --shell=luac
+package.path = "/usr/lib/lua/?.lua;/usr/lib/lua/?/init.lua;" .. package.path
+package.cpath = "/usr/lib/lua/?.so;" .. package.cpath
+
+require("ffluci.http")
+require("ffluci.sys")
+require("ffluci.model.uci")
+
+local srv
+local ip = ffluci.http.remote_addr()
+for k, v in pairs(ffluci.model.uci.show("network").network) do
+ if v[".type"] == "interface" and v.ipaddr then
+ local p = ffluci.sys.net.mask4prefix(v.netmask)
+ if ffluci.sys.net.belongs(ip, v.ipaddr, p) then
+ srv = v.ipaddr
+ break
+ end
+ end
+end
+
+if not srv then
+ ffluci.http.textheader()
+ return print("Unable to detect network settings!")
+end
+
+local action = "splash"
+
+local mac = ffluci.sys.net.ip4mac(ip)
+if not mac then
+ action = "unknown"
+end
+
+local status = ffluci.sys.exec("luci-splash status "..mac)
+
+if status == "whitelisted" or status == "lease" then
+ action = "allowed"
+end
+
+ffluci.http.redirect("http://" .. srv .. "/cgi-bin/luci-splash/" .. action) \ No newline at end of file
diff --git a/contrib/package/ffluci-splash/src/luci-splash/htdocs/index.html b/contrib/package/ffluci-splash/src/luci-splash/htdocs/index.html
new file mode 100644
index 000000000..58387a5fe
--- /dev/null
+++ b/contrib/package/ffluci-splash/src/luci-splash/htdocs/index.html
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="refresh" content="0; URL=/cgi-bin/index.cgi" />
+</head>
+<body style="background-color: black">
+<a style="color: white; text-decoration: none" href="/cgi-bin/index.cgi">FFLuCI - Freifunk Lua Configuration Interface</a>
+</body>
+</html> \ No newline at end of file
diff --git a/contrib/package/ffluci-splash/src/luci_splash.cron b/contrib/package/ffluci-splash/src/luci_splash.cron
new file mode 100644
index 000000000..eae429474
--- /dev/null
+++ b/contrib/package/ffluci-splash/src/luci_splash.cron
@@ -0,0 +1,2 @@
+#!/bin/sh
+[ "$(date +%M | cut -c2)" == "5" ] && luci-splash sync \ No newline at end of file
diff --git a/contrib/package/ffluci-splash/src/luci_splash.init b/contrib/package/ffluci-splash/src/luci_splash.init
new file mode 100644
index 000000000..a7bb4abeb
--- /dev/null
+++ b/contrib/package/ffluci-splash/src/luci_splash.init
@@ -0,0 +1,88 @@
+#!/bin/sh /etc/rc.common
+START=70
+
+iface_add() {
+ local cfg="$1"
+
+ config_get net "$cfg" network
+ [ -n "$net" ] || return 0
+
+ config_get iface "$net" ifname
+ [ -n "$iface" ] || return 0
+ iface="${iface%%:*}"
+
+ config_get ipaddr "$net" ipaddr
+ [ -n "$ipaddr" ] || return 0
+
+ config_get netmask "$net" netmask
+ [ -n "$netmask" ] || return 0
+
+ eval "$(ipcalc.sh $ipaddr $netmask)"
+
+ iptables -t nat -A luci_splash -i "$iface" -s "$IP/$PREFIX" -j luci_splash_portal
+ iptables -t nat -A luci_splash_portal -i "$iface" -s "$IP/$PREFIX" -d "$ipaddr" -p tcp --dport 80 -j RETURN
+}
+
+blacklist_add() {
+ local cfg="$1"
+
+ config_get mac "$cfg" mac
+ [ -n "$mac" ] && iptables -t nat -A luci_splash_portal -m mac --mac-source "$mac" -j DROP
+}
+
+whitelist_add() {
+ local cfg="$1"
+
+ config_get mac "$cfg" mac
+ [ -n "$mac" ] && iptables -t nat -A luci_splash_portal -m mac --mac-source "$mac" -j RETURN
+}
+
+start() {
+ ### Read chains from config
+ include /lib/network
+ scan_interfaces
+ config_load luci_splash
+
+ ### Create subchains
+ iptables -t nat -N luci_splash
+ iptables -t nat -N luci_splash_portal
+ iptables -t nat -N luci_splash_leases
+
+ ### Build the main and portal rule
+ config_foreach blacklist_add blacklist
+ config_foreach whitelist_add whitelist
+ config_foreach iface_add iface
+
+ ### Build the portal rule
+ iptables -t nat -A luci_splash_portal -p udp --dport 53 -j RETURN
+ iptables -t nat -A luci_splash_portal -j luci_splash_leases
+
+ ### Build the leases rule
+ iptables -t nat -A luci_splash_leases -p tcp --dport 80 -j REDIRECT --to-ports 8082
+ iptables -t nat -A luci_splash_leases -j DROP
+
+ ### Start the splash httpd
+ httpd -c /etc/luci_splash_httpd.conf -p 8082 -h /usr/lib/luci-splash/htdocs
+
+ ### Sync leases
+ /usr/lib/luci-splash/sync.lua
+
+ ### Hook in the chain
+ iptables -t nat -A prerouting_rule -j luci_splash
+}
+
+stop() {
+ ### Hook out the chain
+ iptables -t nat -D prerouting_rule -j luci_splash
+
+ ### Clear subchains
+ iptables -t nat -F luci_splash_leases
+ iptables -t nat -F luci_splash_portal
+ iptables -t nat -F luci_splash
+
+ ### Delete subchains
+ iptables -t nat -X luci_splash_leases
+ iptables -t nat -X luci_splash_portal
+ iptables -t nat -X luci_splash
+}
+
diff --git a/contrib/package/ffluci-splash/src/luci_splash.uci b/contrib/package/ffluci-splash/src/luci_splash.uci
new file mode 100644
index 000000000..c4cfef5dd
--- /dev/null
+++ b/contrib/package/ffluci-splash/src/luci_splash.uci
@@ -0,0 +1,2 @@
+config core general
+ option leasetime 1 \ No newline at end of file
diff --git a/contrib/package/ffluci-splash/src/luci_splash_httpd.conf b/contrib/package/ffluci-splash/src/luci_splash_httpd.conf
new file mode 100644
index 000000000..6007e80db
--- /dev/null
+++ b/contrib/package/ffluci-splash/src/luci_splash_httpd.conf
@@ -0,0 +1 @@
+E404:index.html \ No newline at end of file
diff --git a/contrib/package/ffluci-system-addons/Makefile b/contrib/package/ffluci-system-addons/Makefile
new file mode 100644
index 000000000..3d38bd36c
--- /dev/null
+++ b/contrib/package/ffluci-system-addons/Makefile
@@ -0,0 +1,32 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=ffluci-system-addons
+PKG_VERSION:=0.1
+PKG_RELEASE:=1
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+PKG_INSTALL_DIR:=$(PKG_BUILD_DIR)/ipkg-install
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/ffluci-splash
+ SECTION:=admin
+ CATEGORY:=Administration
+ SUBMENU:=FFLuCI
+ TITLE:=FFLuCI System Addons for Kamikaze
+endef
+
+define Build/Compile
+endef
+
+define Package/ffluci-system-addons/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_DIR) $(1)/etc/crontabs
+ $(INSTALL_DIR) $(1)/etc/hotplug.d/iface
+
+ $(INSTALL_BIN) ./src/run-parts $(1)/usr/bin
+ $(CP) ./src/root.crontab $(1)/etc/crontabs/root
+ $(CP) ./src/hotplug.d-20-aliases $(1)/etc/hotplug.d/iface/20-aliases
+endef
+
+$(eval $(call BuildPackage,ffluci-system-addons))
diff --git a/contrib/package/ffluci-system-addons/src/hotplug.d-20-aliases b/contrib/package/ffluci-system-addons/src/hotplug.d-20-aliases
new file mode 100644
index 000000000..b9986e3aa
--- /dev/null
+++ b/contrib/package/ffluci-system-addons/src/hotplug.d-20-aliases
@@ -0,0 +1,24 @@
+add_aliases() {
+ local config="$1"
+
+ config_get base "$INTERFACE" ifname
+ config_get iface "$config" ifname
+ config_get ipaddr "$config" ipaddr
+ config_get auto "$config" auto
+
+ [ "${iface%%:*}" == "$base" -a "$iface" != "$base" ] && {
+ case "$auto" in
+ 1|on|enabled) setup_interface "$iface" "$config";;
+ *) return 1;;
+ esac
+ }
+}
+
+
+case "$ACTION" in
+ ifup)
+ include /lib/network
+ scan_interfaces
+ config_foreach "add_aliases" interface
+ ;;
+esac
diff --git a/contrib/package/ffluci-system-addons/src/root.crontab b/contrib/package/ffluci-system-addons/src/root.crontab
new file mode 100644
index 000000000..6e2e417dc
--- /dev/null
+++ b/contrib/package/ffluci-system-addons/src/root.crontab
@@ -0,0 +1,3 @@
+0-59/1 * * * * /usr/bin/run-parts /etc/cron.minutely
+0 * * * * /usr/bin/run-parts /etc/cron.hourly
+0 0 * * * /usr/bin/run-parts /etc/cron.daily
diff --git a/contrib/package/ffluci-system-addons/src/run-parts b/contrib/package/ffluci-system-addons/src/run-parts
new file mode 100644
index 000000000..0f0cbbdf5
--- /dev/null
+++ b/contrib/package/ffluci-system-addons/src/run-parts
@@ -0,0 +1,18 @@
+#!/bin/sh
+set +e
+
+if [ $# -lt 1 ]; then
+ echo "Usage: run-parts <dir>"
+ exit 1
+fi
+
+if [ ! -d $1 ]; then
+ echo "Not a directory: $1"
+ exit 1
+fi
+
+for i in $1/*; do
+ [ -x $i ] && $i
+done
+
+exit 0 \ No newline at end of file
diff --git a/contrib/package/ffluci/Makefile b/contrib/package/ffluci/Makefile
new file mode 100644
index 000000000..1c45695bb
--- /dev/null
+++ b/contrib/package/ffluci/Makefile
@@ -0,0 +1,74 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=ffluci
+PKG_REV:=HEAD
+PKG_VERSION:=0.3+svn$(PKG_REV)
+PKG_RELEASE:=1
+PKG_BRANCH:=trunk
+
+PKG_SOURCE_PROTO:=svn
+PKG_SOURCE_VERSION:=$(PKG_REV)
+PKG_SOURCE_URL:=https://dev.leipzig.freifunk.net/svn/ff-luci/$(PKG_BRANCH)
+PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
+PKG_SOURCE:=$(PKG_SOURCE_SUBDIR).tar.gz
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+PKG_INSTALL_DIR:=$(PKG_BUILD_DIR)/ipkg-install
+
+PKG_BUILD_DEPENDS:=lua-luci
+
+MAKE_ACTION:=compile LUAC=$(BUILD_DIR_HOST)/lua-luci/luac
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/ffluci
+ SECTION:=admin
+ CATEGORY:=Administration
+ TITLE:=FFLuCI
+ SUBMENU:=FFLuCI
+ DEPENDS:=+luaposix +haserl-lua +ffluci-system-addons
+ MAINTAINER:=Steven Barth <steven-at-midlink-dot-org>
+endef
+
+define Build/Configure
+endef
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR)/core $(MAKE_ACTION)
+ $(MAKE) -C $(PKG_BUILD_DIR)/module/admin-core $(MAKE_ACTION)
+ $(MAKE) -C $(PKG_BUILD_DIR)/module/public-core $(MAKE_ACTION)
+endef
+
+define Package/ffluci/install
+ $(INSTALL_DIR) $(1)/usr/lib/lua/ffluci
+ $(INSTALL_DIR) $(1)/www/cgi-bin
+ $(INSTALL_DIR) $(1)/www/ffluci
+ $(INSTALL_DIR) $(1)/etc/config
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_DIR) $(1)/sbin
+ $(INSTALL_DIR) $(1)/etc/hotplug.d/iface
+
+ $(CP) $(PKG_BUILD_DIR)/core/dist/* $(1)/usr/lib/lua/ -R
+ $(CP) $(PKG_BUILD_DIR)/core/contrib/uci/* $(1)/etc/config/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/core/contrib/ffluci $(1)/www/cgi-bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/core/contrib/ffluci-upload $(1)/www/cgi-bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/core/contrib/index.cgi $(1)/www/cgi-bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/core/contrib/index.html $(1)/www
+
+ $(CP) $(PKG_BUILD_DIR)/themes/fledermaus/contrib/media $(1)/www/ffluci/ -R
+
+ $(CP) $(PKG_BUILD_DIR)/module/admin-core/dist/* $(1)/usr/lib/lua/ffluci/ -R
+ $(CP) $(PKG_BUILD_DIR)/module/admin-core/contrib/uci/luci_fw $(1)/etc/config/luci_fw
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/module/admin-core/contrib/init.d/luci_fw $(1)/etc/init.d/luci_fw
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/module/admin-core/contrib/ffluci-flash $(1)/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/module/admin-core/contrib/luci-splash $(1)/www/cgi-bin
+
+ $(CP) $(PKG_BUILD_DIR)/module/public-core/dist/* $(1)/usr/lib/lua/ffluci/ -R
+ $(CP) $(PKG_BUILD_DIR)/module/public-core/contrib/media $(1)/www/ffluci/ -R
+
+ $(CP) -a ./ipkg/ffluci.postinst $(1)/CONTROL/postinst
+ $(CP) -a ./ipkg/conffiles $(1)/CONTROL/conffiles
+ rm $(DL_DIR)/$(PKG_SOURCE)
+endef
+
+$(eval $(call BuildPackage,ffluci)) \ No newline at end of file
diff --git a/contrib/package/ffluci/ipkg/conffiles b/contrib/package/ffluci/ipkg/conffiles
new file mode 100644
index 000000000..098dbf904
--- /dev/null
+++ b/contrib/package/ffluci/ipkg/conffiles
@@ -0,0 +1,2 @@
+/etc/config/luci
+/etc/config/luci_fw \ No newline at end of file
diff --git a/contrib/package/ffluci/ipkg/ffluci.postinst b/contrib/package/ffluci/ipkg/ffluci.postinst
new file mode 100755
index 000000000..b6703dc06
--- /dev/null
+++ b/contrib/package/ffluci/ipkg/ffluci.postinst
@@ -0,0 +1,9 @@
+#!/bin/sh
+PATTERNS='/cgi-bin/ffluci/admin:root:$p$root /cgi-bin/ffluci-upload:root:$p$root'
+
+for i in $PATTERNS
+do
+ grep "$i" ${IPKG_INSTROOT}/etc/httpd.conf >/dev/null 2>/dev/null || echo "$i" >> ${IPKG_INSTROOT}/etc/httpd.conf
+done
+
+[ -n ${IPKG_INSTROOT} ] || /etc/init.d/httpd restart
diff --git a/contrib/package/haserl-lua/Makefile b/contrib/package/haserl-lua/Makefile
new file mode 100644
index 000000000..ed4279bfd
--- /dev/null
+++ b/contrib/package/haserl-lua/Makefile
@@ -0,0 +1,40 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=haserl-lua
+PKG_VERSION:=0.9.24
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=http://dev.leipzig.freifunk.net/svn/ff-luci/trunk/contrib/package-source/ \
+ http://firmware.freifunk-halle.net/ffluci/package-source/
+PKG_MD5SUM:=b004005594b84e35839b1d5c330f8e03
+
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/haserl-lua
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=A CGI wrapper to embed shell scripts in HTML documents
+ URL:=http://haserl.sourceforge.net/
+ DEPENDS:=+liblua-luci
+endef
+
+CONFIGURE_ARGS += \
+ --with-lua
+
+define Package/haserl-lua/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(STRIP) $(PKG_BUILD_DIR)/src/haserl
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/haserl $(1)/usr/bin/
+ echo "Replaces: haserl" >> $(1)/CONTROL/control
+ echo "Conflicts: haserl" >> $(1)/CONTROL/control
+endef
+
+$(eval $(call BuildPackage,haserl-lua))
diff --git a/contrib/package/haserl-lua/patches/200-bytecode-header-luci b/contrib/package/haserl-lua/patches/200-bytecode-header-luci
new file mode 100644
index 000000000..c93fe7ae6
--- /dev/null
+++ b/contrib/package/haserl-lua/patches/200-bytecode-header-luci
@@ -0,0 +1,12 @@
+diff -ur haserl-0.9.23.orig/src/haserl_lualib.inc haserl-0.9.23/src/haserl_lualib.inc
+--- haserl-0.9.23.orig/src/haserl_lualib.inc 2008-04-05 16:40:35.000000000 +0200
++++ haserl-0.9.23/src/haserl_lualib.inc 2008-04-05 16:41:37.000000000 +0200
+@@ -1,7 +1,7 @@
+ /* This file was automatically generated from haserl_lualib.lua. DO NOT EDIT */
+
+ static const unsigned char haserl_lualib[] = {
+- 27, 76,117, 97, 81, 0, 1, 4, 4, 4, 8, 0, 19, 0, 0, 0,
++ 27, 76,117, 97, 81, 0, 1, 4, 4, 4, 8, 4, 19, 0, 0, 0,
+ 64,104, 97,115,101,114,108, 95,108,117, 97,108,105, 98, 46,108,
+ 117, 97, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 16,
+ 0, 0, 0, 10, 0, 0, 0, 74, 0, 0, 0,138, 0, 0, 0,135,
diff --git a/contrib/package/lua-luci/Makefile b/contrib/package/lua-luci/Makefile
new file mode 100644
index 000000000..ffa26853d
--- /dev/null
+++ b/contrib/package/lua-luci/Makefile
@@ -0,0 +1,151 @@
+#
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=lua-luci
+PKG_VERSION:=5.1.3
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=http://dev.leipzig.freifunk.net/svn/ff-luci/trunk/contrib/package-source/ \
+ http://firmware.freifunk-halle.net/ffluci/package-source/
+PKG_MD5SUM:=98b12c767a5eed92169b01537e988c7f
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+PKG_INSTALL_DIR:=$(PKG_BUILD_DIR)/ipkg-install
+
+X_HOST_DIR:=$(BUILD_DIR_HOST)/$(PKG_NAME)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/lua-luci/Default
+ SUBMENU:=LUA
+ SECTION:=lang
+ CATEGORY:=Languages
+ TITLE:=LUA programming language
+ URL:=http://www.lua.org/
+endef
+
+define Package/lua-luci/Default/description
+ Lua is a powerful light-weight programming language designed for extending
+ applications. Lua is also frequently used as a general-purpose, stand-alone
+ language. Lua is free software.
+endef
+
+define Package/liblua-luci
+$(call Package/lua-luci/Default)
+ SUBMENU:=
+ SECTION:=libs
+ CATEGORY:=Libraries
+ TITLE+= (libraries)
+endef
+
+define Package/liblua-luci/description
+$(call Package/lua-luci/Default/description)
+ This package contains the LUA shared libraries, needed by other programs.
+endef
+
+define Package/lua-luci
+$(call Package/lua-luci/Default)
+ DEPENDS:=+liblua-luci
+ TITLE+= (interpreter)
+endef
+
+define Package/lua-luci/description
+$(call Package/lua-luci/Default/description)
+ This package contains the LUA language interpreter.
+endef
+
+define Package/luac-luci
+$(call Package/lua-luci/Default)
+ DEPENDS:=+liblua-luci
+ TITLE+= (compiler)
+endef
+
+define Package/luac/description
+$(call Package/lua-luci/Default/description)
+ This package contains the LUA language compiler.
+endef
+
+define Package/lua-luci-examples
+$(call Package/lua-luci/Default)
+ DEPENDS:=lua-luci
+ TITLE+= (examples)
+endef
+
+define Package/lua-luci-examples/description
+$(call Package/lua-luci/Default/description)
+ This package contains LUA language examples.
+endef
+
+define Build/Configure
+endef
+
+define Build/Compile
+ cp $(PKG_BUILD_DIR)/src $(PKG_BUILD_DIR)/src-host -R
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ CC="$(TARGET_CROSS)gcc" \
+ LD="$(TARGET_CROSS)ld" \
+ AR="$(TARGET_CROSS)ar rcu" \
+ RANLIB="$(TARGET_CROSS)ranlib" \
+ INSTALL_ROOT=/usr \
+ MYCFLAGS="$(TARGET_CPPFLAGS) $(TARGET_CFLAGS)" \
+ MYLDFLAGS="$(TARGET_LDFLAGS)" \
+ PKG_VERSION=$(PKG_VERSION) \
+ all linux
+ rm -rf $(PKG_INSTALL_DIR)
+ mkdir -p $(PKG_INSTALL_DIR)
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ INSTALL_TOP="$(PKG_INSTALL_DIR)/usr" \
+ install
+ $(MAKE) -C $(PKG_BUILD_DIR)/src-host luac-host
+ mkdir -p $(X_HOST_DIR)
+ cp $(PKG_BUILD_DIR)/src-host/luac-host $(X_HOST_DIR)/luac
+endef
+
+define Build/InstallDev
+ mkdir -p $(1)/usr/include
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/lua{,lib,conf}.h $(1)/usr/include/
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/lauxlib.h $(1)/usr/include/
+ $(CP) $(PKG_INSTALL_DIR)/usr/include/lnum_config.h $(1)/usr/include/
+ mkdir -p $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/liblua.{a,so.*} $(1)/usr/lib/
+ ln -sf liblua.so.$(PKG_VERSION) $(1)/usr/lib/liblua.so
+ ln -sf liblua.so.$(PKG_VERSION) $(1)/usr/lib/liblualib.so
+endef
+
+define Package/liblua-luci/install
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/liblua.so.* $(1)/usr/lib/
+ echo "Replaces: liblua" >> $(1)/CONTROL/control
+ echo "Conflicts: liblua" >> $(1)/CONTROL/control
+endef
+
+define Package/lua-luci/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/lua $(1)/usr/bin/
+ echo "Replaces: lua" >> $(1)/CONTROL/control
+ echo "Conflicts: lua" >> $(1)/CONTROL/control
+endef
+
+define Package/luac-luci/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/luac $(1)/usr/bin/
+ echo "Replaces: luac" >> $(1)/CONTROL/control
+ echo "Conflicts: luac" >> $(1)/CONTROL/control
+endef
+
+define Package/lua-luci-examples/install
+ $(INSTALL_DIR) $(1)/usr/share/lua/examples
+ $(INSTALL_DATA) $(PKG_BUILD_DIR)/test/*.lua \
+ $(1)/usr/share/lua/examples/
+endef
+
+$(eval $(call BuildPackage,liblua-luci))
+$(eval $(call BuildPackage,lua-luci))
+$(eval $(call BuildPackage,luac-luci))
+$(eval $(call BuildPackage,lua-luci-examples))
diff --git a/contrib/package/lua-luci/patches/010-lua-5.1.3-lnum-full-260308.patch b/contrib/package/lua-luci/patches/010-lua-5.1.3-lnum-full-260308.patch
new file mode 100644
index 000000000..a9cc95f75
--- /dev/null
+++ b/contrib/package/lua-luci/patches/010-lua-5.1.3-lnum-full-260308.patch
@@ -0,0 +1,3806 @@
+diff -urN --exclude=.svn --exclude=.DS_Store ../lua-5.1.3/src/Makefile lua-5.1.3-patched/src/Makefile
+--- ../lua-5.1.3/src/Makefile 2008-01-19 21:37:58.000000000 +0200
++++ lua-5.1.3-patched/src/Makefile 2008-03-26 13:05:24.000000000 +0200
+@@ -25,7 +25,7 @@
+ LUA_A= liblua.a
+ CORE_O= lapi.o lcode.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o \
+ lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o \
+- lundump.o lvm.o lzio.o
++ lundump.o lvm.o lzio.o lnum.o
+ LIB_O= lauxlib.o lbaselib.o ldblib.o liolib.o lmathlib.o loslib.o ltablib.o \
+ lstrlib.o loadlib.o linit.o
+
+@@ -148,6 +148,7 @@
+ lmathlib.o: lmathlib.c lua.h luaconf.h lauxlib.h lualib.h
+ lmem.o: lmem.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \
+ ltm.h lzio.h lmem.h ldo.h
++lnum.o: lnum.c lua.h llex.h lnum.h
+ loadlib.o: loadlib.c lua.h luaconf.h lauxlib.h lualib.h
+ lobject.o: lobject.c lua.h luaconf.h ldo.h lobject.h llimits.h lstate.h \
+ ltm.h lzio.h lmem.h lstring.h lgc.h lvm.h
+@@ -179,4 +180,18 @@
+ print.o: print.c ldebug.h lstate.h lua.h luaconf.h lobject.h llimits.h \
+ ltm.h lzio.h lmem.h lopcodes.h lundump.h
+
++luaconf.h: lnum_config.h
++lapi.c: lnum.h
++lauxlib.c: llimits.h
++lbaselib.c: llimits.h lobject.h lapi.h
++lcode.c: lnum.h
++liolib.c: lnum.h llex.h
++llex.c: lnum.h
++lnum.h: lobject.h
++lobject.c: llex.h lnum.h
++ltable.c: lnum.h
++lua.c: llimits.h
++lvm.c: llex.h lnum.h
++print.c: lnum.h
++
+ # (end of Makefile)
+diff -urN --exclude=.svn --exclude=.DS_Store ../lua-5.1.3/src/lapi.c lua-5.1.3-patched/src/lapi.c
+--- ../lua-5.1.3/src/lapi.c 2008-01-03 17:20:39.000000000 +0200
++++ lua-5.1.3-patched/src/lapi.c 2008-03-19 09:52:15.000000000 +0200
+@@ -28,7 +28,7 @@
+ #include "ltm.h"
+ #include "lundump.h"
+ #include "lvm.h"
+-
++#include "lnum.h"
+
+
+ const char lua_ident[] =
+@@ -242,12 +242,13 @@
+
+ LUA_API int lua_type (lua_State *L, int idx) {
+ StkId o = index2adr(L, idx);
+- return (o == luaO_nilobject) ? LUA_TNONE : ttype(o);
++ return (o == luaO_nilobject) ? LUA_TNONE : ttype_ext(o);
+ }
+
+
+ LUA_API const char *lua_typename (lua_State *L, int t) {
+ UNUSED(L);
++ lua_assert( t!= LUA_TINT );
+ return (t == LUA_TNONE) ? "no value" : luaT_typenames[t];
+ }
+
+@@ -265,6 +266,14 @@
+ }
+
+
++LUA_API int lua_isinteger (lua_State *L, int idx) {
++ TValue tmp;
++ lua_Integer dum;
++ const TValue *o = index2adr(L, idx);
++ return tonumber(o,&tmp) && (ttisint(o) || tt_integer_valued(o,&dum));
++}
++
++
+ LUA_API int lua_isstring (lua_State *L, int idx) {
+ int t = lua_type(L, idx);
+ return (t == LUA_TSTRING || t == LUA_TNUMBER);
+@@ -310,31 +319,66 @@
+ }
+
+
+-
+ LUA_API lua_Number lua_tonumber (lua_State *L, int idx) {
+ TValue n;
+ const TValue *o = index2adr(L, idx);
+- if (tonumber(o, &n))
++ if (tonumber(o, &n)) {
++#ifdef LNUM_COMPLEX
++ if (nvalue_img(o) != 0)
++ luaG_runerror(L, "expecting a real number");
++#endif
+ return nvalue(o);
+- else
+- return 0;
++ }
++ return 0;
+ }
+
+
+ LUA_API lua_Integer lua_tointeger (lua_State *L, int idx) {
+ TValue n;
++ /* Lua 5.1 documented behaviour is to return nonzero for non-integer:
++ * "If the number is not an integer, it is truncated in some non-specified way."
++ * I would suggest to change this, to return 0 for anything that would
++ * not fit in 'lua_Integer'.
++ */
++#ifdef LUA_COMPAT_TOINTEGER
++ /* Lua 5.1 compatible */
+ const TValue *o = index2adr(L, idx);
+ if (tonumber(o, &n)) {
+- lua_Integer res;
+- lua_Number num = nvalue(o);
+- lua_number2integer(res, num);
+- return res;
++ lua_Integer i;
++ lua_Number d;
++ if (ttisint(o)) return ivalue(o);
++ d= nvalue_fast(o);
++# ifdef LNUM_COMPLEX
++ if (nvalue_img_fast(o) != 0)
++ luaG_runerror(L, "expecting a real number");
++# endif
++ lua_number2integer(i, d);
++ return i;
+ }
+- else
+- return 0;
++#else
++ /* New suggestion */
++ const TValue *o = index2adr(L, idx);
++ if (tonumber(o, &n)) {
++ lua_Integer i;
++ if (ttisint(o)) return ivalue(o);
++ if (tt_integer_valued(o,&i)) return i;
++ }
++#endif
++ return 0;
+ }
+
+
++#ifdef LNUM_COMPLEX
++LUA_API lua_Complex lua_tocomplex (lua_State *L, int idx) {
++ TValue tmp;
++ const TValue *o = index2adr(L, idx);
++ if (tonumber(o, &tmp))
++ return nvalue_complex(o);
++ return 0;
++}
++#endif
++
++
+ LUA_API int lua_toboolean (lua_State *L, int idx) {
+ const TValue *o = index2adr(L, idx);
+ return !l_isfalse(o);
+@@ -365,6 +409,7 @@
+ case LUA_TSTRING: return tsvalue(o)->len;
+ case LUA_TUSERDATA: return uvalue(o)->len;
+ case LUA_TTABLE: return luaH_getn(hvalue(o));
++ case LUA_TINT:
+ case LUA_TNUMBER: {
+ size_t l;
+ lua_lock(L); /* `luaV_tostring' may create a new string */
+@@ -427,6 +472,8 @@
+ }
+
+
++/* 'lua_pushnumber()' may lose accuracy on integers, 'lua_pushinteger' will not.
++ */
+ LUA_API void lua_pushnumber (lua_State *L, lua_Number n) {
+ lua_lock(L);
+ setnvalue(L->top, n);
+@@ -435,12 +482,22 @@
+ }
+
+
+-LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) {
++LUA_API void lua_pushinteger (lua_State *L, lua_Integer i) {
++ lua_lock(L);
++ setivalue(L->top, i);
++ api_incr_top(L);
++ lua_unlock(L);
++}
++
++
++#ifdef LNUM_COMPLEX
++LUA_API void lua_pushcomplex (lua_State *L, lua_Complex v) {
+ lua_lock(L);
+- setnvalue(L->top, cast_num(n));
++ setnvalue_complex( L->top, v );
+ api_incr_top(L);
+ lua_unlock(L);
+ }
++#endif
+
+
+ LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) {
+@@ -570,7 +627,7 @@
+ lua_lock(L);
+ o = index2adr(L, idx);
+ api_check(L, ttistable(o));
+- setobj2s(L, L->top, luaH_getnum(hvalue(o), n));
++ setobj2s(L, L->top, luaH_getint(hvalue(o), n));
+ api_incr_top(L);
+ lua_unlock(L);
+ }
+@@ -598,6 +655,9 @@
+ case LUA_TUSERDATA:
+ mt = uvalue(obj)->metatable;
+ break;
++ case LUA_TINT:
++ mt = G(L)->mt[LUA_TNUMBER];
++ break;
+ default:
+ mt = G(L)->mt[ttype(obj)];
+ break;
+@@ -688,7 +748,7 @@
+ api_checknelems(L, 1);
+ o = index2adr(L, idx);
+ api_check(L, ttistable(o));
+- setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top-1);
++ setobj2t(L, luaH_setint(L, hvalue(o), n), L->top-1);
+ luaC_barriert(L, hvalue(o), L->top-1);
+ L->top--;
+ lua_unlock(L);
+@@ -722,7 +782,7 @@
+ break;
+ }
+ default: {
+- G(L)->mt[ttype(obj)] = mt;
++ G(L)->mt[ttype_ext(obj)] = mt;
+ break;
+ }
+ }
+@@ -1083,3 +1143,32 @@
+ return name;
+ }
+
++
++/* Help function for 'luaB_tonumber()', avoids multiple str->number
++ * conversions for Lua "tonumber()".
++ *
++ * Also pushes floating point numbers with integer value as integer, which
++ * can be used by 'tonumber()' in scripts to bring values back to integer
++ * realm.
++ *
++ * Note: The 'back to integer realm' is _not_ to affect string conversions:
++ * 'tonumber("4294967295.1")' should give a floating point value, although
++ * the value would be 4294967296 (and storable in int64 realm).
++ */
++int lua_pushvalue_as_number (lua_State *L, int idx)
++{
++ const TValue *o = index2adr(L, idx);
++ TValue tmp;
++ lua_Integer i;
++ if (ttisnumber(o)) {
++ if ( (!ttisint(o)) && tt_integer_valued(o,&i)) {
++ lua_pushinteger( L, i );
++ return 1;
++ }
++ } else if (!tonumber(o, &tmp)) {
++ return 0;
++ }
++ if (ttisint(o)) lua_pushinteger( L, ivalue(o) );
++ else lua_pushnumber( L, nvalue_fast(o) );
++ return 1;
++}
+diff -urN --exclude=.svn --exclude=.DS_Store ../lua-5.1.3/src/lapi.h lua-5.1.3-patched/src/lapi.h
+--- ../lua-5.1.3/src/lapi.h 2007-12-27 15:02:25.000000000 +0200
++++ lua-5.1.3-patched/src/lapi.h 2008-03-03 12:47:53.000000000 +0200
+@@ -13,4 +13,6 @@
+
+ LUAI_FUNC void luaA_pushobject (lua_State *L, const TValue *o);
+
++int lua_pushvalue_as_number (lua_State *L, int idx);
++
+ #endif
+Binary files ../lua-5.1.3/src/lapi.o and lua-5.1.3-patched/src/lapi.o differ
+diff -urN --exclude=.svn --exclude=.DS_Store ../lua-5.1.3/src/lauxlib.c lua-5.1.3-patched/src/lauxlib.c
+--- ../lua-5.1.3/src/lauxlib.c 2008-01-21 15:20:51.000000000 +0200
++++ lua-5.1.3-patched/src/lauxlib.c 2008-03-19 09:51:27.000000000 +0200
+@@ -23,7 +23,7 @@
+ #include "lua.h"
+
+ #include "lauxlib.h"
+-
++#include "llimits.h"
+
+ #define FREELIST_REF 0 /* free list of references */
+
+@@ -66,7 +66,7 @@
+
+
+ static void tag_error (lua_State *L, int narg, int tag) {
+- luaL_typerror(L, narg, lua_typename(L, tag));
++ luaL_typerror(L, narg, tag==LUA_TINT ? "integer" : lua_typename(L, tag));
+ }
+
+
+@@ -188,8 +188,8 @@
+
+ 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);
++ if (d == 0 && !lua_isinteger(L, narg)) /* avoid extra test when d is not 0 */
++ tag_error(L, narg, LUA_TINT);
+ return d;
+ }
+
+@@ -200,6 +200,16 @@
+ }
+
+
++#ifdef LNUM_COMPLEX
++LUALIB_API lua_Complex luaL_checkcomplex (lua_State *L, int narg) {
++ lua_Complex c = lua_tocomplex(L, narg);
++ if (c == 0 && !lua_isnumber(L, narg)) /* avoid extra test when c is not 0 */
++ tag_error(L, narg, LUA_TNUMBER);
++ return c;
++}
++#endif
++
++
+ LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) {
+ if (!lua_getmetatable(L, obj)) /* no metatable? */
+ return 0;
+diff -urN --exclude=.svn --exclude=.DS_Store ../lua-5.1.3/src/lauxlib.h lua-5.1.3-patched/src/lauxlib.h
+--- ../lua-5.1.3/src/lauxlib.h 2007-12-27 15:02:25.000000000 +0200
++++ lua-5.1.3-patched/src/lauxlib.h 2008-03-12 23:15:22.000000000 +0200
+@@ -57,6 +57,12 @@
+ 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);
++#define luaL_checkint32(L,narg) ((int)luaL_checkinteger(L,narg))
++#define luaL_optint32(L,narg,def) ((int)luaL_optinteger(L,narg,def))
++
++#ifdef LNUM_COMPLEX
++ LUALIB_API lua_Complex (luaL_checkcomplex) (lua_State *L, int narg);
++#endif
+
+ 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);
+Binary files ../lua-5.1.3/src/lauxlib.o and lua-5.1.3-patched/src/lauxlib.o differ
+diff -urN --exclude=.svn --exclude=.DS_Store ../lua-5.1.3/src/lbaselib.c lua-5.1.3-patched/src/lbaselib.c
+--- ../lua-5.1.3/src/lbaselib.c 2008-01-20 15:53:22.000000000 +0200
++++ lua-5.1.3-patched/src/lbaselib.c 2008-03-13 10:42:50.000000000 +0200
+@@ -18,7 +18,9 @@
+
+ #include "lauxlib.h"
+ #include "lualib.h"
+-
++#include "llimits.h"
++#include "lobject.h"
++#include "lapi.h"
+
+
+
+@@ -54,20 +56,25 @@
+ 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));
++ if (lua_isnumber(L, 1)) { /* numeric string, or a number */
++ lua_pushvalue_as_number(L,1); /* API extension (not to lose accuracy here) */
+ return 1;
+- }
++ }
+ }
+ else {
+ const char *s1 = luaL_checkstring(L, 1);
+ char *s2;
+- unsigned long n;
++ unsigned LUA_INTEGER n;
+ luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range");
+- n = strtoul(s1, &s2, base);
++ n = lua_str2ul(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? */
++
++ /* Push as number, there needs to be separate 'luaB_tointeger' for
++ * when the caller wants to preserve the bits (matters if unsigned
++ * values are used).
++ */
+ lua_pushnumber(L, (lua_Number)n);
+ return 1;
+ }
+@@ -144,7 +151,7 @@
+ luaL_checktype(L, 2, LUA_TTABLE);
+ getfunc(L, 0);
+ lua_pushvalue(L, 2);
+- if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) {
++ if (lua_isnumber(L, 1) && lua_tointeger(L, 1) == 0) {
+ /* change environment of current thread */
+ lua_pushthread(L);
+ lua_insert(L, -2);
+@@ -209,7 +216,7 @@
+ return 1;
+ }
+ default: {
+- lua_pushnumber(L, res);
++ lua_pushinteger(L, res);
+ return 1;
+ }
+ }
+@@ -629,6 +636,8 @@
+ luaL_register(L, "_G", base_funcs);
+ lua_pushliteral(L, LUA_VERSION);
+ lua_setglobal(L, "_VERSION"); /* set global _VERSION */
++ lua_pushliteral(L, LUA_LNUM);
++ lua_setglobal(L, "_LNUM"); /* "[complex] double|float|ldouble int32|int64" */
+ /* `ipairs' and `pairs' need auxliliary functions as upvalues */
+ auxopen(L, "ipairs", luaB_ipairs, ipairsaux);
+ auxopen(L, "pairs", luaB_pairs, luaB_next);
+Binary files ../lua-5.1.3/src/lbaselib.o and lua-5.1.3-patched/src/lbaselib.o differ
+diff -urN --exclude=.svn --exclude=.DS_Store ../lua-5.1.3/src/lcode.c lua-5.1.3-patched/src/lcode.c
+--- ../lua-5.1.3/src/lcode.c 2007-12-28 17:32:23.000000000 +0200
++++ lua-5.1.3-patched/src/lcode.c 2008-03-19 10:02:51.000000000 +0200
+@@ -22,13 +22,18 @@
+ #include "lopcodes.h"
+ #include "lparser.h"
+ #include "ltable.h"
++#include "lnum.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);
++ int ek=
++#ifdef LNUM_COMPLEX
++ (e->k == VKNUM2) ||
++#endif
++ (e->k == VKINT) || (e->k == VKNUM);
++ return (ek && e->t == NO_JUMP && e->f == NO_JUMP);
+ }
+
+
+@@ -231,12 +236,16 @@
+ 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));
++ if (ttype(idx)==LUA_TNUMBER) {
++ luai_normalize(idx);
++ lua_assert( ttype(idx)==LUA_TINT ); /* had no fraction */
++ }
++ if (ttisint(idx)) {
++ lua_assert(luaO_rawequalObj(&fs->f->k[ivalue(idx)], v));
++ return cast_int(ivalue(idx));
+ }
+ else { /* constant not found; create a new entry */
+- setnvalue(idx, cast_num(fs->nk));
++ setivalue(idx, 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++]);
+@@ -261,6 +270,21 @@
+ }
+
+
++int luaK_integerK (FuncState *fs, lua_Integer r) {
++ TValue o;
++ setivalue(&o, r);
++ return addk(fs, &o, &o);
++}
++
++
++#ifdef LNUM_COMPLEX
++static int luaK_imagK (FuncState *fs, lua_Number r) {
++ TValue o;
++ setnvalue_complex(&o, r*I);
++ return addk(fs, &o, &o);
++}
++#endif
++
+ static int boolK (FuncState *fs, int b) {
+ TValue o;
+ setbvalue(&o, b);
+@@ -359,6 +383,16 @@
+ luaK_codeABx(fs, OP_LOADK, reg, luaK_numberK(fs, e->u.nval));
+ break;
+ }
++ case VKINT: {
++ luaK_codeABx(fs, OP_LOADK, reg, luaK_integerK(fs, e->u.ival));
++ break;
++ }
++#ifdef LNUM_COMPLEX
++ case VKNUM2: {
++ luaK_codeABx(fs, OP_LOADK, reg, luaK_imagK(fs, e->u.nval));
++ break;
++ }
++#endif
+ case VRELOCABLE: {
+ Instruction *pc = &getcode(fs, e);
+ SETARG_A(*pc, reg);
+@@ -444,6 +478,10 @@
+ int luaK_exp2RK (FuncState *fs, expdesc *e) {
+ luaK_exp2val(fs, e);
+ switch (e->k) {
++#ifdef LNUM_COMPLEX
++ case VKNUM2:
++#endif
++ case VKINT:
+ case VKNUM:
+ case VTRUE:
+ case VFALSE:
+@@ -451,6 +489,10 @@
+ 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) :
++ (e->k == VKINT) ? luaK_integerK(fs, e->u.ival) :
++#ifdef LNUM_COMPLEX
++ (e->k == VKNUM2) ? luaK_imagK(fs, e->u.nval) :
++#endif
+ boolK(fs, (e->k == VTRUE));
+ e->k = VK;
+ return RKASK(e->u.s.info);
+@@ -540,7 +582,10 @@
+ int pc; /* pc of last jump */
+ luaK_dischargevars(fs, e);
+ switch (e->k) {
+- case VK: case VKNUM: case VTRUE: {
++#ifdef LNUM_COMPLEX
++ case VKNUM2:
++#endif
++ case VKINT: case VK: case VKNUM: case VTRUE: {
+ pc = NO_JUMP; /* always true; do nothing */
+ break;
+ }
+@@ -598,7 +643,10 @@
+ e->k = VTRUE;
+ break;
+ }
+- case VK: case VKNUM: case VTRUE: {
++#ifdef LNUM_COMPLEX
++ case VKNUM2:
++#endif
++ case VKINT: case VK: case VKNUM: case VTRUE: {
+ e->k = VFALSE;
+ break;
+ }
+@@ -634,25 +682,70 @@
+
+ static int constfolding (OpCode op, expdesc *e1, expdesc *e2) {
+ lua_Number v1, v2, r;
++ int vkres= VKNUM;
+ if (!isnumeral(e1) || !isnumeral(e2)) return 0;
+- v1 = e1->u.nval;
+- v2 = e2->u.nval;
++
++ /* real and imaginary parts don't mix. */
++#ifdef LNUM_COMPLEX
++ if (e1->k == VKNUM2) {
++ if ((op != OP_UNM) && (e2->k != VKNUM2)) return 0;
++ vkres= VKNUM2; }
++ else if (e2->k == VKNUM2) { return 0; }
++#endif
++ if ((e1->k == VKINT) && (e2->k == VKINT)) {
++ lua_Integer i1= e1->u.ival, i2= e2->u.ival;
++ lua_Integer rr;
++ int done= 0;
++ /* Integer/integer calculations (may end up producing floating point) */
++ switch (op) {
++ case OP_ADD: done= try_addint( &rr, i1, i2 ); break;
++ case OP_SUB: done= try_subint( &rr, i1, i2 ); break;
++ case OP_MUL: done= try_mulint( &rr, i1, i2 ); break;
++ case OP_DIV: done= try_divint( &rr, i1, i2 ); break;
++ case OP_MOD: done= try_modint( &rr, i1, i2 ); break;
++ case OP_POW: done= try_powint( &rr, i1, i2 ); break;
++ case OP_UNM: done= try_unmint( &rr, i1 ); break;
++ default: done= 0; break;
++ }
++ if (done) {
++ e1->u.ival = rr; /* remained within integer range */
++ return 1;
++ }
++ }
++ v1 = (e1->k == VKINT) ? ((lua_Number)e1->u.ival) : e1->u.nval;
++ v2 = (e2->k == VKINT) ? ((lua_Number)e2->u.ival) : 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_MUL:
++#ifdef LNUM_COMPLEX
++ if (vkres==VKNUM2) return 0; /* leave to runtime (could do here, but not worth it?) */
++#endif
++ 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;
++#ifdef LNUM_COMPLEX
++ if (vkres==VKNUM2) return 0; /* leave to runtime */
++#endif
++ r = luai_numdiv(v1, v2); break;
+ case OP_MOD:
+ if (v2 == 0) return 0; /* do not attempt to divide by 0 */
++#ifdef LNUM_COMPLEX
++ if (vkres==VKNUM2) return 0; /* leave to runtime */
++#endif
+ r = luai_nummod(v1, v2); break;
+- case OP_POW: r = luai_numpow(v1, v2); break;
++ case OP_POW:
++#ifdef LNUM_COMPLEX
++ if (vkres==VKNUM2) return 0; /* leave to runtime */
++#endif
++ 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->k = cast(expkind,vkres);
+ e1->u.nval = r;
+ return 1;
+ }
+@@ -696,7 +789,8 @@
+
+ void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) {
+ expdesc e2;
+- e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0;
++ e2.t = e2.f = NO_JUMP; e2.k = VKINT; e2.u.ival = 0;
++
+ switch (op) {
+ case OPR_MINUS: {
+ if (!isnumeral(e))
+diff -urN --exclude=.svn --exclude=.DS_Store ../lua-5.1.3/src/lcode.h lua-5.1.3-patched/src/lcode.h
+--- ../lua-5.1.3/src/lcode.h 2007-12-27 15:02:25.000000000 +0200
++++ lua-5.1.3-patched/src/lcode.h 2008-03-03 12:47:53.000000000 +0200
+@@ -71,6 +71,6 @@
+ 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);
+-
++LUAI_FUNC int luaK_integerK (FuncState *fs, lua_Integer r);
+
+ #endif
+Binary files ../lua-5.1.3/src/lcode.o and lua-5.1.3-patched/src/lcode.o differ
+Binary files ../lua-5.1.3/src/ldblib.o and lua-5.1.3-patched/src/ldblib.o differ
+diff -urN --exclude=.svn --exclude=.DS_Store ../lua-5.1.3/src/ldebug.c lua-5.1.3-patched/src/ldebug.c
+--- ../lua-5.1.3/src/ldebug.c 2007-12-28 17:32:23.000000000 +0200
++++ lua-5.1.3-patched/src/ldebug.c 2008-03-06 22:41:08.000000000 +0200
+@@ -183,7 +183,7 @@
+ int *lineinfo = f->l.p->lineinfo;
+ int i;
+ for (i=0; i<f->l.p->sizelineinfo; i++)
+- setbvalue(luaH_setnum(L, t, lineinfo[i]), 1);
++ setbvalue(luaH_setint(L, t, lineinfo[i]), 1);
+ sethvalue(L, L->top, t);
+ }
+ incr_top(L);
+@@ -550,7 +550,7 @@
+
+ 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 *t = luaT_typenames[ttype_ext(o)];
+ const char *kind = (isinstack(L->ci, o)) ?
+ getobjname(L, L->ci, cast_int(o - L->base), &name) :
+ NULL;
+@@ -578,8 +578,8 @@
+
+
+ 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)];
++ const char *t1 = luaT_typenames[ttype_ext(p1)];
++ const char *t2 = luaT_typenames[ttype_ext(p2)];
+ if (t1[2] == t2[2])
+ luaG_runerror(L, "attempt to compare two %s values", t1);
+ else
+Binary files ../lua-5.1.3/src/ldebug.o and lua-5.1.3-patched/src/ldebug.o differ
+diff -urN --exclude=.svn --exclude=.DS_Store ../lua-5.1.3/src/ldo.c lua-5.1.3-patched/src/ldo.c
+--- ../lua-5.1.3/src/ldo.c 2008-01-19 00:31:22.000000000 +0200
++++ lua-5.1.3-patched/src/ldo.c 2008-03-06 22:41:31.000000000 +0200
+@@ -219,9 +219,9 @@
+ luaC_checkGC(L);
+ htab = luaH_new(L, nvar, 1); /* create `arg' table */
+ for (i=0; i<nvar; i++) /* put extra arguments into `arg' table */
+- setobj2n(L, luaH_setnum(L, htab, i+1), L->top - nvar + i);
++ setobj2n(L, luaH_setint(L, htab, i+1), L->top - nvar + i);
+ /* store counter in field `n' */
+- setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), cast_num(nvar));
++ setivalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), nvar);
+ }
+ #endif
+ /* move fixed parameters to final position */
+Binary files ../lua-5.1.3/src/ldo.o and lua-5.1.3-patched/src/ldo.o differ
+diff -urN --exclude=.svn --exclude=.DS_Store ../lua-5.1.3/src/ldump.c lua-5.1.3-patched/src/ldump.c
+--- ../lua-5.1.3/src/ldump.c 2007-12-27 15:02:25.000000000 +0200
++++ lua-5.1.3-patched/src/ldump.c 2008-03-03 12:47:53.000000000 +0200
+@@ -52,6 +52,11 @@
+ DumpVar(x,D);
+ }
+
++static void DumpInteger(lua_Integer x, DumpState* D)
++{
++ DumpVar(x,D);
++}
++
+ static void DumpVector(const void* b, int n, size_t size, DumpState* D)
+ {
+ DumpInt(n,D);
+@@ -93,8 +98,11 @@
+ DumpChar(bvalue(o),D);
+ break;
+ case LUA_TNUMBER:
+- DumpNumber(nvalue(o),D);
++ DumpNumber(nvalue_fast(o),D);
+ break;
++ case LUA_TINT:
++ DumpInteger(ivalue(o),D);
++ break;
+ case LUA_TSTRING:
+ DumpString(rawtsvalue(o),D);
+ break;
+Binary files ../lua-5.1.3/src/ldump.o and lua-5.1.3-patched/src/ldump.o differ
+Binary files ../lua-5.1.3/src/lfunc.o and lua-5.1.3-patched/src/lfunc.o differ
+Binary files ../lua-5.1.3/src/lgc.o and lua-5.1.3-patched/src/lgc.o differ
+Binary files ../lua-5.1.3/src/liblua.a and lua-5.1.3-patched/src/liblua.a differ
+Binary files ../lua-5.1.3/src/linit.o and lua-5.1.3-patched/src/linit.o differ
+diff -urN --exclude=.svn --exclude=.DS_Store ../lua-5.1.3/src/liolib.c lua-5.1.3-patched/src/liolib.c
+--- ../lua-5.1.3/src/liolib.c 2008-01-18 19:47:43.000000000 +0200
++++ lua-5.1.3-patched/src/liolib.c 2008-03-19 10:10:09.000000000 +0200
+@@ -9,6 +9,7 @@
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
++#include <ctype.h>
+
+ #define liolib_c
+ #define LUA_LIB
+@@ -18,7 +19,8 @@
+ #include "lauxlib.h"
+ #include "lualib.h"
+
+-
++#include "lnum.h"
++#include "llex.h"
+
+ #define IO_INPUT 1
+ #define IO_OUTPUT 2
+@@ -269,6 +271,13 @@
+ ** =======================================================
+ */
+
++/*
++* Many problems if we intend the same 'n' format specifier (see 'file:read()')
++* to work for both FP and integer numbers, without losing their accuracy. So
++* we don't. 'n' reads numbers as floating points, 'i' as integers. Old code
++* remains valid, but won't provide full integer accuracy (this only matters
++* with float FP and/or 64-bit integers).
++*/
+
+ static int read_number (lua_State *L, FILE *f) {
+ lua_Number d;
+@@ -279,6 +288,43 @@
+ else return 0; /* read fails */
+ }
+
++static int read_integer (lua_State *L, FILE *f) {
++ lua_Integer i;
++ if (fscanf(f, LUA_INTEGER_SCAN, &i) == 1) {
++ lua_pushinteger(L, i);
++ return 1;
++ }
++ else return 0; /* read fails */
++}
++
++#ifdef LNUM_COMPLEX
++static int read_complex (lua_State *L, FILE *f) {
++ /* NNN / NNNi / NNN+MMMi / NNN-MMMi */
++ lua_Number a,b;
++ if (fscanf(f, LUA_NUMBER_SCAN, &a) == 1) {
++ int c=fgetc(f);
++ switch(c) {
++ case 'i':
++ lua_pushcomplex(L, a*I);
++ return 1;
++ case '+':
++ case '-':
++ /* "i" is consumed if at the end; just 'NNN+MMM' will most likely
++ * behave as if "i" was there? (TBD: test)
++ */
++ if (fscanf(f, LUA_NUMBER_SCAN "i", &b) == 1) {
++ lua_pushcomplex(L, a+ (c=='+' ? b:-b)*I);
++ return 1;
++ }
++ }
++ ungetc( c,f );
++ lua_pushnumber(L,a); /*real part only*/
++ return 1;
++ }
++ return 0; /* read fails */
++}
++#endif
++
+
+ static int test_eof (lua_State *L, FILE *f) {
+ int c = getc(f);
+@@ -352,6 +398,14 @@
+ case 'n': /* number */
+ success = read_number(L, f);
+ break;
++ case 'i': /* integer (full accuracy) */
++ success = read_integer(L, f);
++ break;
++#ifdef LNUM_COMPLEX
++ case 'c': /* complex */
++ success = read_complex(L, f);
++ break;
++#endif
+ case 'l': /* line */
+ success = read_line(L, f);
+ break;
+@@ -412,9 +466,10 @@
+ int status = 1;
+ for (; nargs--; arg++) {
+ if (lua_type(L, arg) == LUA_TNUMBER) {
+- /* optimization: could be done exactly as for strings */
+- status = status &&
+- fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0;
++ if (lua_isinteger(L,arg))
++ status = status && fprintf(f, LUA_INTEGER_FMT, lua_tointeger(L, arg)) > 0;
++ else
++ status = status && fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0;
+ }
+ else {
+ size_t l;
+@@ -457,7 +512,7 @@
+ static const char *const modenames[] = {"no", "full", "line", NULL};
+ FILE *f = tofile(L);
+ int op = luaL_checkoption(L, 2, NULL, modenames);
+- lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE);
++ size_t sz = luaL_optint32(L, 3, LUAL_BUFFERSIZE);
+ int res = setvbuf(f, NULL, mode[op], sz);
+ return pushresult(L, res == 0, NULL);
+ }
+Binary files ../lua-5.1.3/src/liolib.o and lua-5.1.3-patched/src/liolib.o differ
+diff -urN --exclude=.svn --exclude=.DS_Store ../lua-5.1.3/src/llex.c lua-5.1.3-patched/src/llex.c
+--- ../lua-5.1.3/src/llex.c 2007-12-27 15:02:25.000000000 +0200
++++ lua-5.1.3-patched/src/llex.c 2008-03-04 11:10:30.000000000 +0200
+@@ -22,6 +22,7 @@
+ #include "lstring.h"
+ #include "ltable.h"
+ #include "lzio.h"
++#include "lnum.h"
+
+
+
+@@ -34,13 +35,17 @@
+
+
+ /* ORDER RESERVED */
+-const char *const luaX_tokens [] = {
++static 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",
+ "..", "...", "==", ">=", "<=", "~=",
+ "<number>", "<name>", "<string>", "<eof>",
++ "<integer>",
++#ifdef LNUM_COMPLEX
++ "<number2>",
++#endif
+ NULL
+ };
+
+@@ -90,7 +95,11 @@
+ switch (token) {
+ case TK_NAME:
+ case TK_STRING:
++ case TK_INT:
+ case TK_NUMBER:
++#ifdef LNUM_COMPLEX
++ case TK_NUMBER2:
++#endif
+ save(ls, '\0');
+ return luaZ_buffer(ls->buff);
+ default:
+@@ -173,23 +182,27 @@
+ if (p[n] == from) p[n] = to;
+ }
+
+-
+-static void trydecpoint (LexState *ls, SemInfo *seminfo) {
++/* TK_NUMBER (/ TK_NUMBER2) */
++static int trydecpoint (LexState *ls, SemInfo *seminfo) {
+ /* format error: try to update decimal point separator */
+ struct lconv *cv = localeconv();
+ char old = ls->decpoint;
++ int ret;
+ 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)) {
++ ret= luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r, NULL);
++ if (!ret) {
+ /* 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);
+ }
++ return ret;
+ }
+
+
+-/* LUA_NUMBER */
+-static void read_numeral (LexState *ls, SemInfo *seminfo) {
++/* TK_NUMBER / TK_INT (/TK_NUMBER2) */
++static int read_numeral (LexState *ls, SemInfo *seminfo) {
++ int ret;
+ lua_assert(isdigit(ls->current));
+ do {
+ save_and_next(ls);
+@@ -200,8 +213,9 @@
+ 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 */
++ ret= luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r, &seminfo->i );
++ if (!ret) return trydecpoint(ls, seminfo); /* try to update decimal point separator */
++ return ret;
+ }
+
+
+@@ -329,6 +343,7 @@
+ }
+
+
++/* char / TK_* */
+ static int llex (LexState *ls, SemInfo *seminfo) {
+ luaZ_resetbuffer(ls->buff);
+ for (;;) {
+@@ -400,8 +415,7 @@
+ }
+ else if (!isdigit(ls->current)) return '.';
+ else {
+- read_numeral(ls, seminfo);
+- return TK_NUMBER;
++ return read_numeral(ls, seminfo);
+ }
+ }
+ case EOZ: {
+@@ -414,8 +428,7 @@
+ continue;
+ }
+ else if (isdigit(ls->current)) {
+- read_numeral(ls, seminfo);
+- return TK_NUMBER;
++ return read_numeral(ls, seminfo);
+ }
+ else if (isalpha(ls->current) || ls->current == '_') {
+ /* identifier or reserved word */
+diff -urN --exclude=.svn --exclude=.DS_Store ../lua-5.1.3/src/llex.h lua-5.1.3-patched/src/llex.h
+--- ../lua-5.1.3/src/llex.h 2007-12-27 15:02:25.000000000 +0200
++++ lua-5.1.3-patched/src/llex.h 2008-03-04 11:12:08.000000000 +0200
+@@ -29,19 +29,22 @@
+ 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
++ TK_NAME, TK_STRING, TK_EOS, TK_INT
++#ifdef LNUM_COMPLEX
++ , TK_NUMBER2 /* imaginary constants: Ni */
++#endif
+ };
+
+ /* 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 [];
+-
+-
++/* SemInfo is a local data structure of 'llex.c', used for carrying a string
++ * or a number. A separate token (TK_*) will tell, how to interpret the data.
++ */
+ typedef union {
+ lua_Number r;
++ lua_Integer i;
+ TString *ts;
+ } SemInfo; /* semantics information */
+
+Binary files ../lua-5.1.3/src/llex.o and lua-5.1.3-patched/src/llex.o differ
+diff -urN --exclude=.svn --exclude=.DS_Store ../lua-5.1.3/src/llimits.h lua-5.1.3-patched/src/llimits.h
+--- ../lua-5.1.3/src/llimits.h 2007-12-27 15:02:25.000000000 +0200
++++ lua-5.1.3-patched/src/llimits.h 2008-03-04 11:16:43.000000000 +0200
+@@ -49,6 +49,7 @@
+
+ /* result of a `usual argument conversion' over lua_Number */
+ typedef LUAI_UACNUMBER l_uacNumber;
++typedef LUAI_UACINTEGER l_uacInteger;
+
+
+ /* internal assertions for in-house debugging */
+@@ -80,7 +81,6 @@
+ #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)
+diff -urN --exclude=.svn --exclude=.DS_Store ../lua-5.1.3/src/lmathlib.c lua-5.1.3-patched/src/lmathlib.c
+--- ../lua-5.1.3/src/lmathlib.c 2007-12-27 15:02:25.000000000 +0200
++++ lua-5.1.3-patched/src/lmathlib.c 2008-03-26 11:32:25.000000000 +0200
+@@ -4,7 +4,6 @@
+ ** See Copyright Notice in lua.h
+ */
+
+-
+ #include <stdlib.h>
+ #include <math.h>
+
+@@ -16,113 +15,210 @@
+ #include "lauxlib.h"
+ #include "lualib.h"
+
++/* 'luai_vectpow()' as a replacement for 'cpow()'. Defined in the header; we
++ * don't intrude the code libs internal functions.
++ */
++#ifdef LNUM_COMPLEX
++# include "lnum.h"
++#endif
+
+ #undef PI
+-#define PI (3.14159265358979323846)
+-#define RADIANS_PER_DEGREE (PI/180.0)
+-
++#ifdef LNUM_FLOAT
++# define PI (3.14159265358979323846F)
++#elif defined(M_PI)
++# define PI M_PI
++#else
++# define PI (3.14159265358979323846264338327950288)
++#endif
++#define RADIANS_PER_DEGREE (PI/180)
+
++#undef HUGE
++#ifdef LNUM_FLOAT
++# define HUGE HUGE_VALF
++#elif defined(LNUM_LDOUBLE)
++# define HUGE HUGE_VALL
++#else
++# define HUGE HUGE_VAL
++#endif
+
+ static int math_abs (lua_State *L) {
+- lua_pushnumber(L, fabs(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++ lua_pushnumber(L, _LF(cabs) (luaL_checkcomplex(L,1)));
++#else
++ lua_pushnumber(L, _LF(fabs) (luaL_checknumber(L, 1)));
++#endif
+ return 1;
+ }
+
+ static int math_sin (lua_State *L) {
+- lua_pushnumber(L, sin(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++ lua_pushcomplex(L, _LF(csin) (luaL_checkcomplex(L,1)));
++#else
++ lua_pushnumber(L, _LF(sin) (luaL_checknumber(L, 1)));
++#endif
+ return 1;
+ }
+
+ static int math_sinh (lua_State *L) {
+- lua_pushnumber(L, sinh(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++ lua_pushcomplex(L, _LF(csinh) (luaL_checkcomplex(L,1)));
++#else
++ lua_pushnumber(L, _LF(sinh) (luaL_checknumber(L, 1)));
++#endif
+ return 1;
+ }
+
+ static int math_cos (lua_State *L) {
+- lua_pushnumber(L, cos(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++ lua_pushcomplex(L, _LF(ccos) (luaL_checkcomplex(L,1)));
++#else
++ lua_pushnumber(L, _LF(cos) (luaL_checknumber(L, 1)));
++#endif
+ return 1;
+ }
+
+ static int math_cosh (lua_State *L) {
+- lua_pushnumber(L, cosh(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++ lua_pushcomplex(L, _LF(ccosh) (luaL_checkcomplex(L,1)));
++#else
++ lua_pushnumber(L, _LF(cosh) (luaL_checknumber(L, 1)));
++#endif
+ return 1;
+ }
+
+ static int math_tan (lua_State *L) {
+- lua_pushnumber(L, tan(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++ lua_pushcomplex(L, _LF(ctan) (luaL_checkcomplex(L,1)));
++#else
++ lua_pushnumber(L, _LF(tan) (luaL_checknumber(L, 1)));
++#endif
+ return 1;
+ }
+
+ static int math_tanh (lua_State *L) {
+- lua_pushnumber(L, tanh(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++ lua_pushcomplex(L, _LF(ctanh) (luaL_checkcomplex(L,1)));
++#else
++ lua_pushnumber(L, _LF(tanh) (luaL_checknumber(L, 1)));
++#endif
+ return 1;
+ }
+
+ static int math_asin (lua_State *L) {
+- lua_pushnumber(L, asin(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++ lua_pushcomplex(L, _LF(casin) (luaL_checkcomplex(L,1)));
++#else
++ lua_pushnumber(L, _LF(asin) (luaL_checknumber(L, 1)));
++#endif
+ return 1;
+ }
+
+ static int math_acos (lua_State *L) {
+- lua_pushnumber(L, acos(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++ lua_pushcomplex(L, _LF(cacos) (luaL_checkcomplex(L,1)));
++#else
++ lua_pushnumber(L, _LF(acos) (luaL_checknumber(L, 1)));
++#endif
+ return 1;
+ }
+
+ static int math_atan (lua_State *L) {
+- lua_pushnumber(L, atan(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++ lua_pushcomplex(L, _LF(catan) (luaL_checkcomplex(L,1)));
++#else
++ lua_pushnumber(L, _LF(atan) (luaL_checknumber(L, 1)));
++#endif
+ return 1;
+ }
+
+ static int math_atan2 (lua_State *L) {
+- lua_pushnumber(L, atan2(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
++ /* scalars only */
++ lua_pushnumber(L, _LF(atan2) (luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
+ return 1;
+ }
+
+ static int math_ceil (lua_State *L) {
+- lua_pushnumber(L, ceil(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++ lua_Complex v= luaL_checkcomplex(L, 1);
++ lua_pushcomplex(L, _LF(ceil) (_LF(creal)(v)) + _LF(ceil) (_LF(cimag)(v))*I);
++#else
++ lua_pushnumber(L, _LF(ceil) (luaL_checknumber(L, 1)));
++#endif
+ return 1;
+ }
+
+ static int math_floor (lua_State *L) {
+- lua_pushnumber(L, floor(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++ lua_Complex v= luaL_checkcomplex(L, 1);
++ lua_pushcomplex(L, _LF(floor) (_LF(creal)(v)) + _LF(floor) (_LF(cimag)(v))*I);
++#else
++ lua_pushnumber(L, _LF(floor) (luaL_checknumber(L, 1)));
++#endif
+ return 1;
+ }
+
+-static int math_fmod (lua_State *L) {
+- lua_pushnumber(L, fmod(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
++static int math_fmod (lua_State *L) {
++ /* scalars only */
++ lua_pushnumber(L, _LF(fmod) (luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
+ return 1;
+ }
+
+ static int math_modf (lua_State *L) {
+- double ip;
+- double fp = modf(luaL_checknumber(L, 1), &ip);
++ /* scalars only */
++ lua_Number ip;
++ lua_Number fp = _LF(modf) (luaL_checknumber(L, 1), &ip);
+ lua_pushnumber(L, ip);
+ lua_pushnumber(L, fp);
+ return 2;
+ }
+
+ static int math_sqrt (lua_State *L) {
+- lua_pushnumber(L, sqrt(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++ lua_pushcomplex(L, _LF(csqrt) (luaL_checkcomplex(L,1)));
++#else
++ lua_pushnumber(L, _LF(sqrt) (luaL_checknumber(L, 1)));
++#endif
+ return 1;
+ }
+
+ static int math_pow (lua_State *L) {
+- lua_pushnumber(L, pow(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
++#ifdef LNUM_COMPLEX
++ /* C99 'cpow' gives somewhat inaccurate results (i.e. (-1)^2 = -1+1.2246467991474e-16i).
++ * 'luai_vectpow' smoothens such, reusing it is the reason we need to #include "lnum.h".
++ */
++ lua_pushcomplex(L, luai_vectpow(luaL_checkcomplex(L,1), luaL_checkcomplex(L,2)));
++#else
++ lua_pushnumber(L, _LF(pow) (luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
++#endif
+ return 1;
+ }
+
+ static int math_log (lua_State *L) {
+- lua_pushnumber(L, log(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++ lua_pushcomplex(L, _LF(clog) (luaL_checkcomplex(L,1)));
++#else
++ lua_pushnumber(L, _LF(log) (luaL_checknumber(L, 1)));
++#endif
+ return 1;
+ }
+
+ static int math_log10 (lua_State *L) {
+- lua_pushnumber(L, log10(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++ /* Not in standard <complex.h> , but easy to calculate: log_a(x) = log_b(x) / log_b(a)
++ */
++ lua_pushcomplex(L, _LF(clog) (luaL_checkcomplex(L,1)) / _LF(log) (10));
++#else
++ lua_pushnumber(L, _LF(log10) (luaL_checknumber(L, 1)));
++#endif
+ return 1;
+ }
+
+ static int math_exp (lua_State *L) {
+- lua_pushnumber(L, exp(luaL_checknumber(L, 1)));
++#ifdef LNUM_COMPLEX
++ lua_pushcomplex(L, _LF(cexp) (luaL_checkcomplex(L,1)));
++#else
++ lua_pushnumber(L, _LF(exp) (luaL_checknumber(L, 1)));
++#endif
+ return 1;
+ }
+
+@@ -138,19 +234,20 @@
+
+ static int math_frexp (lua_State *L) {
+ int e;
+- lua_pushnumber(L, frexp(luaL_checknumber(L, 1), &e));
++ lua_pushnumber(L, _LF(frexp) (luaL_checknumber(L, 1), &e));
+ lua_pushinteger(L, e);
+ return 2;
+ }
+
+ static int math_ldexp (lua_State *L) {
+- lua_pushnumber(L, ldexp(luaL_checknumber(L, 1), luaL_checkint(L, 2)));
++ lua_pushnumber(L, _LF(ldexp) (luaL_checknumber(L, 1), luaL_checkint(L, 2)));
+ return 1;
+ }
+
+
+
+ static int math_min (lua_State *L) {
++ /* scalars only */
+ int n = lua_gettop(L); /* number of arguments */
+ lua_Number dmin = luaL_checknumber(L, 1);
+ int i;
+@@ -165,6 +262,7 @@
+
+
+ static int math_max (lua_State *L) {
++ /* scalars only */
+ int n = lua_gettop(L); /* number of arguments */
+ lua_Number dmax = luaL_checknumber(L, 1);
+ int i;
+@@ -182,25 +280,20 @@
+ /* the `%' avoids the (rare) case of r==1, and is needed also because on
+ some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */
+ lua_Number r = (lua_Number)(rand()%RAND_MAX) / (lua_Number)RAND_MAX;
+- switch (lua_gettop(L)) { /* check number of arguments */
+- case 0: { /* no arguments */
+- lua_pushnumber(L, r); /* Number between 0 and 1 */
+- break;
+- }
+- case 1: { /* only upper limit */
+- int u = luaL_checkint(L, 1);
+- luaL_argcheck(L, 1<=u, 1, "interval is empty");
+- lua_pushnumber(L, floor(r*u)+1); /* int between 1 and `u' */
+- break;
+- }
+- case 2: { /* lower and upper limits */
+- int l = luaL_checkint(L, 1);
+- int u = luaL_checkint(L, 2);
+- luaL_argcheck(L, l<=u, 2, "interval is empty");
+- lua_pushnumber(L, floor(r*(u-l+1))+l); /* int between `l' and `u' */
+- break;
+- }
+- default: return luaL_error(L, "wrong number of arguments");
++ int n= lua_gettop(L); /* number of arguments */
++ if (n==0) { /* no arguments: range [0,1) */
++ lua_pushnumber(L, r);
++ } else if (n<=2) { /* int range [1,u] or [l,u] */
++ int l= n==1 ? 1 : luaL_checkint(L, 1);
++ int u = luaL_checkint(L, n);
++ int tmp;
++ lua_Number d;
++ luaL_argcheck(L, l<=u, n, "interval is empty");
++ d= _LF(floor)(r*(u-l+1));
++ lua_number2int(tmp,d);
++ lua_pushinteger(L, l+tmp);
++ } else {
++ return luaL_error(L, "wrong number of arguments");
+ }
+ return 1;
+ }
+@@ -211,6 +304,66 @@
+ return 0;
+ }
+
++/*
++* Lua 5.1 does not have acosh, asinh, atanh for scalars (not ANSI C)
++*/
++#if __STDC_VERSION__ >= 199901L
++static int math_acosh (lua_State *L) {
++# ifdef LNUM_COMPLEX
++ lua_pushcomplex(L, _LF(cacosh) (luaL_checkcomplex(L,1)));
++# else
++ lua_pushnumber(L, _LF(acosh) (luaL_checknumber(L,1)));
++# endif
++ return 1;
++}
++static int math_asinh (lua_State *L) {
++# ifdef LNUM_COMPLEX
++ lua_pushcomplex(L, _LF(casinh) (luaL_checkcomplex(L,1)));
++# else
++ lua_pushnumber(L, _LF(asinh) (luaL_checknumber(L,1)));
++# endif
++ return 1;
++}
++static int math_atanh (lua_State *L) {
++# ifdef LNUM_COMPLEX
++ lua_pushcomplex(L, _LF(catanh) (luaL_checkcomplex(L,1)));
++# else
++ lua_pushnumber(L, _LF(atanh) (luaL_checknumber(L,1)));
++# endif
++ return 1;
++}
++#endif
++
++/*
++ * C99 complex functions, not covered above.
++*/
++#ifdef LNUM_COMPLEX
++static int math_arg (lua_State *L) {
++ lua_pushnumber(L, _LF(carg) (luaL_checkcomplex(L,1)));
++ return 1;
++}
++
++static int math_imag (lua_State *L) {
++ lua_pushnumber(L, _LF(cimag) (luaL_checkcomplex(L,1)));
++ return 1;
++}
++
++static int math_real (lua_State *L) {
++ lua_pushnumber(L, _LF(creal) (luaL_checkcomplex(L,1)));
++ return 1;
++}
++
++static int math_conj (lua_State *L) {
++ lua_pushcomplex(L, _LF(conj) (luaL_checkcomplex(L,1)));
++ return 1;
++}
++
++static int math_proj (lua_State *L) {
++ lua_pushcomplex(L, _LF(cproj) (luaL_checkcomplex(L,1)));
++ return 1;
++}
++#endif
++
+
+ static const luaL_Reg mathlib[] = {
+ {"abs", math_abs},
+@@ -241,6 +394,18 @@
+ {"sqrt", math_sqrt},
+ {"tanh", math_tanh},
+ {"tan", math_tan},
++#if __STDC_VERSION__ >= 199901L
++ {"acosh", math_acosh},
++ {"asinh", math_asinh},
++ {"atanh", math_atanh},
++#endif
++#ifdef LNUM_COMPLEX
++ {"arg", math_arg},
++ {"imag", math_imag},
++ {"real", math_real},
++ {"conj", math_conj},
++ {"proj", math_proj},
++#endif
+ {NULL, NULL}
+ };
+
+@@ -252,8 +417,10 @@
+ luaL_register(L, LUA_MATHLIBNAME, mathlib);
+ lua_pushnumber(L, PI);
+ lua_setfield(L, -2, "pi");
+- lua_pushnumber(L, HUGE_VAL);
++ lua_pushnumber(L, HUGE);
+ lua_setfield(L, -2, "huge");
++ lua_pushinteger(L, LUA_INTEGER_MAX );
++ lua_setfield(L, -2, "hugeint");
+ #if defined(LUA_COMPAT_MOD)
+ lua_getfield(L, -1, "fmod");
+ lua_setfield(L, -2, "mod");
+Binary files ../lua-5.1.3/src/lmathlib.o and lua-5.1.3-patched/src/lmathlib.o differ
+Binary files ../lua-5.1.3/src/lmem.o and lua-5.1.3-patched/src/lmem.o differ
+diff -urN --exclude=.svn --exclude=.DS_Store ../lua-5.1.3/src/lnum.c lua-5.1.3-patched/src/lnum.c
+--- ../lua-5.1.3/src/lnum.c 1970-01-01 02:00:00.000000000 +0200
++++ lua-5.1.3-patched/src/lnum.c 2008-03-26 11:32:25.000000000 +0200
+@@ -0,0 +1,312 @@
++/*
++** $Id: lnum.c,v ... $
++** Internal number model
++** See Copyright Notice in lua.h
++*/
++
++#include <stdlib.h>
++#include <math.h>
++#include <ctype.h>
++#include <string.h>
++#include <stdio.h>
++#include <errno.h>
++
++#define lnum_c
++#define LUA_CORE
++
++#include "lua.h"
++#include "llex.h"
++#include "lnum.h"
++
++/*
++** lua_real2str converts a (non-complex) number to a string.
++** lua_str2real converts a string to a (non-complex) number.
++*/
++#define lua_real2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n))
++
++/*
++* Note: Only 'strtod()' is part of ANSI C; others are C99 and
++* may need '--std=c99' compiler setting (at least on Ubuntu 7.10).
++*
++* Visual C++ 2008 Express does not have 'strtof()', nor 'strtold()'.
++* References to '_strtold()' exist but don't compile. It seems best
++* to leave Windows users with DOUBLE only (or compile with MinGW).
++*
++* In practise, using '(long double)strtod' is a risky thing, since
++* it will cause accuracy loss in reading in numbers, and such losses
++* will pile up in later processing. Get a real 'strtold()' or don't
++* use that mode at all.
++*/
++#ifdef LNUM_DOUBLE
++# define lua_str2real strtod
++#elif defined(LNUM_FLOAT)
++# define lua_str2real strtof
++#elif defined(LNUM_LDOUBLE)
++# define lua_str2real strtold
++#endif
++
++#define lua_integer2str(s,v) sprintf((s), LUA_INTEGER_FMT, (v))
++
++/* 's' is expected to be LUAI_MAXNUMBER2STR long (enough for any number)
++*/
++void luaO_num2buf( char *s, const TValue *o )
++{
++ lua_Number n;
++ lua_assert( ttisnumber(o) );
++
++ /* Reason to handle integers differently is not only speed, but accuracy as
++ * well. We want to make any integer tostring() without roundings, at all.
++ */
++ if (ttisint(o)) {
++ lua_integer2str( s, ivalue(o) );
++ return;
++ }
++ n= nvalue_fast(o);
++ lua_real2str(s, n);
++
++#ifdef LNUM_COMPLEX
++ lua_Number n2= nvalue_img_fast(o);
++ if (n2!=0) { /* Postfix with +-Ni */
++ int re0= (n == 0);
++ char *s2= re0 ? s : strchr(s,'\0');
++ if ((!re0) && (n2>0)) *s2++= '+';
++ lua_real2str( s2, n2 );
++ strcat(s2,"i");
++ }
++#endif
++}
++
++/*
++* If a LUA_TNUMBER has integer value, give it.
++*/
++int /*bool*/ tt_integer_valued( const TValue *o, lua_Integer *ref ) {
++ lua_Number d;
++ lua_Integer i;
++
++ lua_assert( ttype(o)==LUA_TNUMBER );
++ lua_assert( ref );
++#ifdef LNUM_COMPLEX
++ if (nvalue_img_fast(o)!=0) return 0;
++#endif
++ d= nvalue_fast(o);
++ lua_number2integer(i, d);
++ if (cast_num(i) == d) {
++ *ref= i; return 1;
++ }
++ return 0;
++}
++
++/*
++ * Lua 5.1.3 (using 'strtod()') allows 0x+hex but not 0+octal. This is good,
++ * and we should NOT use 'autobase' 0 with 'strtoul[l]()' for this reason.
++ *
++ * Lua 5.1.3 allows '0x...' numbers to overflow and lose precision; this is not
++ * good. On Visual C++ 2008, 'strtod()' does not even take them in. Better to
++ * require hex values to fit 'lua_Integer' or give an error that they don't?
++ *
++ * Full hex range (0 .. 0xff..ff) is stored as integers, not to lose any bits.
++ * Numerical value of 0xff..ff will be -1, if used in calculations.
++ *
++ * Returns: TK_INT for a valid integer, '*endptr_ref' updated
++ * TK_NUMBER for seemingly numeric, to be parsed as floating point
++ * 0 for bad characters, not a number (or '0x' out of range)
++ */
++static int luaO_str2i (const char *s, lua_Integer *res, char **endptr_ref) {
++ char *endptr;
++ /* 'v' gets ULONG_MAX on possible overflow (which is > LUA_INTEGER_MAX);
++ * we don't have to check 'errno' here.
++ */
++ unsigned LUA_INTEGER v= lua_str2ul(s, &endptr, 10);
++ if (endptr == s) return 0; /* nothing numeric */
++ if (v==0 && *endptr=='x') {
++ errno= 0; /* needs to be set, 'strtoul[l]' does not clear it */
++ v= lua_str2ul(endptr+1, &endptr, 16); /* retry as hex, unsigned range */
++ if (errno==ERANGE) { /* clamped to 0xff..ff */
++#if (defined(LNUM_INT32) && !defined(LNUM_FLOAT)) || defined(LNUM_LDOUBLE)
++ return TK_NUMBER; /* Allow to be read as floating point (has more integer range) */
++#else
++ return 0; /* Reject the number */
++#endif
++ }
++ } else if ((v > LUA_INTEGER_MAX) || (*endptr && (!isspace(*endptr)))) {
++ return TK_NUMBER; /* not in signed range, or has '.', 'e' etc. trailing */
++ }
++ *res= (lua_Integer)v;
++ *endptr_ref= endptr;
++ return TK_INT;
++}
++
++/* 0 / TK_NUMBER / TK_INT (/ TK_NUMBER2) */
++int luaO_str2d (const char *s, lua_Number *res_n, lua_Integer *res_i) {
++ char *endptr;
++ int ret= TK_NUMBER;
++ /* Check integers first, if caller is allowing.
++ * If 'res2'==NULL, they're only looking for floating point.
++ */
++ if (res_i) {
++ ret= luaO_str2i(s,res_i,&endptr);
++ if (ret==0) return 0;
++ }
++ if (ret==TK_NUMBER) {
++ lua_assert(res_n);
++ /* Note: Visual C++ 2008 Express 'strtod()' does not read in "0x..."
++ * numbers; it will read '0' and spit 'x' as endptr.
++ * This means hex constants not fitting in 'lua_Integer' won't
++ * be read in at all. What to do?
++ */
++ *res_n = lua_str2real(s, &endptr);
++ if (endptr == s) return 0; /* conversion failed */
++ /* Visual C++ 2008 'strtod()' does not allow "0x..." input. */
++#if defined(_MSC_VER) && !defined(LNUM_FLOAT) && !defined(LNUM_INT64)
++ if (*res_n==0 && *endptr=='x') {
++ /* Hex constant too big for 'lua_Integer' but that could fit in 'lua_Number'
++ * integer bits
++ */
++ unsigned __int64 v= _strtoui64( s, &endptr, 16 );
++ /* We just let > 64 bit values be clamped to _UI64_MAX (MSDN does not say 'errno'==ERANGE would be set) */
++ *res_n= cast_num(v);
++ if (*res_n != v) return 0; /* Would have lost accuracy */
++ }
++#endif
++#ifdef LNUM_COMPLEX
++ if (*endptr == 'i') { endptr++; ret= TK_NUMBER2; }
++#endif
++ }
++ if (*endptr) {
++ while (isspace(cast(unsigned char, *endptr))) endptr++;
++ if (*endptr) return 0; /* invalid trail */
++ }
++ return ret;
++}
++
++
++/* Functions for finding out, when integer operations remain in range
++ * (and doing them).
++ */
++int try_addint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) {
++ lua_Integer v= ib+ic; /* may overflow */
++ if (ib>0 && ic>0) { if (v < 0) return 0; /*overflow, use floats*/ }
++ else if (ib<0 && ic<0) { if (v >= 0) return 0; }
++ *r= v;
++ return 1;
++}
++
++int try_subint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) {
++ lua_Integer v= ib-ic; /* may overflow */
++ if (ib>=0 && ic<0) { if (v < 0) return 0; /*overflow, use floats*/ }
++ else if (ib<0 && ic>0) { if (v >= 0) return 0; }
++ *r= v;
++ return 1;
++}
++
++int try_mulint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) {
++ if (ib!=LUA_INTEGER_MIN && ic!=LUA_INTEGER_MIN) {
++ lua_Integer b= luai_abs(ib), c= luai_abs(ic);
++ if ( (ib==0) || (LUA_INTEGER_MAX/b >= c) ) {
++ *r= ib*ic; /* no overflow */
++ return 1;
++ }
++ } else if (ib==0 || ic==0) {
++ *r= 0; return 1;
++ }
++
++ /* Result can be LUA_INTEGER_MIN; if it is, calculating it using floating
++ * point will not cause accuracy loss.
++ */
++ if ( luai_nummul( cast_num(ib), cast_num(ic) ) == LUA_INTEGER_MIN ) {
++ *r= LUA_INTEGER_MIN;
++ return 1;
++ }
++ return 0;
++}
++
++int try_divint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) {
++ /* N/0: leave to float side, to give an error
++ */
++ if (ic==0) return 0;
++
++ /* N/LUA_INTEGER_MIN: always non-integer results, or 0 or +1
++ */
++ if (ic==LUA_INTEGER_MIN) {
++ if (ib==LUA_INTEGER_MIN) { *r=1; return 1; }
++ if (ib==0) { *r=0; return 1; }
++
++ /* LUA_INTEGER_MIN (-2^31|63)/N: calculate using float side (either the division
++ * causes non-integer results, or there is no accuracy loss in int->fp->int
++ * conversions (N=2,4,8,..,256 and N=2^30,2^29,..2^23).
++ */
++ } else if (ib==LUA_INTEGER_MIN) {
++ lua_Number d= luai_numdiv( cast_num(LUA_INTEGER_MIN), cast_num(ic) );
++ lua_Integer i; lua_number2integer(i,d);
++ if (cast_num(i)==d) { *r= i; return 1; }
++
++ } else {
++ /* Note: We _can_ use ANSI C mod here, even on negative values, since
++ * we only test for == 0 (the sign would be implementation dependent).
++ */
++ if (ib%ic == 0) { *r= ib/ic; return 1; }
++ }
++
++ return 0;
++}
++
++int try_modint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) {
++ if (ic!=0) {
++ /* ANSI C can be trusted when b%c==0, or when values are non-negative.
++ * b - (floor(b/c) * c)
++ * -->
++ * + +: b - (b/c) * c (b % c can be used)
++ * - -: b - (b/c) * c (b % c could work, but not defined by ANSI C)
++ * 0 -: b - (b/c) * c (=0, b % c could work, but not defined by ANSI C)
++ * - +: b - (b/c-1) * c (when b!=-c)
++ * + -: b - (b/c-1) * c (when b!=-c)
++ *
++ * o MIN%MIN ends up 0, via overflow in calcs but that does not matter.
++ * o MIN%MAX ends up MAX-1 (and other such numbers), also after overflow,
++ * but that does not matter, results do.
++ */
++ lua_Integer v= ib % ic;
++ if ( v!=0 && (ib<0 || ic<0) ) {
++ v= ib - ((ib/ic) - ((ib<=0 && ic<0) ? 0:1)) * ic;
++ }
++ /* Result should always have same sign as 2nd argument. (PIL2) */
++ lua_assert( (v<0) ? (ic<0) : (v>0) ? (ic>0) : 1 );
++ *r= v;
++ return 1;
++ }
++ return 0; /* let float side return NaN */
++}
++
++int try_powint( lua_Integer *r, lua_Integer ib, lua_Integer ic ) {
++
++ /* In FLOAT/INT32 or FLOAT|DOUBLE/INT64 modes, calculating integer powers
++ * via FP realm may lose accuracy (i.e. 7^11 = 1977326743, which fits int32
++ * but not 23-bit float mantissa).
++ *
++ * The current solution is dumb, but it works and uses little code. Use of
++ * integer powers is not anticipated to be very frequent (apart from 2^x,
++ * which is separately optimized).
++ */
++ if (ib==0) *r=0;
++ else if (ic<0) return 0; /* FP realm */
++ else if (ib==2 && ic < (int)sizeof(lua_Integer)*8-1) *r= ((lua_Integer)1)<<ic; /* 1,2,4,...2^30 | 2^62 optimization */
++ else if (ic==0) *r=1;
++ else if (luai_abs(ib)==1) *r= (ic%2) ? ib:1;
++ else {
++ lua_Integer x= ib;
++ while( --ic ) {
++ if (!try_mulint( &x, x, ib ))
++ return 0; /* FP realm */
++ }
++ *r= x;
++ }
++ return 1;
++}
++
++int try_unmint( lua_Integer *r, lua_Integer ib ) {
++ /* Negating LUA_INTEGER_MIN leaves the range. */
++ if ( ib != LUA_INTEGER_MIN )
++ { *r= -ib; return 1; }
++ return 0;
++}
++
+diff -urN --exclude=.svn --exclude=.DS_Store ../lua-5.1.3/src/lnum.h lua-5.1.3-patched/src/lnum.h
+--- ../lua-5.1.3/src/lnum.h 1970-01-01 02:00:00.000000000 +0200
++++ lua-5.1.3-patched/src/lnum.h 2008-03-19 11:35:51.000000000 +0200
+@@ -0,0 +1,116 @@
++/*
++** $Id: lnum.h,v ... $
++** Internal Number model
++** See Copyright Notice in lua.h
++*/
++
++#ifndef lnum_h
++#define lnum_h
++
++#include <math.h>
++
++#include "lobject.h"
++
++/*
++** The luai_num* macros define the primitive operations over 'lua_Number's
++** (not 'lua_Integer's, not 'lua_Complex').
++*/
++#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_nummod(a,b) ((a) - _LF(floor)((a)/(b))*(b))
++#define luai_numpow(a,b) (_LF(pow)(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)))
++
++int try_addint( lua_Integer *r, lua_Integer ib, lua_Integer ic );
++int try_subint( lua_Integer *r, lua_Integer ib, lua_Integer ic );
++int try_mulint( lua_Integer *r, lua_Integer ib, lua_Integer ic );
++int try_divint( lua_Integer *r, lua_Integer ib, lua_Integer ic );
++int try_modint( lua_Integer *r, lua_Integer ib, lua_Integer ic );
++int try_powint( lua_Integer *r, lua_Integer ib, lua_Integer ic );
++int try_unmint( lua_Integer *r, lua_Integer ib );
++
++#ifdef LNUM_COMPLEX
++ static inline lua_Complex luai_vectunm( lua_Complex a ) { return -a; }
++ static inline lua_Complex luai_vectadd( lua_Complex a, lua_Complex b ) { return a+b; }
++ static inline lua_Complex luai_vectsub( lua_Complex a, lua_Complex b ) { return a-b; }
++ static inline lua_Complex luai_vectmul( lua_Complex a, lua_Complex b ) { return a*b; }
++ static inline lua_Complex luai_vectdiv( lua_Complex a, lua_Complex b ) { return a/b; }
++
++/*
++ * C99 does not provide modulus for complex numbers. It most likely is not
++ * meaningful at all.
++ */
++
++/*
++ * Complex power
++ *
++ * C99 'cpow' gives inaccurate results for many common cases s.a. (1i)^2 ->
++ * -1+1.2246467991474e-16i (OS X 10.4, gcc 4.0.1 build 5367)
++ *
++ * [(a+bi)^(c+di)] = (r^c) * exp(-d*t) * cos(c*t + d*ln(r)) +
++ * = (r^c) * exp(-d*t) * sin(c*t + d*ln(r)) *i
++ * r = sqrt(a^2+b^2), t = arctan( b/a )
++ *
++ * Reference: <http://home.att.net/~srschmitt/complexnumbers.html>
++ * Could also be calculated using: x^y = exp(ln(x)*y)
++ *
++ * Note: Defined here (and not in .c) so 'lmathlib.c' can share the
++ * implementation.
++ */
++ static inline
++ lua_Complex luai_vectpow( lua_Complex a, lua_Complex b )
++ {
++# if 1
++ lua_Number ar= _LF(creal)(a), ai= _LF(cimag)(a);
++ lua_Number br= _LF(creal)(b), bi= _LF(cimag)(b);
++
++ if (ai==0 && bi==0) { /* a^c (real) */
++ return luai_numpow( ar, br );
++ }
++
++ int br_int= (int)br;
++
++ if ( ai!=0 && bi==0 && br_int==br && br_int!=0 && br_int!=INT_MIN ) {
++ /* (a+bi)^N, N = { +-1,+-2, ... +-INT_MAX }
++ */
++ lua_Number k= luai_numpow( _LF(sqrt) (ar*ar + ai*ai), br );
++ lua_Number cos_z, sin_z;
++
++ /* Situation depends upon c (N) in the following manner:
++ *
++ * N%4==0 => cos(c*t)=1, sin(c*t)=0
++ * (N*sign(b))%4==1 or (N*sign(b))%4==-3 => cos(c*t)=0, sin(c*t)=1
++ * N%4==2 or N%4==-2 => cos(c*t)=-1, sin(c*t)=0
++ * (N*sign(b))%4==-1 or (N*sign(b))%4==3 => cos(c*t)=0, sin(c*t)=-1
++ */
++ int br_int_abs = br_int<0 ? -br_int:br_int;
++
++ switch( (br_int_abs%4) * (br_int<0 ? -1:1) * (ai<0 ? -1:1) ) {
++ case 0: cos_z=1, sin_z=0; break;
++ case 2: case -2: cos_z=-1, sin_z=0; break;
++ case 1: case -3: cos_z=0, sin_z=1; break;
++ case 3: case -1: cos_z=0, sin_z=-1; break;
++ default: lua_assert(0); return 0;
++ }
++ return k*cos_z + (k*sin_z)*I;
++ }
++# endif
++ return _LF(cpow) ( a, b );
++ }
++#endif
++
++LUAI_FUNC int luaO_str2d (const char *s, lua_Number *res1, lua_Integer *res2);
++LUAI_FUNC void luaO_num2buf( char *s, const TValue *o );
++
++LUAI_FUNC int /*bool*/ tt_integer_valued( const TValue *o, lua_Integer *ref );
++
++#define luai_normalize(o) \
++{ lua_Integer _i; if (tt_integer_valued(o,&_i)) setivalue(o,_i); }
++
++#endif
+Binary files ../lua-5.1.3/src/lnum.o and lua-5.1.3-patched/src/lnum.o differ
+diff -urN --exclude=.svn --exclude=.DS_Store ../lua-5.1.3/src/lnum_config.h lua-5.1.3-patched/src/lnum_config.h
+--- ../lua-5.1.3/src/lnum_config.h 1970-01-01 02:00:00.000000000 +0200
++++ lua-5.1.3-patched/src/lnum_config.h 2008-03-26 11:32:25.000000000 +0200
+@@ -0,0 +1,221 @@
++/*
++** $Id: lnum_config.h,v ... $
++** Internal Number model
++** See Copyright Notice in lua.h
++*/
++
++#ifndef lnum_config_h
++#define lnum_config_h
++
++/*
++** Default number modes
++*/
++#if (!defined LNUM_DOUBLE) && (!defined LNUM_FLOAT) && (!defined LNUM_LDOUBLE)
++# define LNUM_DOUBLE
++#endif
++#if (!defined LNUM_INT16) && (!defined LNUM_INT32) && (!defined LNUM_INT64)
++# define LNUM_INT32
++#endif
++
++/*
++** Require C99 mode for COMPLEX, FLOAT and LDOUBLE (only DOUBLE is ANSI C).
++*/
++#if defined(LNUM_COMPLEX) && (__STDC_VERSION__ < 199901L)
++# error "Need C99 for complex (use '--std=c99' or similar)"
++#elif defined(LNUM_LDOUBLE) && (__STDC_VERSION__ < 199901L) && !defined(_MSC_VER)
++# error "Need C99 for 'long double' (use '--std=c99' or similar)"
++#elif defined(LNUM_FLOAT) && (__STDC_VERSION__ < 199901L)
++/* LNUM_FLOAT not supported on Windows */
++# error "Need C99 for 'float' (use '--std=c99' or similar)"
++#endif
++
++/*
++** Number mode identifier to accompany the version string.
++*/
++#ifdef LNUM_COMPLEX
++# define _LNUM1 "complex "
++#else
++# define _LNUM1 ""
++#endif
++#ifdef LNUM_DOUBLE
++# define _LNUM2 "double"
++#elif defined(LNUM_FLOAT)
++# define _LNUM2 "float"
++#elif defined(LNUM_LDOUBLE)
++# define _LNUM2 "ldouble"
++#endif
++#ifdef LNUM_INT32
++# define _LNUM3 "int32"
++#elif defined(LNUM_INT64)
++# define _LNUM3 "int64"
++#elif defined(LNUM_INT16)
++# define _LNUM3 "int16"
++#endif
++#define LUA_LNUM _LNUM1 _LNUM2 " " _LNUM3
++
++/*
++** LUA_NUMBER is the type of floating point number in Lua
++** LUA_NUMBER_SCAN is the format for reading numbers.
++** LUA_NUMBER_FMT is the format for writing numbers.
++*/
++#ifdef LNUM_FLOAT
++# define LUA_NUMBER float
++# define LUA_NUMBER_SCAN "%f"
++# define LUA_NUMBER_FMT "%g"
++#elif (defined LNUM_DOUBLE)
++# define LUA_NUMBER double
++# define LUA_NUMBER_SCAN "%lf"
++# define LUA_NUMBER_FMT "%.14g"
++#elif (defined LNUM_LDOUBLE)
++# define LUA_NUMBER long double
++# define LUA_NUMBER_SCAN "%Lg"
++# define LUA_NUMBER_FMT "%.20Lg"
++#endif
++
++
++/*
++** LUAI_MAXNUMBER2STR: size of a buffer fitting any number->string result.
++**
++** double: 24 (sign, x.xxxxxxxxxxxxxxe+nnnn, and \0)
++** int64: 21 (19 digits, sign, and \0)
++** long double: 43 for 128-bit (sign, x.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxe+nnnn, and \0)
++** 30 for 80-bit (sign, x.xxxxxxxxxxxxxxxxxxxxe+nnnn, and \0)
++*/
++#ifdef LNUM_LDOUBLE
++# define _LUAI_MN2S 44
++#else
++# define _LUAI_MN2S 24
++#endif
++
++#ifdef LNUM_COMPLEX
++# define LUAI_MAXNUMBER2STR (2*_LUAI_MN2S)
++#else
++# define LUAI_MAXNUMBER2STR _LUAI_MN2S
++#endif
++
++/*
++** LUA_INTEGER is the integer type used by lua_pushinteger/lua_tointeger/lua_isinteger.
++** LUA_INTEGER_SCAN is the format for reading integers
++** LUA_INTEGER_FMT is the format for writing integers
++**
++** Note: Visual C++ 2005 does not have 'strtoull()', use '_strtoui64()' instead.
++*/
++#ifdef LNUM_INT32
++# if LUAI_BITSINT > 16
++# define LUA_INTEGER int
++# define LUA_INTEGER_SCAN "%d"
++# define LUA_INTEGER_FMT "%d"
++# else
++/* Note: 'LUA_INTEGER' being 'ptrdiff_t' (as in Lua 5.1) causes problems with
++ * 'printf()' operations. Also 'unsigned ptrdiff_t' is invalid.
++ */
++# define LUA_INTEGER long
++# define LUA_INTEGER_SCAN "%ld"
++# define LUA_INTEGER_FMT "%ld"
++# endif
++# define LUA_INTEGER_MAX 0x7FFFFFFF /* 2^31-1 */
++/* */
++#elif defined(LNUM_INT64)
++# define LUA_INTEGER long long
++# ifdef _MSC_VER
++# define lua_str2ul _strtoui64
++# else
++# define lua_str2ul strtoull
++# endif
++# define LUA_INTEGER_SCAN "%lld"
++# define LUA_INTEGER_FMT "%lld"
++# define LUA_INTEGER_MAX 0x7fffffffffffffffLL /* 2^63-1 */
++# define LUA_INTEGER_MIN (-LUA_INTEGER_MAX - 1LL) /* -2^63 */
++/* */
++#elif defined(LNUM_INT16)
++# if LUAI_BITSINT > 16
++# define LUA_INTEGER short
++# define LUA_INTEGER_SCAN "%hd"
++# define LUA_INTEGER_FMT "%hd"
++# else
++# define LUA_INTEGER int
++# define LUA_INTEGER_SCAN "%d"
++# define LUA_INTEGER_FMT "%d"
++# endif
++# define LUA_INTEGER_MAX 0x7FFF /* 2^16-1 */
++#endif
++
++#ifndef lua_str2ul
++# define lua_str2ul (unsigned LUA_INTEGER)strtoul
++#endif
++#ifndef LUA_INTEGER_MIN
++# define LUA_INTEGER_MIN (-LUA_INTEGER_MAX -1) /* -2^16|32 */
++#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(LNUM_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
++# else
++
++/* the next trick should work on any Pentium, but sometimes clashes
++ with a DirectX idiosyncrasy */
++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; }
++# endif
++
++# ifndef LNUM_INT64
++# define lua_number2integer lua_number2int
++# endif
++
++/* this option always works, but may be slow */
++#else
++# define lua_number2int(i,d) ((i)=(int)(d))
++#endif
++
++/* Note: Some compilers (OS X gcc 4.0?) may choke on double->long long conversion
++ * since it can lose precision. Others do require 'long long' there.
++ */
++#ifndef lua_number2integer
++# define lua_number2integer(i,d) ((i)=(lua_Integer)(d))
++#endif
++
++/*
++** 'luai_abs()' to give absolute value of 'lua_Integer'
++*/
++#ifdef LNUM_INT32
++# define luai_abs abs
++#elif defined(LNUM_INT64) && (__STDC_VERSION__ >= 199901L)
++# define luai_abs llabs
++#else
++# define luai_abs(v) ((v) >= 0 ? (v) : -(v))
++#endif
++
++/*
++** LUAI_UACNUMBER is the result of an 'usual argument conversion' over a number.
++** LUAI_UACINTEGER the same, over an integer.
++*/
++#define LUAI_UACNUMBER double
++#define LUAI_UACINTEGER long
++
++/* ANSI C only has math funcs for 'double. C99 required for float and long double
++ * variants.
++ */
++#ifdef LNUM_DOUBLE
++# define _LF(name) name
++#elif defined(LNUM_FLOAT)
++# define _LF(name) name ## f
++#elif defined(LNUM_LDOUBLE)
++# define _LF(name) name ## l
++#endif
++
++#endif
++
+Binary files ../lua-5.1.3/src/loadlib.o and lua-5.1.3-patched/src/loadlib.o differ
+diff -urN --exclude=.svn --exclude=.DS_Store ../lua-5.1.3/src/lobject.c lua-5.1.3-patched/src/lobject.c
+--- ../lua-5.1.3/src/lobject.c 2007-12-27 15:02:25.000000000 +0200
++++ lua-5.1.3-patched/src/lobject.c 2008-03-14 11:08:49.000000000 +0200
+@@ -21,7 +21,8 @@
+ #include "lstate.h"
+ #include "lstring.h"
+ #include "lvm.h"
+-
++#include "llex.h"
++#include "lnum.h"
+
+
+ const TValue luaO_nilobject_ = {{NULL}, LUA_TNIL};
+@@ -70,12 +71,31 @@
+
+
+ int luaO_rawequalObj (const TValue *t1, const TValue *t2) {
+- if (ttype(t1) != ttype(t2)) return 0;
++ if (!ttype_ext_same(t1,t2)) return 0;
+ else switch (ttype(t1)) {
+ case LUA_TNIL:
+ return 1;
++ case LUA_TINT:
++ if (ttype(t2)==LUA_TINT)
++ return ivalue(t1) == ivalue(t2);
++ else { /* t1:int, t2:num */
++#ifdef LNUM_COMPLEX
++ if (nvalue_img_fast(t2) != 0) return 0;
++#endif
++ /* Avoid doing accuracy losing cast, if possible. */
++ lua_Integer tmp;
++ if (tt_integer_valued(t2,&tmp))
++ return ivalue(t1) == tmp;
++ else
++ return luai_numeq( cast_num(ivalue(t1)), nvalue_fast(t2) );
++ }
+ case LUA_TNUMBER:
+- return luai_numeq(nvalue(t1), nvalue(t2));
++ if (ttype(t2)==LUA_TINT)
++ return luaO_rawequalObj(t2, t1); /* swap LUA_TINT to left */
++#ifdef LNUM_COMPLEX
++ if (!luai_numeq(nvalue_img_fast(t1), nvalue_img_fast(t2))) return 0;
++#endif
++ return luai_numeq(nvalue_fast(t1), nvalue_fast(t2));
+ case LUA_TBOOLEAN:
+ return bvalue(t1) == bvalue(t2); /* boolean true must be 1 !! */
+ case LUA_TLIGHTUSERDATA:
+@@ -86,21 +106,6 @@
+ }
+ }
+
+-
+-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);
+@@ -131,7 +136,11 @@
+ break;
+ }
+ case 'd': {
+- setnvalue(L->top, cast_num(va_arg(argp, int)));
++ /* This is tricky for 64-bit integers; maybe they even cannot be
++ * supported on all compilers; depends on the conversions applied to
++ * variable argument lists. TBD: test!
++ */
++ setivalue(L->top, (lua_Integer) va_arg(argp, l_uacInteger));
+ incr_top(L);
+ break;
+ }
+@@ -212,3 +221,4 @@
+ }
+ }
+ }
++
+diff -urN --exclude=.svn --exclude=.DS_Store ../lua-5.1.3/src/lobject.h lua-5.1.3-patched/src/lobject.h
+--- ../lua-5.1.3/src/lobject.h 2007-12-27 15:02:25.000000000 +0200
++++ lua-5.1.3-patched/src/lobject.h 2008-03-19 11:40:13.000000000 +0200
+@@ -17,7 +17,11 @@
+
+
+ /* tags for values visible from Lua */
+-#define LAST_TAG LUA_TTHREAD
++#if LUA_TINT > LUA_TTHREAD
++# define LAST_TAG LUA_TINT
++#else
++# define LAST_TAG LUA_TTHREAD
++#endif
+
+ #define NUM_TAGS (LAST_TAG+1)
+
+@@ -59,7 +63,12 @@
+ typedef union {
+ GCObject *gc;
+ void *p;
++#ifdef LNUM_COMPLEX
++ lua_Complex n;
++#else
+ lua_Number n;
++#endif
++ lua_Integer i;
+ int b;
+ } Value;
+
+@@ -77,7 +86,11 @@
+
+ /* Macros to test type */
+ #define ttisnil(o) (ttype(o) == LUA_TNIL)
+-#define ttisnumber(o) (ttype(o) == LUA_TNUMBER)
++#define ttisint(o) (ttype(o) == LUA_TINT)
++#define ttisnumber(o) ((ttype(o) == LUA_TINT) || (ttype(o) == LUA_TNUMBER))
++#ifdef LNUM_COMPLEX
++# define ttiscomplex(o) ((ttype(o) == LUA_TNUMBER) && (nvalue_img_fast(o)!=0))
++#endif
+ #define ttisstring(o) (ttype(o) == LUA_TSTRING)
+ #define ttistable(o) (ttype(o) == LUA_TTABLE)
+ #define ttisfunction(o) (ttype(o) == LUA_TFUNCTION)
+@@ -90,7 +103,25 @@
+ #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 ttype_ext(o) ( ttype(o) == LUA_TINT ? LUA_TNUMBER : ttype(o) )
++#define ttype_ext_same(o1,o2) ( (ttype(o1)==ttype(o2)) || (ttisnumber(o1) && ttisnumber(o2)) )
++
++/* '_fast' variants are for cases where 'ttype(o)' is known to be LUA_TNUMBER.
++ */
++#ifdef LNUM_COMPLEX
++# define nvalue_complex_fast(o) check_exp( ttype(o)==LUA_TNUMBER, (o)->value.n )
++# define nvalue_fast(o) ( _LF(creal) ( nvalue_complex_fast(o) ) )
++# define nvalue_img_fast(o) ( _LF(cimag) ( nvalue_complex_fast(o) ) )
++# define nvalue_complex(o) check_exp( ttisnumber(o), (ttype(o)==LUA_TINT) ? (o)->value.i : (o)->value.n )
++# define nvalue_img(o) check_exp( ttisnumber(o), (ttype(o)==LUA_TINT) ? 0 : _LF(cimag)( (o)->value.n ) )
++# define nvalue(o) check_exp( ttisnumber(o), (ttype(o)==LUA_TINT) ? cast_num((o)->value.i) : _LF(creal)((o)->value.n) )
++#else
++# define nvalue(o) check_exp( ttisnumber(o), (ttype(o)==LUA_TINT) ? cast_num((o)->value.i) : (o)->value.n )
++# define nvalue_fast(o) check_exp( ttype(o)==LUA_TNUMBER, (o)->value.n )
++#endif
++#define ivalue(o) check_exp( ttype(o)==LUA_TINT, (o)->value.i )
++
+ #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)
+@@ -116,8 +147,27 @@
+ /* 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; }
++/* Must not have side effects, 'x' may be expression.
++*/
++#define setivalue(obj,x) \
++ { TValue *i_o=(obj); i_o->value.i=(x); i_o->tt=LUA_TINT; }
++
++# define setnvalue(obj,x) \
++ { TValue *i_o=(obj); i_o->value.n= (x); i_o->tt=LUA_TNUMBER; }
++
++/* Note: Complex always has "inline", both are C99.
++*/
++#ifdef LNUM_COMPLEX
++ static inline void setnvalue_complex_fast( TValue *obj, lua_Complex x ) {
++ lua_assert( _LF(cimag)(x) != 0 );
++ obj->value.n= x; obj->tt= LUA_TNUMBER;
++ }
++ static inline void setnvalue_complex( TValue *obj, lua_Complex x ) {
++ if (_LF(cimag)(x) == 0) { setnvalue(obj, _LF(creal)(x)); }
++ else { obj->value.n= x; obj->tt= LUA_TNUMBER; }
++ }
++#endif
++
+
+ #define setpvalue(obj,x) \
+ { TValue *i_o=(obj); i_o->value.p=(x); i_o->tt=LUA_TLIGHTUSERDATA; }
+@@ -155,9 +205,6 @@
+ 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; \
+@@ -185,8 +232,11 @@
+
+ #define setttype(obj, tt) (ttype(obj) = (tt))
+
+-
+-#define iscollectable(o) (ttype(o) >= LUA_TSTRING)
++#if LUA_TINT >= LUA_TSTRING
++# define iscollectable(o) ((ttype(o) >= LUA_TSTRING) && (ttype(o) != LUA_TINT))
++#else
++# define iscollectable(o) (ttype(o) >= LUA_TSTRING)
++#endif
+
+
+
+@@ -370,12 +420,10 @@
+ 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
+
+Binary files ../lua-5.1.3/src/lobject.o and lua-5.1.3-patched/src/lobject.o differ
+Binary files ../lua-5.1.3/src/lopcodes.o and lua-5.1.3-patched/src/lopcodes.o differ
+diff -urN --exclude=.svn --exclude=.DS_Store ../lua-5.1.3/src/loslib.c lua-5.1.3-patched/src/loslib.c
+--- ../lua-5.1.3/src/loslib.c 2008-01-18 18:38:18.000000000 +0200
++++ lua-5.1.3-patched/src/loslib.c 2008-03-19 11:02:22.000000000 +0200
+@@ -186,15 +186,30 @@
+ }
+ if (t == (time_t)(-1))
+ lua_pushnil(L);
+- else
+- lua_pushnumber(L, (lua_Number)t);
++ else {
++ /* On float systems the pushed value must be an integer, NOT a number.
++ * Otherwise, accuracy is lost in the time_t->float conversion.
++ */
++#ifdef LNUM_FLOAT
++ lua_pushinteger(L, (lua_Integer) t);
++#else
++ lua_pushnumber(L, (lua_Number) t);
++#endif
++ }
+ return 1;
+ }
+
+
+ static int os_difftime (lua_State *L) {
++#ifdef LNUM_FLOAT
++ lua_Integer i= (lua_Integer)
++ difftime( (time_t)(luaL_checkinteger(L, 1)),
++ (time_t)(luaL_optinteger(L, 2, 0)));
++ lua_pushinteger(L, i);
++#else
+ lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)),
+ (time_t)(luaL_optnumber(L, 2, 0))));
++#endif
+ return 1;
+ }
+
+Binary files ../lua-5.1.3/src/loslib.o and lua-5.1.3-patched/src/loslib.o differ
+diff -urN --exclude=.svn --exclude=.DS_Store ../lua-5.1.3/src/lparser.c lua-5.1.3-patched/src/lparser.c
+--- ../lua-5.1.3/src/lparser.c 2007-12-28 17:32:23.000000000 +0200
++++ lua-5.1.3-patched/src/lparser.c 2008-03-06 21:58:41.000000000 +0200
+@@ -33,7 +33,6 @@
+
+ #define luaY_checklimit(fs,v,l,m) if ((v)>(l)) errorlimit(fs,l,m)
+
+-
+ /*
+ ** nodes for block list (list of active blocks)
+ */
+@@ -72,7 +71,7 @@
+ 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);
++ (fs->f->linedefined), limit, what);
+ luaX_lexerror(fs->ls, msg, 0);
+ }
+
+@@ -733,6 +732,18 @@
+ v->u.nval = ls->t.seminfo.r;
+ break;
+ }
++ case TK_INT: {
++ init_exp(v, VKINT, 0);
++ v->u.ival = ls->t.seminfo.i;
++ break;
++ }
++#ifdef LNUM_COMPLEX
++ case TK_NUMBER2: {
++ init_exp(v, VKNUM2, 0);
++ v->u.nval = ls->t.seminfo.r;
++ break;
++ }
++#endif
+ case TK_STRING: {
+ codestring(ls, v, ls->t.seminfo.ts);
+ break;
+@@ -1079,7 +1090,7 @@
+ if (testnext(ls, ','))
+ exp1(ls); /* optional step */
+ else { /* default step = 1 */
+- luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1));
++ luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_integerK(fs, 1));
+ luaK_reserveregs(fs, 1);
+ }
+ forbody(ls, base, line, 1, 1);
+diff -urN --exclude=.svn --exclude=.DS_Store ../lua-5.1.3/src/lparser.h lua-5.1.3-patched/src/lparser.h
+--- ../lua-5.1.3/src/lparser.h 2007-12-27 15:02:25.000000000 +0200
++++ lua-5.1.3-patched/src/lparser.h 2008-03-06 22:01:11.000000000 +0200
+@@ -31,7 +31,11 @@
+ VRELOCABLE, /* info = instruction pc */
+ VNONRELOC, /* info = result register */
+ VCALL, /* info = instruction pc */
+- VVARARG /* info = instruction pc */
++ VVARARG, /* info = instruction pc */
++ VKINT /* ival = integer value */
++#ifdef LNUM_COMPLEX
++ ,VKNUM2 /* nval = imaginary value */
++#endif
+ } expkind;
+
+ typedef struct expdesc {
+@@ -39,6 +43,7 @@
+ union {
+ struct { int info, aux; } s;
+ lua_Number nval;
++ lua_Integer ival;
+ } u;
+ int t; /* patch list of `exit when true' */
+ int f; /* patch list of `exit when false' */
+Binary files ../lua-5.1.3/src/lparser.o and lua-5.1.3-patched/src/lparser.o differ
+Binary files ../lua-5.1.3/src/lstate.o and lua-5.1.3-patched/src/lstate.o differ
+Binary files ../lua-5.1.3/src/lstring.o and lua-5.1.3-patched/src/lstring.o differ
+diff -urN --exclude=.svn --exclude=.DS_Store ../lua-5.1.3/src/lstrlib.c lua-5.1.3-patched/src/lstrlib.c
+--- ../lua-5.1.3/src/lstrlib.c 2007-12-28 17:32:23.000000000 +0200
++++ lua-5.1.3-patched/src/lstrlib.c 2008-03-12 23:15:22.000000000 +0200
+@@ -42,8 +42,8 @@
+ 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);
++ ptrdiff_t start = posrelat(luaL_checkint32(L, 2), l);
++ ptrdiff_t end = posrelat(luaL_optint32(L, 3, -1), l);
+ if (start < 1) start = 1;
+ if (end > (ptrdiff_t)l) end = (ptrdiff_t)l;
+ if (start <= end)
+@@ -105,8 +105,8 @@
+ 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);
++ ptrdiff_t posi = posrelat(luaL_optint32(L, 2, 1), l);
++ ptrdiff_t pose = posrelat(luaL_optint32(L, 3, posi), l);
+ int n, i;
+ if (posi <= 0) posi = 1;
+ if ((size_t)pose > l) pose = l;
+@@ -495,7 +495,7 @@
+ 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;
++ ptrdiff_t init = posrelat(luaL_optint32(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? */
+@@ -689,7 +689,7 @@
+ ** 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)
++#define MAX_FORMAT (sizeof(FLAGS) + sizeof(LUA_INTEGER_FMT)-2 + 10)
+
+
+ static void addquoted (lua_State *L, luaL_Buffer *b, int arg) {
+@@ -746,9 +746,9 @@
+ 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';
++ const char *tmp= LUA_INTEGER_FMT; /* "%lld" or "%ld" */
++ strcpy(form + l - 1, tmp+1);
++ form[l + sizeof(LUA_INTEGER_FMT)-4] = spec;
+ }
+
+
+@@ -776,12 +776,12 @@
+ }
+ case 'd': case 'i': {
+ addintlen(form);
+- sprintf(buff, form, (LUA_INTFRM_T)luaL_checknumber(L, arg));
++ sprintf(buff, form, luaL_checkinteger(L, arg));
+ break;
+ }
+ case 'o': case 'u': case 'x': case 'X': {
+ addintlen(form);
+- sprintf(buff, form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg));
++ sprintf(buff, form, (unsigned LUA_INTEGER)luaL_checkinteger(L, arg));
+ break;
+ }
+ case 'e': case 'E': case 'f':
+Binary files ../lua-5.1.3/src/lstrlib.o and lua-5.1.3-patched/src/lstrlib.o differ
+diff -urN --exclude=.svn --exclude=.DS_Store ../lua-5.1.3/src/ltable.c lua-5.1.3-patched/src/ltable.c
+--- ../lua-5.1.3/src/ltable.c 2007-12-28 17:32:23.000000000 +0200
++++ lua-5.1.3-patched/src/ltable.c 2008-03-26 13:04:20.000000000 +0200
+@@ -33,6 +33,7 @@
+ #include "lobject.h"
+ #include "lstate.h"
+ #include "ltable.h"
++#include "lnum.h"
+
+
+ /*
+@@ -51,25 +52,15 @@
+
+ #define hashstr(t,str) hashpow2(t, (str)->tsv.hash)
+ #define hashboolean(t,p) hashpow2(t, p)
+-
++#define hashint(t,i) hashpow2(t,i)
+
+ /*
+ ** 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_ = {
+@@ -80,27 +71,46 @@
+
+ /*
+ ** hash for lua_Numbers
++**
++** for non-complex modes, never called with 'lua_Integer' value range (s.a. 0)
+ */
+ 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]);
++ const unsigned int *p= cast(const unsigned int *,&n);
++ unsigned int sum= *p;
++ unsigned int m= sizeof(lua_Number)/sizeof(int);
++ unsigned int i;
++ /* OS X Intel has 'm'==4 and gives "Bus error" if the last integer of
++ * 'n' is read; the actual size of long double is only 80 bits = 10 bytes.
++ * Linux x86 has 'm'==3, and does not require reduction.
++ */
++#if defined(LNUM_LDOUBLE) && defined(__i386__)
++ if (m>3) m--;
++#endif
++ for (i = 1; i < m; i++) sum += p[i];
++ return hashmod(t, sum);
+ }
+
+
+-
+ /*
+ ** returns the `main' position of an element in a table (that is, the index
+ ** of its hash value)
++**
++** Floating point numbers with integer value give the hash position of the
++** integer (so they use the same table position).
+ */
+ static Node *mainposition (const Table *t, const TValue *key) {
++ lua_Integer i;
+ switch (ttype(key)) {
+ case LUA_TNUMBER:
+- return hashnum(t, nvalue(key));
++ if (tt_integer_valued(key,&i))
++ return hashint(t, i);
++#ifdef LNUM_COMPLEX
++ if (nvalue_img_fast(key)!=0 && luai_numeq(nvalue_fast(key),0))
++ return gnode(t, 0); /* 0 and -0 to give same hash */
++#endif
++ return hashnum(t, nvalue_fast(key));
++ case LUA_TINT:
++ return hashint(t, ivalue(key));
+ case LUA_TSTRING:
+ return hashstr(t, rawtsvalue(key));
+ case LUA_TBOOLEAN:
+@@ -116,16 +126,20 @@
+ /*
+ ** returns the index for `key' if `key' is an appropriate key to live in
+ ** the array part of the table, -1 otherwise.
++**
++** Anything <=0 is taken as not being in the array part.
+ */
+-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;
++static int arrayindex (const TValue *key, int max) {
++ lua_Integer k;
++ switch( ttype(key) ) {
++ case LUA_TINT:
++ k= ivalue(key); break;
++ case LUA_TNUMBER:
++ if (tt_integer_valued(key,&k)) break;
++ default:
++ return -1; /* not to be used as array index */
+ }
+- return -1; /* `key' did not match some condition */
++ return ((k>0) && (k <= max)) ? cast_int(k) : -1;
+ }
+
+
+@@ -137,8 +151,8 @@
+ 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? */
++ i = arrayindex(key, t->sizearray);
++ if (i>0) /* inside array part? */
+ return i-1; /* yes; that's the index (corrected to C) */
+ else {
+ Node *n = mainposition(t, key);
+@@ -163,7 +177,7 @@
+ 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));
++ setivalue(key, i+1);
+ setobj2s(L, key+1, &t->array[i]);
+ return 1;
+ }
+@@ -209,8 +223,8 @@
+
+
+ static int countint (const TValue *key, int *nums) {
+- int k = arrayindex(key);
+- if (0 < k && k <= MAXASIZE) { /* is `key' an appropriate array index? */
++ int k = arrayindex(key,MAXASIZE);
++ if (k>0) { /* appropriate array index? */
+ nums[ceillog2(k)]++; /* count as such */
+ return 1;
+ }
+@@ -308,7 +322,7 @@
+ /* re-insert elements from vanishing slice */
+ for (i=nasize; i<oldasize; i++) {
+ if (!ttisnil(&t->array[i]))
+- setobjt2t(L, luaH_setnum(L, t, i+1), &t->array[i]);
++ setobjt2t(L, luaH_setint(L, t, i+1), &t->array[i]);
+ }
+ /* shrink array */
+ luaM_reallocvector(L, t->array, oldasize, nasize, TValue);
+@@ -409,7 +423,9 @@
+ 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 */
++ 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 */
+@@ -432,17 +448,18 @@
+ /*
+ ** search function for integers
+ */
+-const TValue *luaH_getnum (Table *t, int key) {
++const TValue *luaH_getint (Table *t, lua_Integer 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);
++ Node *n = hashint(t, key);
+ do { /* check whether `key' is somewhere in the chain */
+- if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk))
++ if (ttisint(gkey(n)) && (ivalue(gkey(n)) == key)) {
+ return gval(n); /* that's it */
+- else n = gnext(n);
++ } else {
++ n = gnext(n);
++ }
+ } while (n);
+ return luaO_nilobject;
+ }
+@@ -470,14 +487,12 @@
+ switch (ttype(key)) {
+ case LUA_TNIL: return luaO_nilobject;
+ case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key));
++ case LUA_TINT: return luaH_getint(t, ivalue(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 */
+- }
++ lua_Integer i;
++ if (tt_integer_valued(key,&i))
++ return luaH_getint(t,i);
++ } /* pass through */
+ default: {
+ Node *n = mainposition(t, key);
+ do { /* check whether `key' is somewhere in the chain */
+@@ -498,20 +513,25 @@
+ 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");
++ else if (ttype(key)==LUA_TNUMBER) {
++ lua_Integer k;
++ if (luai_numisnan(nvalue_fast(key)))
++ luaG_runerror(L, "table index is NaN");
++ if (tt_integer_valued(key,&k))
++ return luaH_setint(L, t, k);
++ }
+ return newkey(L, t, key);
+ }
+ }
+
+
+-TValue *luaH_setnum (lua_State *L, Table *t, int key) {
+- const TValue *p = luaH_getnum(t, key);
++TValue *luaH_setint (lua_State *L, Table *t, lua_Integer key) {
++ const TValue *p = luaH_getint(t, key);
+ if (p != luaO_nilobject)
+ return cast(TValue *, p);
+ else {
+ TValue k;
+- setnvalue(&k, cast_num(key));
++ setivalue(&k, key);
+ return newkey(L, t, &k);
+ }
+ }
+@@ -533,20 +553,21 @@
+ 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))) {
++ while (!ttisnil(luaH_getint(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;
++ for( i = 1; i<MAX_INT+1; i++ ) {
++ if (ttisnil(luaH_getint(t, i))) break;
++ }
++ return i - 1; /* up to MAX_INT */
+ }
+ }
+ /* 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;
++ if (ttisnil(luaH_getint(t, m))) j = m;
+ else i = m;
+ }
+ return i;
+diff -urN --exclude=.svn --exclude=.DS_Store ../lua-5.1.3/src/ltable.h lua-5.1.3-patched/src/ltable.h
+--- ../lua-5.1.3/src/ltable.h 2007-12-27 15:02:25.000000000 +0200
++++ lua-5.1.3-patched/src/ltable.h 2008-03-16 20:49:18.000000000 +0200
+@@ -18,8 +18,8 @@
+ #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_getint (Table *t, lua_Integer key);
++LUAI_FUNC TValue *luaH_setint (lua_State *L, Table *t, lua_Integer 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);
+Binary files ../lua-5.1.3/src/ltable.o and lua-5.1.3-patched/src/ltable.o differ
+Binary files ../lua-5.1.3/src/ltablib.o and lua-5.1.3-patched/src/ltablib.o differ
+diff -urN --exclude=.svn --exclude=.DS_Store ../lua-5.1.3/src/ltm.c lua-5.1.3-patched/src/ltm.c
+--- ../lua-5.1.3/src/ltm.c 2007-12-27 15:02:25.000000000 +0200
++++ lua-5.1.3-patched/src/ltm.c 2008-03-06 22:47:33.000000000 +0200
+@@ -19,7 +19,6 @@
+ #include "ltm.h"
+
+
+-
+ const char *const luaT_typenames[] = {
+ "nil", "boolean", "userdata", "number",
+ "string", "table", "function", "userdata", "thread",
+@@ -67,6 +66,9 @@
+ case LUA_TUSERDATA:
+ mt = uvalue(o)->metatable;
+ break;
++ case LUA_TINT:
++ mt = G(L)->mt[LUA_TNUMBER];
++ break;
+ default:
+ mt = G(L)->mt[ttype(o)];
+ }
+Binary files ../lua-5.1.3/src/ltm.o and lua-5.1.3-patched/src/ltm.o differ
+diff -urN --exclude=.svn --exclude=.DS_Store ../lua-5.1.3/src/lua.c lua-5.1.3-patched/src/lua.c
+--- ../lua-5.1.3/src/lua.c 2007-12-28 17:32:23.000000000 +0200
++++ lua-5.1.3-patched/src/lua.c 2008-03-26 11:32:25.000000000 +0200
+@@ -16,7 +16,7 @@
+
+ #include "lauxlib.h"
+ #include "lualib.h"
+-
++#include "llimits.h"
+
+
+ static lua_State *globalL = NULL;
+@@ -382,6 +382,15 @@
+ l_message(argv[0], "cannot create state: not enough memory");
+ return EXIT_FAILURE;
+ }
++ /* Checking 'sizeof(lua_Integer)' cannot be made in preprocessor on all compilers.
++ */
++#ifdef LNUM_INT16
++ lua_assert( sizeof(lua_Integer) == 2 );
++#elif defined(LNUM_INT32)
++ lua_assert( sizeof(lua_Integer) == 4 );
++#elif defined(LNUM_INT64)
++ lua_assert( sizeof(lua_Integer) == 8 );
++#endif
+ s.argc = argc;
+ s.argv = argv;
+ status = lua_cpcall(L, &pmain, &s);
+diff -urN --exclude=.svn --exclude=.DS_Store ../lua-5.1.3/src/lua.h lua-5.1.3-patched/src/lua.h
+--- ../lua-5.1.3/src/lua.h 2008-01-03 17:41:15.000000000 +0200
++++ lua-5.1.3-patched/src/lua.h 2008-03-19 11:19:34.000000000 +0200
+@@ -19,7 +19,7 @@
+ #define LUA_VERSION "Lua 5.1"
+ #define LUA_RELEASE "Lua 5.1.3"
+ #define LUA_VERSION_NUM 501
+-#define LUA_COPYRIGHT "Copyright (C) 1994-2008 Lua.org, PUC-Rio"
++#define LUA_COPYRIGHT "Copyright (C) 1994-2008 Lua.org, PUC-Rio" " (" LUA_LNUM ")"
+ #define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes"
+
+
+@@ -71,6 +71,16 @@
+ */
+ #define LUA_TNONE (-1)
+
++/* LUA_TINT is an internal type, not visible to applications. There are three
++ * potential values where it can be tweaked to (code autoadjusts to these):
++ *
++ * -2: not 'usual' type value; good since 'LUA_TINT' is not part of the API
++ * LUA_TNUMBER+1: shifts other type values upwards, breaking binary compatibility
++ * not acceptable for 5.1, maybe 5.2 onwards?
++ * 9: greater than existing (5.1) type values.
++*/
++#define LUA_TINT (-2)
++
+ #define LUA_TNIL 0
+ #define LUA_TBOOLEAN 1
+ #define LUA_TLIGHTUSERDATA 2
+@@ -139,6 +149,8 @@
+ 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_isinteger) (lua_State *L, int idx);
++
+ 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);
+@@ -244,6 +256,19 @@
+ LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);
+
+
++/*
++* It is unnecessary to break Lua C API 'lua_tonumber()' compatibility, just
++* because the Lua number type is complex. Most C modules would use scalars
++* only. We'll introduce new 'lua_tocomplex' and 'lua_pushcomplex' for when
++* the module really wants to use them.
++*/
++#ifdef LNUM_COMPLEX
++ #include <complex.h>
++ typedef LUA_NUMBER complex lua_Complex;
++ LUA_API lua_Complex (lua_tocomplex) (lua_State *L, int idx);
++ LUA_API void (lua_pushcomplex) (lua_State *L, lua_Complex v);
++#endif
++
+
+ /*
+ ** ===============================================================
+@@ -268,7 +293,12 @@
+ #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)
++
++#if LUA_TINT < 0
++# define lua_isnoneornil(L, n) ( (lua_type(L,(n)) <= 0) && (lua_type(L,(n)) != LUA_TINT) )
++#else
++# define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0)
++#endif
+
+ #define lua_pushliteral(L, s) \
+ lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1)
+@@ -386,3 +416,4 @@
+
+
+ #endif
++
+Binary files ../lua-5.1.3/src/lua.o and lua-5.1.3-patched/src/lua.o differ
+Binary files ../lua-5.1.3/src/luac and lua-5.1.3-patched/src/luac differ
+Binary files ../lua-5.1.3/src/luac.o and lua-5.1.3-patched/src/luac.o differ
+diff -urN --exclude=.svn --exclude=.DS_Store ../lua-5.1.3/src/luaconf.h lua-5.1.3-patched/src/luaconf.h
+--- ../lua-5.1.3/src/luaconf.h 2008-01-18 19:07:48.000000000 +0200
++++ lua-5.1.3-patched/src/luaconf.h 2008-03-24 20:28:57.000000000 +0200
+@@ -10,7 +10,9 @@
+
+ #include <limits.h>
+ #include <stddef.h>
+-
++#ifdef lua_assert
++# include <assert.h>
++#endif
+
+ /*
+ ** ==================================================================
+@@ -136,14 +138,38 @@
+
+
+ /*
+-@@ 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.)
++@@ 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.
+ */
+-#define LUA_INTEGER ptrdiff_t
++/* avoid overflows in comparison */
++#if INT_MAX-20 < 32760
++#define LUAI_BITSINT 16
++#elif 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
+
+
+ /*
++@@ LNUM_DOUBLE | LNUM_FLOAT | LNUM_LDOUBLE: Generic Lua number mode
++@@ LNUM_INT32 | LNUM_INT64: Integer type
++@@ LNUM_COMPLEX: Define for using 'a+bi' numbers
++@@
++@@ You can combine LNUM_xxx but only one of each group. I.e. '-DLNUM_FLOAT
++@@ -DLNUM_INT32 -DLNUM_COMPLEX' gives float range complex numbers, with
++@@ 32-bit scalar integer range optimized.
++**
++** These are kept in a separate configuration file mainly for ease of patching
++** (can be changed if integerated to Lua proper).
++*/
++/*#define LNUM_DOUBLE*/
++/*#define LNUM_INT32*/
++#include "lnum_config.h"
++
++/*
+ @@ 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.
+@@ -383,22 +409,6 @@
+
+
+ /*
+-@@ 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 INT_MAX-20 < 32760
+-#define LUAI_BITSINT 16
+-#elif 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
+@@ -425,6 +435,15 @@
+ #define LUAI_MEM long
+ #endif
+
++/*
++@@ LUAI_BOOL carries 0 and nonzero (normally 1). It may be defined as 'char'
++** (to save memory), 'int' (for speed), 'bool' (for C++) or '_Bool' (C99)
++*/
++#ifdef __cplusplus
++# define LUAI_BOOL bool
++#else
++# define LUAI_BOOL int
++#endif
+
+ /*
+ @@ LUAI_MAXCALLS limits the number of nested calls.
+@@ -490,101 +509,6 @@
+ /* }================================================================== */
+
+
+-
+-
+-/*
+-** {==================================================================
+-@@ 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.
+-** ===================================================================
+-*/
+-
+-#define LUA_NUMBER_DOUBLE
+-#define LUA_NUMBER double
+-
+-/*
+-@@ LUAI_UACNUMBER is the result of an 'usual argument conversion'
+-@* over a number.
+-*/
+-#define LUAI_UACNUMBER double
+-
+-
+-/*
+-@@ 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.
+-*/
+-#define LUA_NUMBER_SCAN "%lf"
+-#define LUA_NUMBER_FMT "%.14g"
+-#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n))
+-#define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */
+-#define lua_str2number(s,p) strtod((s), (p))
+-
+-
+-/*
+-@@ The luai_num* macros define the primitive operations over numbers.
+-*/
+-#if defined(LUA_CORE)
+-#include <math.h>
+-#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_nummod(a,b) ((a) - floor((a)/(b))*(b))
+-#define luai_numpow(a,b) (pow(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)))
+-#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
+@@ -728,28 +652,6 @@
+ #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
+-
+-
+-
+ /* =================================================================== */
+
+ /*
+diff -urN --exclude=.svn --exclude=.DS_Store ../lua-5.1.3/src/lundump.c lua-5.1.3-patched/src/lundump.c
+--- ../lua-5.1.3/src/lundump.c 2008-01-18 18:39:11.000000000 +0200
++++ lua-5.1.3-patched/src/lundump.c 2008-03-26 04:33:51.000000000 +0200
+@@ -74,6 +74,13 @@
+ return x;
+ }
+
++static lua_Integer LoadInteger(LoadState* S)
++{
++ lua_Integer x;
++ LoadVar(S,x);
++ return x;
++}
++
+ static TString* LoadString(LoadState* S)
+ {
+ size_t size;
+@@ -120,6 +127,9 @@
+ case LUA_TNUMBER:
+ setnvalue(o,LoadNumber(S));
+ break;
++ case LUA_TINT: /* Integer type saved in bytecode (see lcode.c) */
++ setivalue(o,LoadInteger(S));
++ break;
+ case LUA_TSTRING:
+ setsvalue2n(S->L,o,LoadString(S));
+ break;
+@@ -221,5 +231,22 @@
+ *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? */
++
++ /*
++ * Last byte of header (0/1 in unpatched Lua 5.1.3):
++ *
++ * 0: lua_Number is float or double, lua_Integer not used. (nonpatched only)
++ * 1: lua_Number is integer (nonpatched only)
++ *
++ * +2: LNUM_INT16: sizeof(lua_Integer)
++ * +4: LNUM_INT32: sizeof(lua_Integer)
++ * +8: LNUM_INT64: sizeof(lua_Integer)
++ *
++ * +0x80: LNUM_COMPLEX
++ */
++ *h++ = (char)(sizeof(lua_Integer)
++#ifdef LNUM_COMPLEX
++ | 0x80
++#endif
++ );
+ }
+Binary files ../lua-5.1.3/src/lundump.o and lua-5.1.3-patched/src/lundump.o differ
+diff -urN --exclude=.svn --exclude=.DS_Store ../lua-5.1.3/src/lvm.c lua-5.1.3-patched/src/lvm.c
+--- ../lua-5.1.3/src/lvm.c 2007-12-28 17:32:23.000000000 +0200
++++ lua-5.1.3-patched/src/lvm.c 2008-03-14 11:13:17.000000000 +0200
+@@ -25,22 +25,35 @@
+ #include "ltable.h"
+ #include "ltm.h"
+ #include "lvm.h"
+-
+-
++#include "llex.h"
++#include "lnum.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 'obj' is a string, it is tried to be interpreted as a number.
++ */
++const TValue *luaV_tonumber ( const TValue *obj, TValue *n) {
++ lua_Number d;
++ lua_Integer i;
++
+ if (ttisnumber(obj)) return obj;
+- if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) {
+- setnvalue(n, num);
+- return n;
+- }
+- else
+- return NULL;
++
++ if (ttisstring(obj)) {
++ switch( luaO_str2d( svalue(obj), &d, &i ) ) {
++ case TK_INT:
++ setivalue(n,i); return n;
++ case TK_NUMBER:
++ setnvalue(n,d); return n;
++#ifdef LNUM_COMPLEX
++ case TK_NUMBER2: /* "N.NNNi", != 0 */
++ setnvalue_complex_fast(n, d*I); return n;
++#endif
++ }
++ }
++ return NULL;
+ }
+
+
+@@ -49,8 +62,7 @@
+ return 0;
+ else {
+ char s[LUAI_MAXNUMBER2STR];
+- lua_Number n = nvalue(obj);
+- lua_number2str(s, n);
++ luaO_num2buf(s,obj);
+ setsvalue2s(L, obj, luaS_new(L, s));
+ return 1;
+ }
+@@ -218,59 +230,127 @@
+ }
+
+
++#ifdef LNUM_COMPLEX
++void error_complex( lua_State *L, const TValue *l, const TValue *r )
++{
++ char buf1[ LUAI_MAXNUMBER2STR ];
++ char buf2[ LUAI_MAXNUMBER2STR ];
++ luaO_num2buf( buf1, l );
++ luaO_num2buf( buf2, r );
++ luaG_runerror( L, "unable to compare: %s with %s", buf1, buf2 );
++ /* no return */
++}
++#endif
++
++
+ int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) {
+ int res;
+- if (ttype(l) != ttype(r))
++ int tl,tr;
++ lua_Integer tmp;
++
++ if (!ttype_ext_same(l,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)
++#ifdef LNUM_COMPLEX
++ if ( (nvalue_img(l)!=0) || (nvalue_img(r)!=0) )
++ error_complex( L, l, r );
++#endif
++ tl= ttype(l); tr= ttype(r);
++ if (tl==tr) { /* clear arithmetics */
++ switch(tl) {
++ case LUA_TINT: return ivalue(l) < ivalue(r);
++ case LUA_TNUMBER: return luai_numlt(nvalue_fast(l), nvalue_fast(r));
++ case LUA_TSTRING: return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0;
++ }
++ } else if (tl==LUA_TINT) { /* l:int, r:num */
++ /* Avoid accuracy losing casts: if 'r' is integer by value, do comparisons
++ * in integer realm. Only otherwise cast 'l' to FP (which might change its
++ * value).
++ */
++ if (tt_integer_valued(r,&tmp))
++ return ivalue(l) < tmp;
++ else
++ return luai_numlt( cast_num(ivalue(l)), nvalue_fast(r) );
++
++ } else if (tl==LUA_TNUMBER) { /* l:num, r:int */
++ if (tt_integer_valued(l,&tmp))
++ return tmp < ivalue(r);
++ else
++ return luai_numlt( nvalue_fast(l), cast_num(ivalue(r)) );
++
++ } 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))
++ int tl, tr;
++ lua_Integer tmp;
++
++ if (!ttype_ext_same(l,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' */
++#ifdef LNUM_COMPLEX
++ if ( (nvalue_img(l)!=0) || (nvalue_img(r)!=0) )
++ error_complex( L, l, r );
++#endif
++ tl= ttype(l); tr= ttype(r);
++ if (tl==tr) { /* clear arithmetics */
++ switch(tl) {
++ case LUA_TINT: return ivalue(l) <= ivalue(r);
++ case LUA_TNUMBER: return luai_numle(nvalue_fast(l), nvalue_fast(r));
++ case LUA_TSTRING: return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0;
++ }
++ }
++ if (tl==LUA_TINT) { /* l:int, r:num */
++ if (tt_integer_valued(r,&tmp))
++ return ivalue(l) <= tmp;
++ else
++ return luai_numle( cast_num(ivalue(l)), nvalue_fast(r) );
++
++ } else if (tl==LUA_TNUMBER) { /* l:num, r:int */
++ if (tt_integer_valued(l,&tmp))
++ return tmp <= ivalue(r);
++ else
++ return luai_numle( nvalue_fast(l), cast_num(ivalue(r)) );
++
++ } 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) {
++/* Note: 'luaV_equalval()' and 'luaO_rawequalObj()' have largely overlapping
++ * implementation. LUA_TNIL..LUA_TLIGHTUSERDATA cases could be handled
++ * simply by the 'default' case here.
++ */
++int luaV_equalval (lua_State *L, const TValue *l, const TValue *r) {
+ const TValue *tm;
+- lua_assert(ttype(t1) == ttype(t2));
+- switch (ttype(t1)) {
++ lua_assert(ttype_ext_same(l,r));
++ switch (ttype(l)) {
+ 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_TINT:
++ case LUA_TNUMBER: return luaO_rawequalObj(l,r);
++ case LUA_TBOOLEAN: return bvalue(l) == bvalue(r); /* true must be 1 !! */
++ case LUA_TLIGHTUSERDATA: return pvalue(l) == pvalue(r);
+ case LUA_TUSERDATA: {
+- if (uvalue(t1) == uvalue(t2)) return 1;
+- tm = get_compTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable,
+- TM_EQ);
++ if (uvalue(l) == uvalue(r)) return 1;
++ tm = get_compTM(L, uvalue(l)->metatable, uvalue(r)->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);
++ if (hvalue(l) == hvalue(r)) return 1;
++ tm = get_compTM(L, hvalue(l)->metatable, hvalue(r)->metatable, TM_EQ);
+ break; /* will try TM */
+ }
+- default: return gcvalue(t1) == gcvalue(t2);
++ default: return gcvalue(l) == gcvalue(r);
+ }
+ if (tm == NULL) return 0; /* no TM? */
+- callTMres(L, L->top, tm, t1, t2); /* call TM */
++ callTMres(L, L->top, tm, l, r); /* call TM */
+ return !l_isfalse(L->top);
+ }
+
+@@ -310,30 +390,6 @@
+ }
+
+
+-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'
+ */
+@@ -357,17 +413,154 @@
+ #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)); \
++/* Note: if called for unary operations, 'rc'=='rb'.
++ */
++static void Arith (lua_State *L, StkId ra, const TValue *rb,
++ const TValue *rc, TMS op) {
++ TValue tempb, tempc;
++ const TValue *b, *c;
++ lua_Number nb,nc;
++
++ if ((b = luaV_tonumber(rb, &tempb)) != NULL &&
++ (c = luaV_tonumber(rc, &tempc)) != NULL) {
++
++ /* Keep integer arithmetics in the integer realm, if possible.
++ */
++ if (ttisint(b) && ttisint(c)) {
++ lua_Integer ib = ivalue(b), ic = ivalue(c);
++ lua_Integer *ri = &ra->value.i;
++ ra->tt= LUA_TINT; /* part of 'setivalue(ra)' */
++ switch (op) {
++ case TM_ADD: if (try_addint( ri, ib, ic)) return; break;
++ case TM_SUB: if (try_subint( ri, ib, ic)) return; break;
++ case TM_MUL: if (try_mulint( ri, ib, ic)) return; break;
++ case TM_DIV: if (try_divint( ri, ib, ic)) return; break;
++ case TM_MOD: if (try_modint( ri, ib, ic)) return; break;
++ case TM_POW: if (try_powint( ri, ib, ic)) return; break;
++ case TM_UNM: if (try_unmint( ri, ib)) return; break;
++ default: lua_assert(0);
++ }
++ }
++ /* Fallback to floating point, when leaving range. */
++
++#ifdef LNUM_COMPLEX
++ if ((nvalue_img(b)!=0) || (nvalue_img(c)!=0)) {
++ lua_Complex r;
++ if (op==TM_UNM) {
++ r= -nvalue_complex_fast(b); /* never an integer (or scalar) */
++ setnvalue_complex_fast( ra, r );
++ } else {
++ lua_Complex bb= nvalue_complex(b), cc= nvalue_complex(c);
++ switch (op) {
++ case TM_ADD: r= bb + cc; break;
++ case TM_SUB: r= bb - cc; break;
++ case TM_MUL: r= bb * cc; break;
++ case TM_DIV: r= bb / cc; break;
++ case TM_MOD:
++ luaG_runerror(L, "attempt to use %% on complex numbers"); /* no return */
++ case TM_POW: r= luai_vectpow( bb, cc ); break;
++ default: lua_assert(0); r=0;
++ }
++ setnvalue_complex( ra, r );
+ }
++ return;
++ }
++#endif
++ nb = nvalue(b); nc = nvalue(c);
++ switch (op) {
++ case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); return;
++ case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); return;
++ case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); return;
++ case TM_DIV: setnvalue(ra, luai_numdiv(nb, nc)); return;
++ case TM_MOD: setnvalue(ra, luai_nummod(nb, nc)); return;
++ case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); return;
++ case TM_UNM: setnvalue(ra, luai_numunm(nb)); return;
++ default: lua_assert(0);
++ }
++ }
++
++ /* Either operand not a number */
++ if (!call_binTM(L, rb, rc, ra, op))
++ luaG_aritherror(L, rb, rc);
++}
+
++/* Helper macro to sort arithmetic operations into four categories:
++ * TK_INT: integer - integer operands
++ * TK_NUMBER: number - number (non complex, either may be integer)
++ * TK_NUMBER2: complex numbers (at least the other)
++ * 0: non-numeric (at least the other)
++*/
++#ifdef LNUM_COMPLEX
++static inline int arith_mode( const TValue *rb, const TValue *rc ) {
++ if (ttisint(rb) && ttisint(rc)) return TK_INT;
++ if (ttiscomplex(rb) || ttiscomplex(rc)) return TK_NUMBER2;
++ if (ttisnumber(rb) && ttisnumber(rc)) return TK_NUMBER;
++ return 0;
++}
++#else
++# define arith_mode(rb,rc) \
++ ( (ttisint(rb) && ttisint(rc)) ? TK_INT : \
++ (ttisnumber(rb) && ttisnumber(rc)) ? TK_NUMBER : 0 )
++#endif
++
++/* arith_op macro for two operators:
++ * automatically chooses, which function (number, integer, complex) to use
++ */
++#define ARITH_OP2_START( op_num, op_int ) \
++ int failed= 0; \
++ switch( arith_mode(rb,rc) ) { \
++ case TK_INT: \
++ if (op_int ( &(ra)->value.i, ivalue(rb), ivalue(rc) )) \
++ { ra->tt= LUA_TINT; break; } /* else flow through */ \
++ case TK_NUMBER: \
++ setnvalue(ra, op_num ( nvalue(rb), nvalue(rc) )); break;
++
++#define ARITH_OP2_END \
++ default: \
++ failed= 1; break; \
++ } if (!failed) continue;
++
++#define arith_op_continue_scalar( op_num, op_int ) \
++ ARITH_OP2_START( op_num, op_int ) \
++ ARITH_OP2_END
++
++#ifdef LNUM_COMPLEX
++# define arith_op_continue( op_num, op_int, op_complex ) \
++ ARITH_OP2_START( op_num, op_int ) \
++ case TK_NUMBER2: \
++ setnvalue_complex( ra, op_complex ( nvalue_complex(rb), nvalue_complex(rc) ) ); break; \
++ ARITH_OP2_END
++#else
++# define arith_op_continue(op_num,op_int,_) arith_op_continue_scalar(op_num,op_int)
++#endif
++
++/* arith_op macro for one operator:
++ */
++#define ARITH_OP1_START( op_num, op_int ) \
++ int failed= 0; \
++ switch( arith_mode(rb,rb) ) { \
++ case TK_INT: \
++ if (op_int ( &(ra)->value.i, ivalue(rb) )) \
++ { ra->tt= LUA_TINT; break; } /* else flow through */ \
++ case TK_NUMBER: \
++ setnvalue(ra, op_num (nvalue(rb))); break; \
++
++#define ARITH_OP1_END \
++ default: \
++ failed= 1; break; \
++ } if (!failed) continue;
++
++#ifdef LNUM_COMPLEX
++# define arith_op1_continue( op_num, op_int, op_complex ) \
++ ARITH_OP1_START( op_num, op_int ) \
++ case TK_NUMBER2: \
++ setnvalue_complex( ra, op_complex ( nvalue_complex_fast(rb) )); break; \
++ ARITH_OP1_END
++#else
++# define arith_op1_continue( op_num, op_int, _ ) \
++ ARITH_OP1_START( op_num, op_int ) \
++ ARITH_OP1_END
++#endif
+
+
+ void luaV_execute (lua_State *L, int nexeccalls) {
+@@ -468,38 +661,45 @@
+ continue;
+ }
+ case OP_ADD: {
+- arith_op(luai_numadd, TM_ADD);
++ TValue *rb = RKB(i), *rc= RKC(i);
++ arith_op_continue( luai_numadd, try_addint, luai_vectadd );
++ Protect(Arith(L, ra, rb, rc, TM_ADD)); \
+ continue;
+ }
+ case OP_SUB: {
+- arith_op(luai_numsub, TM_SUB);
++ TValue *rb = RKB(i), *rc= RKC(i);
++ arith_op_continue( luai_numsub, try_subint, luai_vectsub );
++ Protect(Arith(L, ra, rb, rc, TM_SUB));
+ continue;
+ }
+ case OP_MUL: {
+- arith_op(luai_nummul, TM_MUL);
++ TValue *rb = RKB(i), *rc= RKC(i);
++ arith_op_continue(luai_nummul, try_mulint, luai_vectmul);
++ Protect(Arith(L, ra, rb, rc, TM_MUL));
+ continue;
+ }
+ case OP_DIV: {
+- arith_op(luai_numdiv, TM_DIV);
++ TValue *rb = RKB(i), *rc= RKC(i);
++ arith_op_continue(luai_numdiv, try_divint, luai_vectdiv);
++ Protect(Arith(L, ra, rb, rc, TM_DIV));
+ continue;
+ }
+ case OP_MOD: {
+- arith_op(luai_nummod, TM_MOD);
++ TValue *rb = RKB(i), *rc= RKC(i);
++ arith_op_continue_scalar(luai_nummod, try_modint); /* scalars only */
++ Protect(Arith(L, ra, rb, rc, TM_MOD));
+ continue;
+ }
+ case OP_POW: {
+- arith_op(luai_numpow, TM_POW);
++ TValue *rb = RKB(i), *rc= RKC(i);
++ arith_op_continue(luai_numpow, try_powint, luai_vectpow);
++ Protect(Arith(L, ra, rb, rc, 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));
+- }
++ arith_op1_continue(luai_numunm, try_unmint, luai_vectunm);
++ Protect(Arith(L, ra, rb, rb, TM_UNM));
+ continue;
+ }
+ case OP_NOT: {
+@@ -511,11 +711,11 @@
+ const TValue *rb = RB(i);
+ switch (ttype(rb)) {
+ case LUA_TTABLE: {
+- setnvalue(ra, cast_num(luaH_getn(hvalue(rb))));
++ setivalue(ra, luaH_getn(hvalue(rb)));
+ break;
+ }
+ case LUA_TSTRING: {
+- setnvalue(ra, cast_num(tsvalue(rb)->len));
++ setivalue(ra, tsvalue(rb)->len);
+ break;
+ }
+ default: { /* try metamethod */
+@@ -648,14 +848,30 @@
+ }
+ }
+ 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 */
++ /* If start,step and limit are all integers, we don't need to check
++ * against overflow in the looping.
++ */
++ if (ttisint(ra) && ttisint(ra+1) && ttisint(ra+2)) {
++ lua_Integer step = ivalue(ra+2);
++ lua_Integer idx = ivalue(ra) + step; /* increment index */
++ lua_Integer limit = ivalue(ra+1);
++ if (step > 0 ? (idx <= limit) : (limit <= idx)) {
++ dojump(L, pc, GETARG_sBx(i)); /* jump back */
++ setivalue(ra, idx); /* update internal index... */
++ setivalue(ra+3, idx); /* ...and external index */
++ }
++ } else {
++ /* non-integer looping (don't use 'nvalue_fast', some may be integer!)
++ */
++ 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;
+ }
+@@ -664,13 +880,21 @@
+ const TValue *plimit = ra+1;
+ const TValue *pstep = ra+2;
+ L->savedpc = pc; /* next steps may throw errors */
++ /* Using same location for tonumber's both arguments, effectively does
++ * in-place modification (string->number). */
+ 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)));
++ /* Step back one value (keep within integers if we can)
++ */
++ if (!( ttisint(ra) && ttisint(pstep) &&
++ try_subint( &ra->value.i, ivalue(ra), ivalue(pstep) ) )) {
++ /* don't use 'nvalue_fast()', values may be integer */
++ setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep)));
++ }
+ dojump(L, pc, GETARG_sBx(i));
+ continue;
+ }
+@@ -707,7 +931,7 @@
+ 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);
++ setobj2t(L, luaH_setint(L, h, last--), val);
+ luaC_barriert(L, h, val);
+ }
+ continue;
+diff -urN --exclude=.svn --exclude=.DS_Store ../lua-5.1.3/src/lvm.h lua-5.1.3-patched/src/lvm.h
+--- ../lua-5.1.3/src/lvm.h 2007-12-27 15:02:25.000000000 +0200
++++ lua-5.1.3-patched/src/lvm.h 2008-03-19 10:49:34.000000000 +0200
+@@ -15,11 +15,9 @@
+
+ #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 tonumber(o,n) (ttisnumber(o) || (((o) = luaV_tonumber(o,n)) != NULL))
+
+-#define equalobj(L,o1,o2) \
+- (ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2))
++#define equalobj(L,o1,o2) (ttype_ext_same(o1,o2) && luaV_equalval(L, o1, o2))
+
+
+ LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r);
+Binary files ../lua-5.1.3/src/lvm.o and lua-5.1.3-patched/src/lvm.o differ
+Binary files ../lua-5.1.3/src/lzio.o and lua-5.1.3-patched/src/lzio.o differ
+diff -urN --exclude=.svn --exclude=.DS_Store ../lua-5.1.3/src/print.c lua-5.1.3-patched/src/print.c
+--- ../lua-5.1.3/src/print.c 2007-03-26 03:17:38.000000000 +0300
++++ lua-5.1.3-patched/src/print.c 2008-03-19 11:04:51.000000000 +0200
+@@ -14,6 +14,7 @@
+ #include "lobject.h"
+ #include "lopcodes.h"
+ #include "lundump.h"
++#include "lnum.h"
+
+ #define PrintFunction luaU_print
+
+@@ -59,8 +60,16 @@
+ case LUA_TBOOLEAN:
+ printf(bvalue(o) ? "true" : "false");
+ break;
++ case LUA_TINT:
++ printf(LUA_INTEGER_FMT,ivalue(o));
++ break;
+ case LUA_TNUMBER:
+- printf(LUA_NUMBER_FMT,nvalue(o));
++#ifdef LNUM_COMPLEX
++ // TBD: Do we get complex values here?
++ { lua_Number b= nvalue_img_fast(o);
++ printf( LUA_NUMBER_FMT "%s" LUA_NUMBER_FMT "i", nvalue_fast(o), b>=0 ? "+":"", b ); }
++#endif
++ printf(LUA_NUMBER_FMT,nvalue_fast(o));
+ break;
+ case LUA_TSTRING:
+ PrintString(rawtsvalue(o));
+Binary files ../lua-5.1.3/src/print.o and lua-5.1.3-patched/src/print.o differ
diff --git a/contrib/package/lua-luci/patches/020-shared_liblua.patch b/contrib/package/lua-luci/patches/020-shared_liblua.patch
new file mode 100644
index 000000000..7942e8760
--- /dev/null
+++ b/contrib/package/lua-luci/patches/020-shared_liblua.patch
@@ -0,0 +1,139 @@
+diff -ur lua-5.1.3-pt1/Makefile lua-5.1.3-pt2/Makefile
+--- lua-5.1.3-pt1/Makefile 2008-04-05 14:23:14.000000000 +0200
++++ lua-5.1.3-pt2/Makefile 2008-04-05 15:13:38.000000000 +0200
+@@ -37,8 +37,8 @@
+
+ # What to install.
+ TO_BIN= lua luac
+-TO_INC= lua.h luaconf.h lualib.h lauxlib.h ../etc/lua.hpp
+-TO_LIB= liblua.a
++TO_INC= lua.h luaconf.h lualib.h lauxlib.h ../etc/lua.hpp lnum_config.h
++TO_LIB= liblua.a liblua.so liblua.so.$R
+ TO_MAN= lua.1 luac.1
+
+ # Lua version and release.
+diff -ur lua-5.1.3-pt1/src/ldo.h lua-5.1.3-pt2/src/ldo.h
+--- lua-5.1.3-pt1/src/ldo.h 2008-04-05 14:23:14.000000000 +0200
++++ lua-5.1.3-pt2/src/ldo.h 2008-04-05 14:25:40.000000000 +0200
+@@ -46,7 +46,7 @@
+ 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);
++LUA_API 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);
+diff -ur lua-5.1.3-pt1/src/lfunc.h lua-5.1.3-pt2/src/lfunc.h
+--- lua-5.1.3-pt1/src/lfunc.h 2008-04-05 14:23:14.000000000 +0200
++++ lua-5.1.3-pt2/src/lfunc.h 2008-04-05 14:25:40.000000000 +0200
+@@ -18,7 +18,7 @@
+ cast(int, sizeof(TValue *)*((n)-1)))
+
+
+-LUAI_FUNC Proto *luaF_newproto (lua_State *L);
++LUA_API 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);
+diff -ur lua-5.1.3-pt1/src/lmem.h lua-5.1.3-pt2/src/lmem.h
+--- lua-5.1.3-pt1/src/lmem.h 2008-04-05 14:23:14.000000000 +0200
++++ lua-5.1.3-pt2/src/lmem.h 2008-04-05 14:25:40.000000000 +0200
+@@ -38,9 +38,9 @@
+ ((v)=cast(t *, luaM_reallocv(L, v, oldn, n, sizeof(t))))
+
+
+-LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize,
++LUA_API void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize,
+ size_t size);
+-LUAI_FUNC void *luaM_toobig (lua_State *L);
++LUA_API 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);
+diff -ur lua-5.1.3-pt1/src/lstring.h lua-5.1.3-pt2/src/lstring.h
+--- lua-5.1.3-pt1/src/lstring.h 2008-04-05 14:23:14.000000000 +0200
++++ lua-5.1.3-pt2/src/lstring.h 2008-04-05 14:25:40.000000000 +0200
+@@ -25,7 +25,7 @@
+
+ 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);
++LUA_API TString *luaS_newlstr (lua_State *L, const char *str, size_t l);
+
+
+ #endif
+diff -ur lua-5.1.3-pt1/src/lundump.h lua-5.1.3-pt2/src/lundump.h
+--- lua-5.1.3-pt1/src/lundump.h 2008-04-05 14:23:14.000000000 +0200
++++ lua-5.1.3-pt2/src/lundump.h 2008-04-05 14:25:40.000000000 +0200
+@@ -17,7 +17,7 @@
+ 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);
++LUA_API 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 */
+diff -ur lua-5.1.3-pt1/src/Makefile lua-5.1.3-pt2/src/Makefile
+--- lua-5.1.3-pt1/src/Makefile 2008-04-05 14:23:31.000000000 +0200
++++ lua-5.1.3-pt2/src/Makefile 2008-04-05 14:25:40.000000000 +0200
+@@ -23,6 +23,7 @@
+ PLATS= aix ansi bsd freebsd generic linux macosx mingw posix solaris
+
+ LUA_A= liblua.a
++LUA_SO= liblua.so
+ CORE_O= lapi.o lcode.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o \
+ lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o \
+ lundump.o lvm.o lzio.o lnum.o
+@@ -33,11 +34,12 @@
+ LUA_O= lua.o
+
+ LUAC_T= luac
+-LUAC_O= luac.o print.o
++LUAC_O= luac.o print.o lopcodes.o
+
+ ALL_O= $(CORE_O) $(LIB_O) $(LUA_O) $(LUAC_O)
+-ALL_T= $(LUA_A) $(LUA_T) $(LUAC_T)
++ALL_T= $(LUA_A) $(LUA_SO) $(LUA_T) $(LUAC_T)
+ ALL_A= $(LUA_A)
++ALL_SO= $(LUA_SO)
+
+ default: $(PLAT)
+
+@@ -47,14 +49,23 @@
+
+ a: $(ALL_A)
+
++so: $(ALL_SO)
++
+ $(LUA_A): $(CORE_O) $(LIB_O)
+ $(AR) $@ $?
+ $(RANLIB) $@
+
+-$(LUA_T): $(LUA_O) $(LUA_A)
+- $(CC) -o $@ $(MYLDFLAGS) $(LUA_O) $(LUA_A) $(LIBS)
++$(LUA_SO): $(CORE_O) $(LIB_O)
++ $(LD) -o $@.$(PKG_VERSION) -shared -soname="$@.$(PKG_VERSION)" $?
++ ln -fs $@.$(PKG_VERSION) $@
++
++$(LUA_T): $(LUA_O) $(LUA_SO)
++ $(CC) -o $@ -L. -llua $(MYLDFLAGS) $(LUA_O) $(LIBS)
++
++$(LUAC_T): $(LUAC_O) $(LUA_SO)
++ $(CC) -o $@ -L. -llua $(MYLDFLAGS) $(LUAC_O) $(LIBS)
+
+-$(LUAC_T): $(LUAC_O) $(LUA_A)
++$(LUAC_T)-host: $(LUAC_O) $(LUA_A)
+ $(CC) -o $@ $(MYLDFLAGS) $(LUAC_O) $(LUA_A) $(LIBS)
+
+ clean:
+@@ -96,7 +107,7 @@
+ $(MAKE) all MYCFLAGS=
+
+ linux:
+- $(MAKE) all MYCFLAGS=-DLUA_USE_LINUX MYLIBS="-Wl,-E -ldl -lreadline -lhistory -lncurses"
++ $(MAKE) all MYCFLAGS+=-DLUA_USE_LINUX MYLIBS="-Wl,-E -ldl -lreadline -lhistory -lncurses"
+
+ macosx:
+ $(MAKE) all MYCFLAGS=-DLUA_USE_LINUX MYLIBS="-lreadline"
diff --git a/contrib/package/lua-luci/patches/030-archindependent-bytecode.patch b/contrib/package/lua-luci/patches/030-archindependent-bytecode.patch
new file mode 100644
index 000000000..4ba58ebfb
--- /dev/null
+++ b/contrib/package/lua-luci/patches/030-archindependent-bytecode.patch
@@ -0,0 +1,113 @@
+diff -ur lua-5.1.3-pt2/src/ldump.c lua-5.1.3-pt3/src/ldump.c
+--- lua-5.1.3-pt2/src/ldump.c 2008-04-05 14:25:13.000000000 +0200
++++ lua-5.1.3-pt3/src/ldump.c 2008-04-05 14:28:27.000000000 +0200
+@@ -67,12 +67,12 @@
+ {
+ if (s==NULL || getstr(s)==NULL)
+ {
+- size_t size=0;
++ unsigned int size=0;
+ DumpVar(size,D);
+ }
+ else
+ {
+- size_t size=s->tsv.len+1; /* include trailing '\0' */
++ unsigned int size=s->tsv.len+1; /* include trailing '\0' */
+ DumpVar(size,D);
+ DumpBlock(getstr(s),size,D);
+ }
+diff -ur lua-5.1.3-pt2/src/lundump.c lua-5.1.3-pt3/src/lundump.c
+--- lua-5.1.3-pt2/src/lundump.c 2008-04-05 14:25:13.000000000 +0200
++++ lua-5.1.3-pt3/src/lundump.c 2008-04-05 14:28:27.000000000 +0200
+@@ -25,6 +25,7 @@
+ ZIO* Z;
+ Mbuffer* b;
+ const char* name;
++ int swap;
+ } LoadState;
+
+ #ifdef LUAC_TRUST_BINARIES
+@@ -40,7 +41,6 @@
+ }
+ #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)
+@@ -52,6 +52,49 @@
+ IF (r!=0, "unexpected end");
+ }
+
++static void LoadMem (LoadState* S, void* b, int n, size_t size)
++{
++ LoadBlock(S,b,n*size);
++ if (S->swap)
++ {
++ char* p=(char*) b;
++ char c;
++ switch (size)
++ {
++ case 1:
++ break;
++ case 2:
++ while (n--)
++ {
++ c=p[0]; p[0]=p[1]; p[1]=c;
++ p+=2;
++ }
++ break;
++ case 4:
++ while (n--)
++ {
++ c=p[0]; p[0]=p[3]; p[3]=c;
++ c=p[1]; p[1]=p[2]; p[2]=c;
++ p+=4;
++ }
++ break;
++ case 8:
++ while (n--)
++ {
++ c=p[0]; p[0]=p[7]; p[7]=c;
++ c=p[1]; p[1]=p[6]; p[6]=c;
++ c=p[2]; p[2]=p[5]; p[5]=c;
++ c=p[3]; p[3]=p[4]; p[4]=c;
++ p+=8;
++ }
++ break;
++ default:
++ IF(1, "bad size");
++ break;
++ }
++ }
++}
++
+ static int LoadChar(LoadState* S)
+ {
+ char x;
+@@ -83,7 +126,7 @@
+
+ static TString* LoadString(LoadState* S)
+ {
+- size_t size;
++ unsigned int size;
+ LoadVar(S,size);
+ if (size==0)
+ return NULL;
+@@ -194,6 +237,7 @@
+ char s[LUAC_HEADERSIZE];
+ luaU_header(h);
+ LoadBlock(S,s,LUAC_HEADERSIZE);
++ S->swap=(s[6]!=h[6]); s[6]=h[6];
+ IF (memcmp(h,s,LUAC_HEADERSIZE)!=0, "bad header");
+ }
+
+@@ -228,7 +272,7 @@
+ *h++=(char)LUAC_FORMAT;
+ *h++=(char)*(char*)&x; /* endianness */
+ *h++=(char)sizeof(int);
+- *h++=(char)sizeof(size_t);
++ *h++=(char)sizeof(unsigned int);
+ *h++=(char)sizeof(Instruction);
+ *h++=(char)sizeof(lua_Number);
+
diff --git a/contrib/package/lua-luci/patches/100-no_readline.patch b/contrib/package/lua-luci/patches/100-no_readline.patch
new file mode 100644
index 000000000..7368187d8
--- /dev/null
+++ b/contrib/package/lua-luci/patches/100-no_readline.patch
@@ -0,0 +1,53 @@
+diff -ur lua-luci-5.1.3/src/luaconf.h lua-luci-5.1.3-new/src/luaconf.h
+--- lua-luci-5.1.3/src/luaconf.h 2008-04-14 13:19:54.000000000 +0200
++++ lua-luci-5.1.3-new/src/luaconf.h 2008-04-14 13:19:17.000000000 +0200
+@@ -38,7 +38,6 @@
+ #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)
+Nur in lua-luci-5.1.3-new/src: luaconf.h.orig.
+diff -ur lua-luci-5.1.3/src/Makefile lua-luci-5.1.3-new/src/Makefile
+--- lua-luci-5.1.3/src/Makefile 2008-04-14 13:19:57.000000000 +0200
++++ lua-luci-5.1.3-new/src/Makefile 2008-04-14 13:19:17.000000000 +0200
+@@ -17,6 +17,7 @@
+ MYCFLAGS=
+ MYLDFLAGS=
+ MYLIBS=
++# USE_READLINE=1
+
+ # == END OF USER SETTINGS. NO NEED TO CHANGE ANYTHING BELOW THIS LINE =========
+
+@@ -86,7 +87,7 @@
+ @echo "MYLIBS = $(MYLIBS)"
+
+ # convenience targets for popular platforms
+-
++RFLAG=$(if $(USE_READLINE),-DLUA_USE_READLINE)
+ none:
+ @echo "Please choose a platform:"
+ @echo " $(PLATS)"
+@@ -101,16 +102,16 @@
+ $(MAKE) all MYCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" MYLIBS="-Wl,-E"
+
+ freebsd:
+- $(MAKE) all MYCFLAGS="-DLUA_USE_LINUX" MYLIBS="-Wl,-E -lreadline"
++ $(MAKE) all MYCFLAGS="-DLUA_USE_LINUX $(RFLAG)" MYLIBS="-Wl,-E$(if $(USE_READLINE), -lreadline)"
+
+ generic:
+ $(MAKE) all MYCFLAGS=
+
+ linux:
+- $(MAKE) all MYCFLAGS+=-DLUA_USE_LINUX MYLIBS="-Wl,-E -ldl -lreadline -lhistory -lncurses"
++ $(MAKE) all MYCFLAGS+="-DLUA_USE_LINUX $(RFLAG)" MYLIBS="-Wl,-E -ldl $(if $(USE_READLINE), -lreadline -lhistory -lncurses)"
+
+ macosx:
+- $(MAKE) all MYCFLAGS=-DLUA_USE_LINUX MYLIBS="-lreadline"
++ $(MAKE) all MYCFLAGS=-DLUA_USE_LINUX $(if $(USE_READLINE), MYLIBS="-lreadline")
+ # use this on Mac OS X 10.3-
+ # $(MAKE) all MYCFLAGS=-DLUA_USE_MACOSX
+
+Nur in lua-luci-5.1.3-new/src: Makefile.orig.
diff --git a/contrib/package/luaposix/Makefile b/contrib/package/luaposix/Makefile
new file mode 100644
index 000000000..2eef3ad08
--- /dev/null
+++ b/contrib/package/luaposix/Makefile
@@ -0,0 +1,44 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=luaposix
+PKG_VERSION:=5.1.2
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://luaforge.net/frs/download.php/3063
+PKG_MD5SUM:=31deeb4add91f76b3c2d36aae2888d81
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+PKG_INSTALL_DIR:=$(PKG_BUILD_DIR)/ipkg-install
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/luaposix
+ SECTION:=lib
+ CATEGORY:=Libraries
+ TITLE:=Lua Posix library
+ URL:=http://luaforge.net/projects/luaposix/
+ DEPENDS:=+liblua-luci
+ MAINTAINER:=Steven Barth <steven-at-midlink-dot-org>
+endef
+
+define Build/Configure
+endef
+
+define Build/Compile
+ $(MAKE) -C $(PKG_BUILD_DIR) \
+ CC="$(TARGET_CROSS)gcc" \
+ LD="$(TARGET_CROSS)ld" \
+ AR="$(TARGET_CROSS)ar rcu" \
+ RANLIB="$(TARGET_CROSS)ranlib" \
+ INSTALL_ROOT=/usr \
+ LUAINC=$(STAGING_DIR)/usr/include
+endef
+
+define Package/luaposix/install
+ $(INSTALL_DIR) $(1)/usr/lib/lua
+ $(STRIP) $(PKG_BUILD_DIR)/posix.so
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/posix.so $(1)/usr/lib/lua
+endef
+
+$(eval $(call BuildPackage,luaposix))