summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--GNUmakefile205
-rw-r--r--config.h.guess32
-rw-r--r--doc/luaossl.pdfbin274840 -> 300085 bytes
-rw-r--r--doc/luaossl.tex42
-rw-r--r--src/GNUmakefile134
-rw-r--r--src/compat52.h168
-rw-r--r--src/openssl.c575
-rw-r--r--src/openssl.ssl.context.lua14
-rw-r--r--src/openssl.ssl.lua20
-rw-r--r--vendor/compat53/.gitignore10
-rw-r--r--vendor/compat53/LICENSE20
-rw-r--r--vendor/compat53/README.md229
-rw-r--r--vendor/compat53/c-api/compat-5.3.c617
-rw-r--r--vendor/compat53/c-api/compat-5.3.h388
-rw-r--r--vendor/compat53/compat53/init.lua373
-rw-r--r--vendor/compat53/compat53/module.lua827
-rw-r--r--vendor/compat53/lprefix.h175
-rw-r--r--vendor/compat53/lstrlib.c1584
-rw-r--r--vendor/compat53/ltablib.c450
-rw-r--r--vendor/compat53/lutf8lib.c256
-rw-r--r--vendor/compat53/rockspecs/compat53-0.1-1.rockspec31
-rw-r--r--vendor/compat53/rockspecs/compat53-0.2-1.rockspec32
-rw-r--r--vendor/compat53/rockspecs/compat53-0.3-1.rockspec32
-rw-r--r--vendor/compat53/rockspecs/compat53-0.4-1.rockspec32
-rw-r--r--vendor/compat53/rockspecs/compat53-0.5-1.rockspec32
-rw-r--r--vendor/compat53/rockspecs/compat53-scm-0.rockspec32
-rwxr-xr-xvendor/compat53/tests/test.lua789
-rw-r--r--vendor/compat53/tests/testmod.c318
28 files changed, 7017 insertions, 400 deletions
diff --git a/GNUmakefile b/GNUmakefile
index c58686c..1893378 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -9,6 +9,20 @@ GUARD_$(d) := 1
9 9
10all: # default target 10all: # default target
11 11
12#
13# G N U M A K E F U N C T I O N S
14#
15KNOWN_APIS = 5.1 5.2 5.3
16
17# template for invoking luapath script
18LUAPATH := $(d)/mk/luapath
19LUAPATH_FN = $(shell env CC='$(subst ',\\',$(CC))' CPPFLAGS='$(subst ',\\',$(CPPFLAGS))' LDFLAGS='$(subst ',\\',$(LDFLAGS))' $(LUAPATH) -krxm3 -I '$(subst ',\\',$(DESTDIR)$(includedir))' -I/usr/include -I/usr/local/include -P '$(subst ',\\',$(DESTDIR)$(bindir))' -P '$(subst ',\\',$(bindir))' -L '$(subst ',\\',$(DESTDIR)$(libdir))' -L '$(subst ',\\',$(libdir))' -v$(1) $(2))
20
21# check whether luapath can locate Lua $(1) headers
22HAVE_API_FN = $(and $(filter $(1),$(call LUAPATH_FN,$(1),version)),$(1)$(info enabling Lua $(1)))
23
24# check whether $(1) in LUA_APIS or $(LUA$(1:.=)_CPPFLAGS) is non-empty
25WITH_API_FN = $$(and $$(or $$(filter $(1),$$(LUA_APIS)),$$(LUA$(subst .,,$(1))_CPPFLAGS)),$(1))
12 26
13# 27#
14# E N V I R O N M E N T C O N F I G U R A T I O N 28# E N V I R O N M E N T C O N F I G U R A T I O N
@@ -30,47 +44,43 @@ lua53path ?= $(datadir)/lua/5.3
30AR ?= ar 44AR ?= ar
31RANLIB ?= ranlib 45RANLIB ?= ranlib
32M4 ?= m4 46M4 ?= m4
47MV ?= mv
33RM ?= rm 48RM ?= rm
34CP ?= cp 49CP ?= cp
35LN ?= ln
36LN_S ?= $(LN) -s
37RMDIR ?= rmdir 50RMDIR ?= rmdir
38MKDIR ?= mkdir 51MKDIR ?= mkdir
39CHMOD ?= chmod 52CHMOD ?= chmod
40INSTALL ?= install 53INSTALL ?= install
41INSTALL_DATA ?= $(INSTALL) -m 644 54INSTALL_DATA ?= $(INSTALL) -m 644
55TOUCH ?= touch
56TEE ?= tee
57TEE_A ?= $(TEE) -a
58
59# see Lua Autodetection, below
42 60
43.PHONY: $(d)/config 61.PHONY: $(d)/config
44 62
63PRINT_$(d) = printf "%s = %s\n" '$(1)' '$(subst ',\\',$(2))' | $(TEE_A) '$(3)'
64
65LAZY_$(d) = \
66 prefix includedir libdir datadir bindir \
67 lua51cpath lua51path lua52cpath lua52path lua53cpath lua53path \
68 CC ALL_CPPFLAGS CPPFLAGS ALL_CFLAGS CFLAGS ALL_LDFLAGS LDFLAGS \
69 ALL_SOFLAGS SOFLAGS ALL_LIB LIBS \
70 $(foreach API,$(KNOWN_APIS),ALL_LUA$(subst .,,$(API))_CPPFLAGS) \
71 AR RANLIB M4 MV RM CP RMDIR MKDIR CHMOD INSTALL INSTALL_DATA TOUCH \
72 TEE TEE_A
73
74NONLAZY_$(d) = \
75 LUA_APIS \
76 $(foreach API,$(KNOWN_APIS),LUAC$(subst .,,$(API))) \
77 $(foreach API,$(KNOWN_APIS),$(and $(call WITH_API_FN,$(API)),LUA$(subst .,,$(API))_CPPFLAGS))
78
45$(d)/config: 79$(d)/config:
46 printf 'prefix ?= $(value prefix)'"\n" >| $(@D)/.config 80 $(TOUCH) $(@D)/.config.tmp
47 printf 'includedir ?= $(value includedir)'"\n" >> $(@D)/.config 81 @$(foreach V,$(LAZY_$(@D)), $(call PRINT_$(@D),$(V),$(value $(V)),$(@D)/.config.tmp);)
48 printf 'libdir ?= $(value libdir)'"\n" >> $(@D)/.config 82 @$(foreach V,$(NONLAZY_$(@D)), $(call PRINT_$(@D),$(V),$($(V)),$(@D)/.config.tmp);)
49 printf 'datadir ?= $(value datadir)'"\n" >> $(@D)/.config 83 $(MV) $(@D)/.config.tmp $(@D)/.config
50 printf 'bindir ?= $(value bindir)'"\n" >> $(@D)/.config
51 printf 'lua51cpath ?= $(value lua51cpath)'"\n" >> $(@D)/.config
52 printf 'lua51path ?= $(value lua51path)'"\n" >> $(@D)/.config
53 printf 'lua52cpath ?= $(value lua52cpath)'"\n" >> $(@D)/.config
54 printf 'lua52path ?= $(value lua52path)'"\n" >> $(@D)/.config
55 printf 'lua53cpath ?= $(value lua53cpath)'"\n" >> $(@D)/.config
56 printf 'lua53path ?= $(value lua53path)'"\n" >> $(@D)/.config
57 printf 'CC ?= $(CC)'"\n" >> $(@D)/.config
58 printf 'CPPFLAGS ?= $(value CPPFLAGS)'"\n" >> $(@D)/.config
59 printf 'CFLAGS ?= $(value CFLAGS)'"\n" >> $(@D)/.config
60 printf 'LDFLAGS ?= $(value LDFLAGS)'"\n" >> $(@D)/.config
61 printf 'SOFLAGS ?= $(value SOFLAGS)'"\n" >> $(@D)/.config
62 printf 'AR ?= $(value AR)'"\n" >> $(@D)/.config
63 printf 'RANLIB ?= $(value RANLIB)'"\n" >> $(@D)/.config
64 printf 'M4 ?= $(value M4)'"\n" >> $(@D)/.config
65 printf 'RM ?= $(value RM)'"\n" >> $(@D)/.config
66 printf 'CP ?= $(value CP)'"\n" >> $(@D)/.config
67 printf 'LN ?= $(value LN)'"\n" >> $(@D)/.config
68 printf 'LN_S ?= $(value LN_S)'"\n" >> $(@D)/.config
69 printf 'RMDIR ?= $(value RMDIR)'"\n" >> $(@D)/.config
70 printf 'MKDIR ?= $(value MKDIR)'"\n" >> $(@D)/.config
71 printf 'CHMOD ?= $(value CHMOD)'"\n" >> $(@D)/.config
72 printf 'INSTALL ?= $(value INSTALL)'"\n" >> $(@D)/.config
73 printf 'INSTALL_DATA ?= $(value INSTALL_DATA)'"\n" >> $(@D)/.config
74 84
75# add local targets if building from inside project tree 85# add local targets if building from inside project tree
76ifneq "$(filter $(abspath $(d)/..)/%, $(abspath $(firstword $(MAKEFILE_LIST))))" "" 86ifneq "$(filter $(abspath $(d)/..)/%, $(abspath $(firstword $(MAKEFILE_LIST))))" ""
@@ -81,7 +91,49 @@ endif
81 91
82 92
83# 93#
84# S H A R E D C O M P I L A T I O N F L A G S 94# L U A A U T O D E T E C T I O N
95#
96
97# set LUA_APIS if empty or "?"
98ifeq ($(or $(strip $(LUA_APIS)),?),?)
99override LUA_APIS := $(call HAVE_API_FN,5.1) $(call HAVE_API_FN,5.2) $(call HAVE_API_FN,5.3)
100endif
101
102define LUAXY_template
103
104# set luaXYcpath if empty or "?"
105ifeq ($$(or $$(strip $$(lua$(subst .,,$(1))cpath)),?),?)
106override lua$(subst .,,$(1))cpath := $$(or $$(call LUAPATH_FN,$(1),cdir),$$(libdir)/lua/$(1))
107endif
108
109# set luaXYpath if empty or "?"
110ifeq ($$(or $$(strip $$(lua$(subst .,,$(1))path)),?),?)
111override lua$(subst .,,$(1))path = $$(or $$(call LUAPATH_FN,$(1),ldir),$$(datadir)/lua/$(1))
112endif
113
114# set LUAXY_CPPFLAGS if undefined or "?" (NB: can be empty if path already in $(CPPFLAGS))
115ifeq ($$(and $$(findstring undefined,$$(origin LUA$(subst .,,$(1))_CPPFLAGS)),?),?)
116override LUA$(subst .,,$(1))_CPPFLAGS = $$(and $$(call WITH_API_FN,$(1)),$$(call LUAPATH_FN,$(1),cppflags))
117endif
118
119# set ALL_LUAXY_CPPFLAGS if empty or "?"
120ifeq ($$(or $$(strip $$(ALL_LUA$(subst .,,$(1))_CPPFLAGS)),?),?)
121override ALL_LUA$(subst .,,$(1))_CPPFLAGS = $$(LUA$(subst .,,$(1))_CPPFLAGS)
122endif
123
124# set LUAXYC if empty or "?"
125ifeq ($$(or $$(strip $$(LUAC$(subst .,,$(1)))),?),?)
126override LUAC$(subst .,,$(1)) = $$(or $$(call LUAPATH_FN,$(1),luac),true)
127endif
128
129endef # LUAXY_template
130
131$(eval $(call LUAXY_template,5.1))
132$(eval $(call LUAXY_template,5.2))
133$(eval $(call LUAXY_template,5.3))
134
135#
136# A U T O D E T E C T C O M P I L A T I O N F L A G S
85# 137#
86cc-option ?= $(shell if $(CC) $(1) -S -o /dev/null -xc /dev/null \ 138cc-option ?= $(shell if $(CC) $(1) -S -o /dev/null -xc /dev/null \
87 > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi;) 139 > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi;)
@@ -89,44 +141,107 @@ cc-option ?= $(shell if $(CC) $(1) -S -o /dev/null -xc /dev/null \
89VENDOR_OS_$(d) := $(shell $(d)/mk/vendor.os) 141VENDOR_OS_$(d) := $(shell $(d)/mk/vendor.os)
90VENDOR_CC_$(d) := $(shell env CC="$(CC)" $(d)/mk/vendor.cc) 142VENDOR_CC_$(d) := $(shell env CC="$(CC)" $(d)/mk/vendor.cc)
91 143
144#
145# ALL_CPPFLAGS
146#
147ifeq ($(origin ALL_CPPFLAGS), undefined)
148
92ifneq ($(VENDOR_OS_$(d)), OpenBSD) 149ifneq ($(VENDOR_OS_$(d)), OpenBSD)
93CPPFLAGS_$(d) += -D_REENTRANT -D_THREAD_SAFE -D_GNU_SOURCE 150ALL_CPPFLAGS += -D_REENTRANT -D_THREAD_SAFE -D_GNU_SOURCE
94endif 151endif
95 152
96ifeq ($(VENDOR_OS_$(d)), SunOS) 153ifeq ($(VENDOR_OS_$(d)), SunOS)
97CPPFLAGS_$(d) += -Usun -D_XPG4_2 -D__EXTENSIONS__ 154ALL_CPPFLAGS += -Usun -D_XPG4_2 -D__EXTENSIONS__
98endif 155endif
99 156
157ALL_CPPFLAGS += $(CPPFLAGS)
158
159endif # ALL_CPPFLAGS
160
161#
162# ALL_CFLAGS
163#
164ifeq ($(origin ALL_CFLAGS), undefined)
165
100ifeq ($(VENDOR_CC_$(d)), gcc) 166ifeq ($(VENDOR_CC_$(d)), gcc)
101CFLAGS_$(d) += -O2 -std=gnu99 -fPIC 167ALL_CFLAGS += -O2 -std=gnu99 -fPIC
102CFLAGS_$(d) += -g -Wall -Wextra $(call cc-option, -Wno-missing-field-initializers) $(call cc-option, -Wno-override-init) -Wno-unused 168ALL_CFLAGS += -g -Wall -Wextra $(call cc-option, -Wno-missing-field-initializers) $(call cc-option, -Wno-override-init) -Wno-unused
103endif 169endif
104 170
105ifeq ($(VENDOR_CC_$(d)), clang) 171ifeq ($(VENDOR_CC_$(d)), clang)
106CFLAGS_$(d) += -O2 -std=gnu99 -fPIC 172ALL_CFLAGS += -O2 -std=gnu99 -fPIC
107CFLAGS_$(d) += -g -Wall -Wextra -Wno-missing-field-initializers -Wno-initializer-overrides -Wno-unused 173ALL_CFLAGS += -g -Wall -Wextra -Wno-missing-field-initializers -Wno-initializer-overrides -Wno-unused -Wno-dollar-in-identifier-extension
108endif 174endif
109 175
110ifeq ($(VENDOR_CC_$(d)), sunpro) 176ifeq ($(VENDOR_CC_$(d)), sunpro)
111CFLAGS_$(d) += -xcode=pic13 177ALL_CFLAGS += -xcode=pic13
112CFLAGS_$(d) += -g 178ALL_CFLAGS += -g
113# 179#
114# Solaris Studio has a brain-dead function call analyzer which counts 180# Solaris Studio supports anonymous unions just fine; but it complains
115# arguments before preprocessor expansion. 181# incessantly about them.
116# 182#
117CFLAGS_$(d) += -erroff=E_ARGUEMENT_MISMATCH 183ALL_CFLAGS += -erroff=E_ANONYMOUS_UNION_DECL
118endif 184endif
119 185
120ifeq ($(VENDOR_OS_$(d)), Darwin) 186ifeq ($(VENDOR_OS_$(d)), Darwin)
121CFLAGS_$(d) += -Wno-deprecated-declarations 187ALL_CFLAGS += -Wno-deprecated-declarations
122endif 188endif
123 189
190ALL_CFLAGS += $(CFLAGS)
191
192endif # ALL_CFLAGS
193
194#
195# ALL_SOFLAGS
196#
197ifeq ($(origin ALL_SOFLAGS), undefined)
198
124ifeq ($(VENDOR_OS_$(d)), Darwin) 199ifeq ($(VENDOR_OS_$(d)), Darwin)
125SOFLAGS_$(d) += -bundle -undefined dynamic_lookup 200ALL_SOFLAGS += -bundle -undefined dynamic_lookup
126else 201else
127SOFLAGS_$(d) += -shared 202ALL_SOFLAGS += -shared
203endif
204
205ALL_SOFLAGS += $(SOFLAGS)
206
207endif # ALL_SOFLAGS
208
209#
210# ALL_LDFLAGS
211#
212ifeq ($(origin ALL_LDFLAGS), undefined)
213
214ALL_LDFLAGS += -L$(DESTDIR)$(libdir) -L$(libdir)
215ALL_LDFLAGS += $(LDFLAGS)
216
217endif # ALL_LDFLAGS
218
219#
220# ALL_LIBS
221#
222ifeq ($(origin ALL_LIBS), undefined)
223
224# put $(LIBS) first as they're more likely to be higher-level dependencies
225ALL_LIBS += $(LIBS)
226ALL_LIBS += -lssl -lcrypto -lpthread
227
228# NetBSD, FreeBSD, OpenBSD (and presumably descendants) lack any libdl;
229# dlopen, et al are part of libc.
230ifneq ($(patsubst %BSD,BSD,$(VENDOR_OS_$(d))), BSD)
231ALL_LIBS += -ldl
128endif 232endif
129 233
234# This only seems to be necessary on Linux. Darwin and OpenBSD lack a librt.
235# On OpenBSD clock_gettime is part of libc. Others have librt, but linking
236# it in is unnecessary.
237ifeq ($(VENDOR_OS_$(d)), Linux)
238ALL_LIBS += -lrt
239endif
240
241ALL_LIBS += -lm
242
243endif # ALL_LIBS
244
130 245
131# 246#
132# P R O J E C T R U L E S 247# P R O J E C T R U L E S
diff --git a/config.h.guess b/config.h.guess
index 9b5fcdc..db17fc7 100644
--- a/config.h.guess
+++ b/config.h.guess
@@ -34,7 +34,7 @@
34 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 34 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
35 35
36#define AG_VENDOR "william+autoguess@25thandClement.com" 36#define AG_VENDOR "william+autoguess@25thandClement.com"
37#define AG_VERSION 20161019L 37#define AG_VERSION 20170511L
38 38
39 39
40/* 40/*
@@ -347,6 +347,7 @@
347 347
348#define AG_OPENBSD_PREREQ_0_0 (__OpenBSD__) 348#define AG_OPENBSD_PREREQ_0_0 (__OpenBSD__)
349#define AG_OPENBSD_PREREQ_5_5 (OpenBSD >= 201405) 349#define AG_OPENBSD_PREREQ_5_5 (OpenBSD >= 201405)
350#define AG_OPENBSD_PREREQ_5_6 (OpenBSD >= 201411)
350#define AG_OPENBSD_PREREQ_5_7 (OpenBSD >= 201505) 351#define AG_OPENBSD_PREREQ_5_7 (OpenBSD >= 201505)
351#define AG_OPENBSD_PREREQ(M, m) (AG_OPENBSD_PREREQ_ ## M ## _ ## m) 352#define AG_OPENBSD_PREREQ(M, m) (AG_OPENBSD_PREREQ_ ## M ## _ ## m)
352 353
@@ -488,6 +489,11 @@
488#define HAVE_SYS_INOTIFY_H ag_test_include(<sys/inotify.h>, __linux__) 489#define HAVE_SYS_INOTIFY_H ag_test_include(<sys/inotify.h>, __linux__)
489#endif 490#endif
490 491
492#ifndef HAVE_SYS_RANDOM_H
493#define HAVE_SYS_RANDOM_H_ (__sun && defined SYS_getrandom) /* requires #include <sys/syscall.h> :( */
494#define HAVE_SYS_RANDOM_H ag_test_include(<sys/random.h>, HAVE_SYS_RANDOM_H_)
495#endif
496
491#ifndef HAVE_SYS_SIGNALFD_H 497#ifndef HAVE_SYS_SIGNALFD_H
492#define HAVE_SYS_SIGNALFD_H_ (AG_GLIBC_PREREQ(2,8) || (!AG_GLIBC_PREREQ(0,0) && __linux__) || defined SFD_CLOEXEC) 498#define HAVE_SYS_SIGNALFD_H_ (AG_GLIBC_PREREQ(2,8) || (!AG_GLIBC_PREREQ(0,0) && __linux__) || defined SFD_CLOEXEC)
493#define HAVE_SYS_SIGNALFD_H ag_test_include(<sys/signalfd.h>, HAVE_SYS_SIGNALFD_H_) 499#define HAVE_SYS_SIGNALFD_H ag_test_include(<sys/signalfd.h>, HAVE_SYS_SIGNALFD_H_)
@@ -731,6 +737,10 @@
731#define HAVE_GETAUXVAL (HAVE_SYS_AUXV_H && !__sun) 737#define HAVE_GETAUXVAL (HAVE_SYS_AUXV_H && !__sun)
732#endif 738#endif
733 739
740#ifndef HAVE_GETENTROPY
741#define HAVE_GETENTROPY (AG_OPENBSD_PREREQ(5,6) || (HAVE_SYS_RANDOM_H && __sun))
742#endif
743
734#ifndef HAVE_GETENV_R 744#ifndef HAVE_GETENV_R
735#define HAVE_GETENV_R (AG_NETBSD_PREREQ(4,0,0) || __minix) 745#define HAVE_GETENV_R (AG_NETBSD_PREREQ(4,0,0) || __minix)
736#endif 746#endif
@@ -747,6 +757,10 @@
747#define HAVE_GETPROGNAME (HAVE_ARC4RANDOM || AG_SUNOS_PREREQ(5,11)) 757#define HAVE_GETPROGNAME (HAVE_ARC4RANDOM || AG_SUNOS_PREREQ(5,11))
748#endif 758#endif
749 759
760#ifndef HAVE_GETRANDOM
761#define HAVE_GETRANDOM (HAVE_SYS_RANDOM_H && __sun)
762#endif
763
750#ifndef HAVE_INOTIFY_INIT 764#ifndef HAVE_INOTIFY_INIT
751#define HAVE_INOTIFY_INIT HAVE_SYS_INOTIFY_H 765#define HAVE_INOTIFY_INIT HAVE_SYS_INOTIFY_H
752#endif 766#endif
@@ -781,6 +795,14 @@
781 && (!__NetBSD__ || AG_NETBSD_PREREQ(7,0,0))) 795 && (!__NetBSD__ || AG_NETBSD_PREREQ(7,0,0)))
782#endif 796#endif
783 797
798#ifndef HAVE_MKDIRAT
799#define HAVE_MKDIRAT HAVE_OPENAT
800#endif
801
802#ifndef HAVE_MKFIFOAT
803#define HAVE_MKFIFOAT (!__APPLE__ && (!__NetBSD__ || AG_NETBSD_PREREQ(7,0,0)))
804#endif
805
784#ifndef HAVE_PACCEPT 806#ifndef HAVE_PACCEPT
785#define HAVE_PACCEPT AG_NETBSD_PREREQ(6,0,0) 807#define HAVE_PACCEPT AG_NETBSD_PREREQ(6,0,0)
786#endif 808#endif
@@ -829,6 +851,10 @@
829#define HAVE_POSIX_FALLOCATE (_AIX || AG_FREEBSD_PREREQ(9,0,0) || AG_GLIBC_PREREQ(2,2) || AG_MUSL_MAYBE || AG_NETBSD_PREREQ(7,0,0) || __sun) 851#define HAVE_POSIX_FALLOCATE (_AIX || AG_FREEBSD_PREREQ(9,0,0) || AG_GLIBC_PREREQ(2,2) || AG_MUSL_MAYBE || AG_NETBSD_PREREQ(7,0,0) || __sun)
830#endif 852#endif
831 853
854#ifndef HAVE_RENAMEAT
855#define HAVE_RENAMEAT HAVE_OPENAT
856#endif
857
832#ifndef HAVE_SIGNALFD 858#ifndef HAVE_SIGNALFD
833#define HAVE_SIGNALFD HAVE_SYS_SIGNALFD_H 859#define HAVE_SIGNALFD HAVE_SYS_SIGNALFD_H
834#endif 860#endif
@@ -873,6 +899,10 @@
873#define HAVE_TIMERFD_SETTIME HAVE_TIMERFD_CREATE 899#define HAVE_TIMERFD_SETTIME HAVE_TIMERFD_CREATE
874#endif 900#endif
875 901
902#ifndef HAVE_UNLINKAT
903#define HAVE_UNLINKAT HAVE_OPENAT
904#endif
905
876#ifndef STRERROR_R_CHAR_P 906#ifndef STRERROR_R_CHAR_P
877#define STRERROR_R_CHAR_P ((AG_GLIBC_PREREQ(0,0) || AG_UCLIBC_PREREQ(0,0,0)) && (HAVE__GNU_SOURCE || !(_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600))) 907#define STRERROR_R_CHAR_P ((AG_GLIBC_PREREQ(0,0) || AG_UCLIBC_PREREQ(0,0,0)) && (HAVE__GNU_SOURCE || !(_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600)))
878#endif 908#endif
diff --git a/doc/luaossl.pdf b/doc/luaossl.pdf
index 106b4ea..81112d9 100644
--- a/doc/luaossl.pdf
+++ b/doc/luaossl.pdf
Binary files differ
diff --git a/doc/luaossl.tex b/doc/luaossl.tex
index e75a678..5ac7761 100644
--- a/doc/luaossl.tex
+++ b/doc/luaossl.tex
@@ -284,7 +284,9 @@ field & type:default & description\\\hline
284 284
285.bits & number:1024 & private key size \\ 285.bits & number:1024 & private key size \\
286 286
287.exp & number:65537 & RSA or Diffie-Hellman exponent \\ 287.exp & number:65537 & RSA exponent \\
288
289.generator & number:2 & Diffie-Hellman generator \\
288 290
289.dhparam & string & PEM encoded string with precomputed DH parameters \\ 291.dhparam & string & PEM encoded string with precomputed DH parameters \\
290 292
@@ -933,11 +935,17 @@ Sets the private key \module{openssl.pkey} object $key$ for use during SSL conne
933 935
934Sets the allowed public key and private key algorithm(s). The string format is documented in the \href{http://www.openssl.org/docs/apps/ciphers.html#CIPHER_LIST_FORMAT}{OpenSSL ciphers(1) utility documentation}. 936Sets the allowed public key and private key algorithm(s). The string format is documented in the \href{http://www.openssl.org/docs/apps/ciphers.html#CIPHER_LIST_FORMAT}{OpenSSL ciphers(1) utility documentation}.
935 937
938\subsubsection[\fn{context:setCurvesList}]{\fn{context:setCurvesList($string$ [, ...])}}
939
940Sets the supported curves. The string format is a list of colon separated curve names similar to \texttt{ctx:setCipherList(...)}. A list of supported curves can be found by running \texttt{openssl ecparam -list\_curves}.
941
942\emph{Only supported since OpenSSL 1.0.2.}
943
936\subsubsection[\fn{context:setEphemeralKey}]{\fn{context:setEphemeralKey($key$)}} 944\subsubsection[\fn{context:setEphemeralKey}]{\fn{context:setEphemeralKey($key$)}}
937 945
938Sets \module{openssl.pkey} object $key$ as the ephemeral key during key exchanges which use that particular key type. Typically $key$ will be either a Diffie-Hellman or Elliptic Curve key. 946Sets \module{openssl.pkey} object $key$ as the ephemeral key during key exchanges which use that particular key type. Typically $key$ will be either a Diffie-Hellman or Elliptic Curve key.
939 947
940\emph{In order to configure an SSL server to support an ephemeral key exchange cipher suite (i.e. DHE-* and ECDHE-*), the application must explicitly set the ephemeral keys. Simply enabling the cipher suite is not sufficient. The application can statically generate Diffie-Hellman public key parameters, and many servers ship with such a key compiled into the software. Elliptic curve keys are necessarily static, and instantiated by curve name\footnote{\href{http://en.wikipedia.org/w/index.php?title=Comparison\_of\_TLS\_implementations&oldid=629779090\#Supported\_elliptic\_curves}{According to Wikipedia} the most widely supported curve is prime256v1, so to enable ECDHE-* applications can simply do \texttt{ctx:setEphemeralKey(pkey.new\{ type = ``EC'', curve = ``prime256v1'' \})}. To achieve Perfect Forward Secrecy for ECDHE-*, applications must also do \texttt{ctx:setOptions(context.OP\_SINGLE\_ECDH\_USE)}. The \texttt{ctx} object must then be used to configure each SSL session, such as by passing it to \fn{cqueues.socket:starttls()}.}.} 948\emph{In order to configure an SSL server to support an ephemeral key exchange cipher suite (i.e. DHE-* and ECDHE-*), the application must explicitly set the ephemeral keys. Simply enabling the cipher suite is not sufficient. The application can statically generate Diffie-Hellman public key parameters, and many servers ship with such a key compiled into the software. Elliptic curve keys are necessarily static, and instantiated by curve name\footnote{OpenSSL < 1.0.2 only supports a single curve, \href{http://en.wikipedia.org/w/index.php?title=Comparison\_of\_TLS\_implementations&oldid=629779090\#Supported\_elliptic\_curves}{according to Wikipedia} the most widely supported curve is prime256v1, so to enable ECDHE-*, applications can simply do \texttt{ctx:setEphemeralKey(pkey.new\{ type = ``EC'', curve = ``prime256v1'' \})}. To achieve Perfect Forward Secrecy for ECDHE-*, applications must also do \texttt{ctx:setOptions(context.OP\_SINGLE\_ECDH\_USE)}. The \texttt{ctx} object must then be used to configure each SSL session, such as by passing it to \fn{cqueues.socket:starttls()}.}.}
941 949
942\emph{In addition, to attain Perfect Forward Secrecy the options \texttt{OP\_SINGLE\_DH\_USE} and \texttt{OP\_SINGLE\_ECDH\_USE} must be set so that OpenSSL discards and regenerates the secret keying parameters for each key exchange.} 950\emph{In addition, to attain Perfect Forward Secrecy the options \texttt{OP\_SINGLE\_DH\_USE} and \texttt{OP\_SINGLE\_ECDH\_USE} must be set so that OpenSSL discards and regenerates the secret keying parameters for each key exchange.}
943 951
@@ -997,6 +1005,30 @@ Returns the option flags of the SSL connection instance. See \fn{openssl.ssl.con
997 1005
998Clears the option flags of the SSL connection instance. See \fn{openssl.ssl.context:clearOptions}. 1006Clears the option flags of the SSL connection instance. See \fn{openssl.ssl.context:clearOptions}.
999 1007
1008\subsubsection[\fn{ssl:setVerify}]{\fn{ssl:setVerify([$mode$][, $depth$])}}
1009
1010Sets the verification mode flags and maximum validation chain depth.
1011See \fn{openssl.ssl.context:setVerify}.
1012
1013\subsubsection[\fn{ssl:getVerify}]{\fn{ssl:getVerify()}}
1014
1015Returns two values: the bitwise verification mode flags, and the maximum validation depth.
1016See \fn{openssl.ssl.context:getVerify}.
1017
1018\subsubsection[\fn{ssl:getVerifyResult}]{\fn{ssl:getVerifyResult()}}
1019
1020Returns two values: the integer verification result code and the string representation of that code.
1021
1022\subsubsection[\fn{ssl:setCertificate}]{\fn{ssl:setCertificate($crt$)}}
1023
1024Sets the X.509 certificate \module{openssl.x509} object $crt$ to send during SSL connection instance handshakes.
1025See \fn{openssl.ssl.context:setCertificate}.
1026
1027\subsubsection[\fn{ssl:setPrivateKey}]{\fn{ssl:setPrivateKey($key$)}}
1028
1029Sets the private key \module{openssl.pkey} object $key$ for use during SSL connection instance handshakes.
1030See \fn{openssl.ssl.context:setPrivateKey}.
1031
1000\subsubsection[\fn{ssl:getPeerCertificate}]{\fn{ssl:getPeerCertificate()}} 1032\subsubsection[\fn{ssl:getPeerCertificate}]{\fn{ssl:getPeerCertificate()}}
1001 1033
1002Returns the X.509 peer certificate as an \module{openssl.x509} object. If no peer certificate is available, returns $nil$. 1034Returns the X.509 peer certificate as an \module{openssl.x509} object. If no peer certificate is available, returns $nil$.
@@ -1046,6 +1078,12 @@ TLS1\_2\_VERSION & 16-bit TLSv1.2 identifier (0x0303). \\
1046 1078
1047Returns the SSL/TLS version supported by the client, which should be greater than or equal to the negotiated version. See \fn{ssl:getVersion}. 1079Returns the SSL/TLS version supported by the client, which should be greater than or equal to the negotiated version. See \fn{ssl:getVersion}.
1048 1080
1081\subsubsection[\fn{ssl:setCurvesList}]{\fn{ssl:setCurvesList($string$ [, ...])}}
1082
1083Sets the supported curves for this SSL connection instance. See \fn{openssl.ssl.context:setCurvesList}.
1084
1085\emph{Only supported since OpenSSL 1.0.2.}
1086
1049\subsubsection[\fn{ssl:getAlpnSelected}]{\fn{ssl:getAlpnSelected()}} 1087\subsubsection[\fn{ssl:getAlpnSelected}]{\fn{ssl:getAlpnSelected()}}
1050 1088
1051Returns the negotiated ALPN protocol as a string. 1089Returns the negotiated ALPN protocol as a string.
diff --git a/src/GNUmakefile b/src/GNUmakefile
index 9e4fde4..e257ba6 100644
--- a/src/GNUmakefile
+++ b/src/GNUmakefile
@@ -16,66 +16,46 @@ include $(d)/../GNUmakefile
16# 16#
17# C O M P I L A T I O N F L A G S 17# C O M P I L A T I O N F L A G S
18# 18#
19OS_$(d) = $(shell $(d)/../mk/vendor.os) 19CPPFLAGS_$(d) = $(ALL_CPPFLAGS) -DHAVE_CONFIG_H -DCOMPAT53_PREFIX=luaossl
20CC_$(d) = $(shell env CC="$(CC) "$(d)/../mk/vendor.cc) 20CFLAGS_$(d) = $(ALL_CFLAGS)
21LUAPATH_$(d) = $(shell env CC="$(CC)" CPPFLAGS="$(CPPFLAGS)" LDFLAGS="$(LDFLAGS)" $(<D)/../mk/luapath -krxm3 -I$(DESTDIR)$(includedir) -I/usr/include -I/usr/local/include -P$(DESTDIR)$(bindir) -P$(bindir) -L$(DESTDIR)$(libdir) -L$(libdir) -v$(1) $(2)) 21SOFLAGS_$(d) = $(ALL_SOFLAGS)
22 22LDFLAGS_$(d) = $(ALL_LDFLAGS)
23CPPFLAGS_$(d) = $(CPPFLAGS_$(abspath $(@D)/../..)) -DHAVE_CONFIG_H 23LIBS_$(d) = $(ALL_LIBS)
24CFLAGS_$(d) = $(CFLAGS_$(abspath $(@D)/../..))
25LDFLAGS_$(d) = $(LDFLAGS_$(abspath $(@D)/../..))
26SOFLAGS_$(d) = $(SOFLAGS_$(abspath $(@D)/../..))
27
28ifeq ($(CC_$(d)), sunpro)
29CPPFLAGS_$(d) += -DOPENSSL_NO_EC
30endif
31
32LDFLAGS_$(d) += -lssl -lcrypto -lpthread -lm
33
34# NetBSD, FreeBSD, OpenBSD (and presumably descendants) lack any libdl;
35# dlopen, et al are part of libc.
36ifneq ($(patsubst %BSD,BSD,$(OS_$(d))), BSD)
37LDFLAGS_$(d) += -ldl
38endif
39
40 24
41# 25#
42# C O M P I L A T I O N R U L E S 26# C O M P I L A T I O N R U L E S
43# 27#
28OBJS_$(d) = openssl.o ../vendor/compat53/c-api/compat-5.3.o
29
44$(d)/config.h: $(abspath $(d)/..)/config.h 30$(d)/config.h: $(abspath $(d)/..)/config.h
45 $(CP) $< $@ 31 $(CP) $< $@
46 32
47define BUILD_$(d) 33define BUILD_$(d)
48 34
49.SECONDARY: liblua$(1)-openssl openssl$(1) 35$$(d)/$(1)/openssl.so: $$(addprefix $$(d)/$(1)/, $$(OBJS_$(d)))
36 $$(CC) -o $$@ $$^ $$(SOFLAGS_$$(abspath $$(@D)/..)) $$(LDFLAGS_$$(abspath $$(@D)/..)) $$(LIBS_$$(abspath $$(@D)/..))
50 37
51$$(d)/$(1)/openssl.so: $$(d)/$(1)/openssl.o 38$$(d)/$(1)/%.o: $$(d)/%.c $$(d)/../vendor/compat53/c-api/compat-5.3.h $$(d)/config.h
52 $$(CC) -o $$@ $$^ $$(SOFLAGS_$$(abspath $$(@D)/..)) $$(SOFLAGS) $$(LDFLAGS_$$(abspath $$(@D)/..)) $$(LDFLAGS)
53
54$$(d)/$(1)/openssl.o: $$(d)/openssl.c $$(d)/compat52.h $$(d)/config.h
55 test "$$(notdir $$(@D))" = "$$(call LUAPATH_$$(<D), $$(notdir $$(@D)), version)"
56 $$(MKDIR) -p $$(@D) 39 $$(MKDIR) -p $$(@D)
57 $$(CC) $$(CFLAGS_$$(<D)) $$(CFLAGS) $$(call LUAPATH_$$(<D), $$(notdir $$(@D)), cppflags) $$(CPPFLAGS_$$(<D)) $$(CPPFLAGS) -c -o $$@ $$< 40 $$(CC) $$(CFLAGS_$$(<D)) $$(ALL_LUA$(subst .,,$(1))_CPPFLAGS) $$(CPPFLAGS_$$(<D)) -c -o $$@ $$<
41
42.SECONDARY: liblua$(1)-openssl openssl$(1) openssl
58 43
59liblua$(1)-openssl openssl$(1): $$(d)/$(1)/openssl.so 44liblua$(1)-openssl openssl$(1) openssl: $$(d)/$(1)/openssl.so
60 45
61endef # BUILD_$(d) 46endef # BUILD_$(d)
62 47
63$(eval $(call BUILD_$(d),5.1)) 48$(eval $(call BUILD_$(d),5.1))
64
65$(eval $(call BUILD_$(d),5.2)) 49$(eval $(call BUILD_$(d),5.2))
66
67$(eval $(call BUILD_$(d),5.3)) 50$(eval $(call BUILD_$(d),5.3))
68 51
69ifneq "$(filter $(abspath $(d)/..)/%, $(abspath $(firstword $(MAKEFILE_LIST))))" "" 52ifneq "$(filter $(abspath $(d)/..)/%, $(abspath $(firstword $(MAKEFILE_LIST))))" ""
70.SECONDARY: all5.1 all5.2 all 53.SECONDARY: all all5.1 all5.2 all5.3
71 54
72all5.1: liblua5.1-openssl 55all5.1: liblua5.1-openssl
73
74all5.2: liblua5.2-openssl 56all5.2: liblua5.2-openssl
75
76all5.3: liblua5.3-openssl 57all5.3: liblua5.3-openssl
77 58all: $(foreach API,$(strip $(LUA_APIS)),all$(API))
78all: all5.1 all5.2
79 59
80endif 60endif
81 61
@@ -85,8 +65,6 @@ endif
85# 65#
86define INSTALL_$(d) 66define INSTALL_$(d)
87 67
88LUAC$(1)_$(d) = $$(or $$(call LUAPATH_$(d), $(1), luac), true)
89
90MODS$(1)_$(d) = \ 68MODS$(1)_$(d) = \
91 $$(DESTDIR)$(2)/_openssl.so \ 69 $$(DESTDIR)$(2)/_openssl.so \
92 $$(DESTDIR)$(3)/openssl.lua \ 70 $$(DESTDIR)$(3)/openssl.lua \
@@ -116,42 +94,34 @@ MODS$(1)_$(d) = \
116 94
117.SECONDARY: liblua$(1)-openssl-install openssl$(1)-install 95.SECONDARY: liblua$(1)-openssl-install openssl$(1)-install
118 96
119$$(DESTDIR)$(2)/_openssl.so: $$(d)/$(1)/openssl.so 97liblua$(1)-openssl-install openssl$(1)-install: $$(MODS$(1)_$$(d))
120 $$(MKDIR) -p $$(@D)
121 $$(CP) -fp $$< $$@
122 98
123$$(DESTDIR)$(3)/openssl.lua: $$(d)/openssl.lua 99$$(DESTDIR)$(2)/_openssl.so: $$(d)/$(1)/openssl.so
124 $$(LUAC$(1)_$(d)) -p $$<
125 $$(MKDIR) -p $$(@D) 100 $$(MKDIR) -p $$(@D)
126 $$(CP) -p $$< $$@ 101 $$(CP) -p $$< $$@
127 102
128$$(DESTDIR)$(3)/openssl/%.lua: $$(d)/openssl.%.lua 103$$(DESTDIR)$(3)/%.lua: $$(d)/%.lua
129 $$(LUAC$(1)_$(d)) -p $$< 104 $$(LUAC$(subst .,,$(1))) -p $$<
130 $$(MKDIR) -p $$(@D) 105 $$(MKDIR) -p $$(@D)
131 $$(CP) -p $$< $$@ 106 $$(CP) -p $$< $$@
132 107
133# pubkey.lua used to be symbolic link to pkey.lua, but that caused packaging 108$$(DESTDIR)$(3)/openssl/%.lua: $$(d)/openssl.%.lua
134# headaches. Now it's a stub, but the cp -p in the inference rule will copy 109 $$(LUAC$(subst .,,$(1))) -p $$<
135# to the target of the symbolic link, so we need a special install rule to
136# clean up the mess.
137$$(DESTDIR)$(3)/openssl/pubkey.lua: $$(d)/openssl.pubkey.lua
138 $$(LUAC$(1)_$(d)) -p $$<
139 $$(MKDIR) -p $$(@D) 110 $$(MKDIR) -p $$(@D)
140 $$(RM) -f $$@
141 $$(CP) -p $$< $$@ 111 $$(CP) -p $$< $$@
142 112
143$$(DESTDIR)$(3)/openssl/x509/%.lua: $$(d)/openssl.x509.%.lua 113$$(DESTDIR)$(3)/openssl/ocsp/%.lua: $$(d)/ocsp.%.lua
144 $$(LUAC$(1)_$(d)) -p $$< 114 $$(LUAC$(subst .,,$(1))) -p $$<
145 $$(MKDIR) -p $$(@D) 115 $$(MKDIR) -p $$(@D)
146 $$(CP) -p $$< $$@ 116 $$(CP) -p $$< $$@
147 117
148$$(DESTDIR)$(3)/openssl/ssl/%.lua: $$(d)/openssl.ssl.%.lua 118$$(DESTDIR)$(3)/openssl/x509/%.lua: $$(d)/x509.%.lua
149 $$(LUAC$(1)_$(d)) -p $$< 119 $$(LUAC$(subst .,,$(1))) -p $$<
150 $$(MKDIR) -p $$(@D) 120 $$(MKDIR) -p $$(@D)
151 $$(CP) -p $$< $$@ 121 $$(CP) -p $$< $$@
152 122
153$$(DESTDIR)$(3)/openssl/ssl/%.lua: $$(d)/openssl.ssl.%.lua 123$$(DESTDIR)$(3)/openssl/ssl/%.lua: $$(d)/ssl.%.lua
154 $$(LUAC$(1)_$(d)) -p $$< 124 $$(LUAC$(subst .,,$(1))) -p $$<
155 $$(MKDIR) -p $$(@D) 125 $$(MKDIR) -p $$(@D)
156 $$(CP) -p $$< $$@ 126 $$(CP) -p $$< $$@
157 127
@@ -161,6 +131,7 @@ liblua$(1)-openssl-install openssl$(1)-install: $$(MODS$(1)_$$(d))
161 131
162liblua$(1)-openssl-uninstall openssl$(1)-uninstall: 132liblua$(1)-openssl-uninstall openssl$(1)-uninstall:
163 $$(RM) -f $$(MODS$(1)_$(d)) 133 $$(RM) -f $$(MODS$(1)_$(d))
134 -$$(RMDIR) $$(DESTDIR)$(3)/openssl/ocsp
164 -$$(RMDIR) $$(DESTDIR)$(3)/openssl/x509 135 -$$(RMDIR) $$(DESTDIR)$(3)/openssl/x509
165 -$$(RMDIR) $$(DESTDIR)$(3)/openssl/ssl 136 -$$(RMDIR) $$(DESTDIR)$(3)/openssl/ssl
166 -$$(RMDIR) $$(DESTDIR)$(3)/openssl 137 -$$(RMDIR) $$(DESTDIR)$(3)/openssl
@@ -168,31 +139,24 @@ liblua$(1)-openssl-uninstall openssl$(1)-uninstall:
168endef # INSTALL_$(d) 139endef # INSTALL_$(d)
169 140
170$(eval $(call INSTALL_$(d),5.1,$$(lua51cpath),$$(lua51path))) 141$(eval $(call INSTALL_$(d),5.1,$$(lua51cpath),$$(lua51path)))
171
172$(eval $(call INSTALL_$(d),5.2,$$(lua52cpath),$$(lua52path))) 142$(eval $(call INSTALL_$(d),5.2,$$(lua52cpath),$$(lua52path)))
173
174$(eval $(call INSTALL_$(d),5.3,$$(lua53cpath),$$(lua53path))) 143$(eval $(call INSTALL_$(d),5.3,$$(lua53cpath),$$(lua53path)))
175 144
176ifneq "$(filter $(abspath $(d)/..)/%, $(abspath $(firstword $(MAKEFILE_LIST))))" "" 145ifneq "$(filter $(abspath $(d)/..)/%, $(abspath $(firstword $(MAKEFILE_LIST))))" ""
146
177.SECONDARY: install5.1 install5.2 install5.3 install 147.SECONDARY: install5.1 install5.2 install5.3 install
178 148
179install5.1: liblua5.1-openssl-install 149install5.1: liblua5.1-openssl-install
180
181install5.2: liblua5.2-openssl-install 150install5.2: liblua5.2-openssl-install
182
183install5.3: liblua5.3-openssl-install 151install5.3: liblua5.3-openssl-install
184 152install: $(foreach API,$(strip $(LUA_APIS)),install$(API))
185install: install5.1 install5.2
186 153
187.PHONY: uninstall5.1 uninstall5.2 uninstall5.3 uninstall 154.PHONY: uninstall5.1 uninstall5.2 uninstall5.3 uninstall
188 155
189uninstall5.1: liblua5.1-openssl-uninstall 156uninstall5.1: liblua5.1-openssl-uninstall
190
191uninstall5.2: liblua5.2-openssl-uninstall 157uninstall5.2: liblua5.2-openssl-uninstall
192
193uninstall5.3: liblua5.3-openssl-uninstall 158uninstall5.3: liblua5.3-openssl-uninstall
194 159uninstall: $(foreach API,$(strip $(LUA_APIS)),uninstall$(API))
195uninstall: uninstall5.1 uninstall5.2
196 160
197endif 161endif
198 162
@@ -203,7 +167,7 @@ endif
203.PHONY: $(d)/clean $(d)/clean~ clean clean~ 167.PHONY: $(d)/clean $(d)/clean~ clean clean~
204 168
205$(d)/clean: 169$(d)/clean:
206 $(RM) -fr $(@D)/*.so $(@D)/*.o $(@D)/*.dSYM $(@D)/5.1 $(@D)/5.2 $(@D)/5.3 170 $(RM) -fr $(@D)/config.h $(@D)/*.dSYM $(@D)/5.1 $(@D)/5.2 $(@D)/5.3
207 171
208$(d)/clean~: $(d)/clean 172$(d)/clean~: $(d)/clean
209 $(RM) -f $(@D)/*~ 173 $(RM) -f $(@D)/*~
@@ -220,27 +184,27 @@ clean~: $(d)/clean~
220 184
221$(d)/help: 185$(d)/help:
222 @echo 186 @echo
223 @echo "ext/ targets:" 187 @echo "src/ targets:"
224 @echo "" 188 @echo ""
225 @echo " all - build all binary targets" 189 @echo " all - build all API targets"
226 @echo "openssl - invokes openssl5.1 and openssl5.2" 190 @echo " all5.1 - build 5.1/openssl.so"
227 @echo "openssl5.1 - build 5.1/openssl.so" 191 @echo " all5.2 - build 5.2/openssl.so"
228 @echo "openssl5.2 - build 5.2/openssl.so" 192 @echo " all5.3 - build 5.3/openssl.so"
229 @echo "openssl5.3 - build 5.3/openssl.so" 193 @echo " install - install all API targets"
230 @echo "install - invokes install5.1 and install5.2" 194 @echo " install5.1 - install openssl Lua 5.1 modules"
231 @echo "install5.1 - install openssl Lua 5.1 modules" 195 @echo " install5.2 - install openssl Lua 5.2 modules"
232 @echo "install5.2 - install openssl Lua 5.2 modules" 196 @echo " install5.3 - install openssl Lua 5.3 modules"
233 @echo "install5.3 - install openssl Lua 5.3 modules" 197 @echo " uninstall - uninstall all API targets"
234 @echo "uninstall - invokes uninstall5.1 and uninstall5.2"
235 @echo "uninstall5.1 - uninstall openssl Lua 5.1 modules" 198 @echo "uninstall5.1 - uninstall openssl Lua 5.1 modules"
236 @echo "uninstall5.2 - uninstall openssl Lua 5.2 modules" 199 @echo "uninstall5.2 - uninstall openssl Lua 5.2 modules"
237 @echo "uninstall5.3 - uninstall openssl Lua 5.3 modules" 200 @echo "uninstall5.3 - uninstall openssl Lua 5.3 modules"
238 @echo " clean - rm binary targets, object files, debugging symbols, etc" 201 @echo " clean - rm binary targets, object files, debugging symbols, etc"
239 @echo " clean~ - clean + rm *~" 202 @echo " clean~ - clean + rm *~"
240 @echo " help - echo this help message" 203 @echo " help - echo this help message"
241 @echo "" 204 @echo ""
242 @echo "Some important Make variables:" 205 @echo "Some important Make variables:"
243 @echo "" 206 @echo ""
207 @echo ' LUA_APIS - default Lua APIs to target ($(LUA_APIS))'
244 @echo " prefix - path to install root ($(value prefix))" 208 @echo " prefix - path to install root ($(value prefix))"
245 @echo ' lua51path - install path for Lua 5.1 modules ($(value lua51path))' 209 @echo ' lua51path - install path for Lua 5.1 modules ($(value lua51path))'
246 @echo 'lua51cpath - install path for Lua 5.1 C modules ($(value lua51cpath))' 210 @echo 'lua51cpath - install path for Lua 5.1 C modules ($(value lua51cpath))'
@@ -249,6 +213,10 @@ $(d)/help:
249 @echo ' lua53path - install path for Lua 5.3 modules ($(value lua53path))' 213 @echo ' lua53path - install path for Lua 5.3 modules ($(value lua53path))'
250 @echo 'lua53cpath - install path for Lua 5.3 C modules ($(value lua53cpath))' 214 @echo 'lua53cpath - install path for Lua 5.3 C modules ($(value lua53cpath))'
251 @echo "" 215 @echo ""
216 @echo 'LUA51_CPPFLAGS - cpp flags for Lua 5.1 headers ($(LUA51_CPPFLAGS))'
217 @echo 'LUA52_CPPFLAGS - cpp flags for Lua 5.2 headers ($(LUA52_CPPFLAGS))'
218 @echo 'LUA53_CPPFLAGS - cpp flags for Lua 5.3 headers ($(LUA53_CPPFLAGS))'
219 @echo ""
252 @echo "(NOTE: all the common GNU-style paths are supported, including" 220 @echo "(NOTE: all the common GNU-style paths are supported, including"
253 @echo "prefix, bindir, libdir, datadir, includedir, and DESTDIR.)" 221 @echo "prefix, bindir, libdir, datadir, includedir, and DESTDIR.)"
254 @echo "" 222 @echo ""
diff --git a/src/compat52.h b/src/compat52.h
deleted file mode 100644
index 163aecb..0000000
--- a/src/compat52.h
+++ /dev/null
@@ -1,168 +0,0 @@
1/* ==========================================================================
2 * compat52.h - Routines for Lua 5.2 compatibility
3 * --------------------------------------------------------------------------
4 * Copyright (c) 2012 William Ahern
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to permit
11 * persons to whom the Software is furnished to do so, subject to the
12 * following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
20 * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
21 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
22 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
23 * USE OR OTHER DEALINGS IN THE SOFTWARE.
24 * ==========================================================================
25 */
26
27
28#if LUA_VERSION_NUM < 503
29
30#define lua_getfield(L, i, f) (lua_getfield(L, (i), (f)), lua_type(L, -1))
31
32#endif
33
34#if LUA_VERSION_NUM < 502
35
36#define LUA_OK 0
37
38
39static void luaL_setmetatable(lua_State *L, const char *tname) {
40 luaL_getmetatable(L, tname);
41 lua_setmetatable(L, -2);
42} /* luaL_setmetatable() */
43
44
45static int lua_absindex(lua_State *L, int idx) {
46 return (idx > 0 || idx <= LUA_REGISTRYINDEX)? idx : lua_gettop(L) + idx + 1;
47} /* lua_absindex() */
48
49
50static void *luaL_testudata(lua_State *L, int arg, const char *tname) {
51 void *p = lua_touserdata(L, arg);
52 int eq;
53
54 if (!p || !lua_getmetatable(L, arg))
55 return 0;
56
57 luaL_getmetatable(L, tname);
58 eq = lua_rawequal(L, -2, -1);
59 lua_pop(L, 2);
60
61 return (eq)? p : 0;
62} /* luaL_testudate() */
63
64
65static void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup) {
66 int i, t = lua_absindex(L, -1 - nup);
67
68 for (; l->name; l++) {
69 for (i = 0; i < nup; i++)
70 lua_pushvalue(L, -nup);
71 lua_pushcclosure(L, l->func, nup);
72 lua_setfield(L, t, l->name);
73 }
74
75 lua_pop(L, nup);
76} /* luaL_setfuncs() */
77
78
79#define luaL_newlibtable(L, l) \
80 lua_createtable(L, 0, (sizeof (l) / sizeof *(l)) - 1)
81
82#define luaL_newlib(L, l) \
83 (luaL_newlibtable((L), (l)), luaL_setfuncs((L), (l), 0))
84
85
86static void luaL_requiref(lua_State *L, const char *modname, lua_CFunction openf, int glb) {
87 lua_pushcfunction(L, openf);
88 lua_pushstring(L, modname);
89 lua_call(L, 1, 1);
90
91 lua_getglobal(L, "package");
92 lua_getfield(L, -1, "loaded");
93 lua_pushvalue(L, -3);
94 lua_setfield(L, -2, modname);
95
96 lua_pop(L, 2);
97
98 if (glb) {
99 lua_pushvalue(L, -1);
100 lua_setglobal(L, modname);
101 }
102} /* luaL_requiref() */
103
104
105#define lua_resume(L, from, nargs) lua_resume((L), (nargs))
106
107
108static void lua_rawgetp(lua_State *L, int index, const void *p) {
109 index = lua_absindex(L, index);
110 lua_pushlightuserdata(L, (void *)p);
111 lua_rawget(L, index);
112} /* lua_rawgetp() */
113
114static void lua_rawsetp(lua_State *L, int index, const void *p) {
115 index = lua_absindex(L, index);
116 lua_pushlightuserdata(L, (void *)p);
117 lua_pushvalue(L, -2);
118 lua_rawset(L, index);
119 lua_pop(L, 1);
120} /* lua_rawsetp() */
121
122
123#ifndef LUA_UNSIGNED
124#define LUA_UNSIGNED unsigned
125#endif
126
127typedef LUA_UNSIGNED lua_Unsigned;
128
129
130static void lua_pushunsigned(lua_State *L, lua_Unsigned n) {
131 lua_pushnumber(L, (lua_Number)n);
132} /* lua_pushunsigned() */
133
134static lua_Unsigned luaL_checkunsigned(lua_State *L, int arg) {
135 return (lua_Unsigned)luaL_checknumber(L, arg);
136} /* luaL_checkunsigned() */
137
138
139static lua_Unsigned luaL_optunsigned(lua_State *L, int arg, lua_Unsigned def) {
140 return (lua_Unsigned)luaL_optnumber(L, arg, (lua_Number)def);
141} /* luaL_optunsigned() */
142
143
144#ifndef LUA_FILEHANDLE /* Not defined by earlier LuaJIT releases */
145#define LUA_FILEHANDLE "FILE*"
146#endif
147
148/*
149 * Lua 5.1 userdata is a simple FILE *, while LuaJIT is a struct with the
150 * first member a FILE *, similar to Lua 5.2.
151 */
152typedef struct luaL_Stream {
153 FILE *f;
154} luaL_Stream;
155
156
157#define lua_rawlen(...) lua_objlen(__VA_ARGS__)
158
159
160#define lua_pushstring(...) lua52_pushstring(__VA_ARGS__)
161
162static const char *lua52_pushstring(lua_State *L, const char *s) {
163 (lua_pushstring)(L, s);
164 return lua_tostring(L, -1);
165} /* lua52_pushstring() */
166
167
168#endif /* LUA_VERSION_NUM < 502 */
diff --git a/src/openssl.c b/src/openssl.c
index 9fc5b97..1b11207 100644
--- a/src/openssl.c
+++ b/src/openssl.c
@@ -75,7 +75,7 @@
75#include <lualib.h> 75#include <lualib.h>
76#include <lauxlib.h> 76#include <lauxlib.h>
77 77
78#include "compat52.h" 78#include "../vendor/compat53/c-api/compat-5.3.h"
79 79
80#define GNUC_2VER(M, m, p) (((M) * 10000) + ((m) * 100) + (p)) 80#define GNUC_2VER(M, m, p) (((M) * 10000) + ((m) * 100) + (p))
81#define GNUC_PREREQ(M, m, p) (__GNUC__ > 0 && GNUC_2VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) >= GNUC_2VER((M), (m), (p))) 81#define GNUC_PREREQ(M, m, p) (__GNUC__ > 0 && GNUC_2VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) >= GNUC_2VER((M), (m), (p)))
@@ -83,11 +83,16 @@
83#define MSC_2VER(M, m, p) ((((M) + 6) * 10000000) + ((m) * 1000000) + (p)) 83#define MSC_2VER(M, m, p) ((((M) + 6) * 10000000) + ((m) * 1000000) + (p))
84#define MSC_PREREQ(M, m, p) (_MSC_FULL_VER > 0 && _MSC_FULL_VER >= MSC_2VER((M), (m), (p))) 84#define MSC_PREREQ(M, m, p) (_MSC_FULL_VER > 0 && _MSC_FULL_VER >= MSC_2VER((M), (m), (p)))
85 85
86#define OPENSSL_PREREQ(M, m, p) \ 86#ifdef LIBRESSL_VERSION_NUMBER
87 (OPENSSL_VERSION_NUMBER >= (((M) << 28) | ((m) << 20) | ((p) << 12)) && !defined LIBRESSL_VERSION_NUMBER) 87#define OPENSSL_PREREQ(M, m, p) (0)
88
89#define LIBRESSL_PREREQ(M, m, p) \ 88#define LIBRESSL_PREREQ(M, m, p) \
90 (LIBRESSL_VERSION_NUMBER >= (((M) << 28) | ((m) << 20) | ((p) << 12))) 89 (LIBRESSL_VERSION_NUMBER >= (((M) << 28) | ((m) << 20) | ((p) << 12)))
90#else
91#define OPENSSL_PREREQ(M, m, p) \
92 (OPENSSL_VERSION_NUMBER >= (((M) << 28) | ((m) << 20) | ((p) << 12)))
93#define LIBRESSL_PREREQ(M, m, p) (0)
94#endif
95
91 96
92#ifndef __has_builtin 97#ifndef __has_builtin
93#define __has_builtin(x) 0 98#define __has_builtin(x) 0
@@ -146,7 +151,11 @@
146#endif 151#endif
147 152
148#ifndef HAVE_DTLSV1_CLIENT_METHOD 153#ifndef HAVE_DTLSV1_CLIENT_METHOD
149#define HAVE_DTLSV1_CLIENT_METHOD (!defined OPENSSL_NO_DTLS1) 154#ifdef OPENSSL_NO_DTLS1
155#define HAVE_DTLSV1_CLIENT_METHOD (0)
156#else
157#define HAVE_DTLSV1_CLIENT_METHOD (1)
158#endif
150#endif 159#endif
151 160
152#ifndef HAVE_DTLSV1_SERVER_METHOD 161#ifndef HAVE_DTLSV1_SERVER_METHOD
@@ -154,7 +163,11 @@
154#endif 163#endif
155 164
156#ifndef HAVE_DTLS_CLIENT_METHOD 165#ifndef HAVE_DTLS_CLIENT_METHOD
157#define HAVE_DTLS_CLIENT_METHOD (OPENSSL_PREREQ(1,0,2) && !defined OPENSSL_NO_DTLS1) 166#ifdef OPENSSL_NO_DTLS1
167#define HAVE_DTLS_CLIENT_METHOD (0)
168#else
169#define HAVE_DTLS_CLIENT_METHOD OPENSSL_PREREQ(1,0,2)
170#endif
158#endif 171#endif
159 172
160#ifndef HAVE_DTLS_SERVER_METHOD 173#ifndef HAVE_DTLS_SERVER_METHOD
@@ -162,7 +175,11 @@
162#endif 175#endif
163 176
164#ifndef HAVE_DTLSV1_2_CLIENT_METHOD 177#ifndef HAVE_DTLSV1_2_CLIENT_METHOD
165#define HAVE_DTLSV1_2_CLIENT_METHOD (OPENSSL_PREREQ(1,0,2) && !defined OPENSSL_NO_DTLS1) 178#ifdef OPENSSL_NO_DTLS1
179#define HAVE_DTLSV1_2_CLIENT_METHOD (0)
180#else
181#define HAVE_DTLSV1_2_CLIENT_METHOD OPENSSL_PREREQ(1,0,2)
182#endif
166#endif 183#endif
167 184
168#ifndef HAVE_DTLSV1_2_SERVER_METHOD 185#ifndef HAVE_DTLSV1_2_SERVER_METHOD
@@ -229,10 +246,6 @@
229#define HAVE_RSA_GET0_KEY OPENSSL_PREREQ(1,1,0) 246#define HAVE_RSA_GET0_KEY OPENSSL_PREREQ(1,1,0)
230#endif 247#endif
231 248
232#ifndef HAVE_RSA_PKCS1_PSS_PADDING
233#define HAVE_RSA_PKCS1_PSS_PADDING (defined RSA_PKCS1_PSS_PADDING || OPENSSL_PREREQ(1,0,0) || LIBRESSL_PREREQ(2,0,0))
234#endif
235
236#ifndef HAVE_RSA_SET0_CRT_PARAMS 249#ifndef HAVE_RSA_SET0_CRT_PARAMS
237#define HAVE_RSA_SET0_CRT_PARAMS OPENSSL_PREREQ(1,1,0) 250#define HAVE_RSA_SET0_CRT_PARAMS OPENSSL_PREREQ(1,1,0)
238#endif 251#endif
@@ -253,6 +266,14 @@
253#define HAVE_SSL_CTX_GET0_PARAM OPENSSL_PREREQ(1,0,2) 266#define HAVE_SSL_CTX_GET0_PARAM OPENSSL_PREREQ(1,0,2)
254#endif 267#endif
255 268
269#ifndef HAVE_SSL_CTX_SET_CURVES_LIST
270#define HAVE_SSL_CTX_SET_CURVES_LIST (OPENSSL_PREREQ(1,0,2) || LIBRESSL_PREREQ(2,5,1))
271#endif
272
273#ifndef HAVE_SSL_CTX_SET_ECDH_AUTO
274#define HAVE_SSL_CTX_SET_ECDH_AUTO ((OPENSSL_PREREQ(1,0,2) && !OPENSSL_PREREQ(1,1,0)) || LIBRESSL_PREREQ(2,1,2))
275#endif
276
256#ifndef HAVE_SSL_CTX_SET_ALPN_PROTOS 277#ifndef HAVE_SSL_CTX_SET_ALPN_PROTOS
257#define HAVE_SSL_CTX_SET_ALPN_PROTOS (OPENSSL_PREREQ(1,0,2) || LIBRESSL_PREREQ(2,1,3)) 278#define HAVE_SSL_CTX_SET_ALPN_PROTOS (OPENSSL_PREREQ(1,0,2) || LIBRESSL_PREREQ(2,1,3))
258#endif 279#endif
@@ -261,6 +282,10 @@
261#define HAVE_SSL_CTX_SET_ALPN_SELECT_CB HAVE_SSL_CTX_SET_ALPN_PROTOS 282#define HAVE_SSL_CTX_SET_ALPN_SELECT_CB HAVE_SSL_CTX_SET_ALPN_PROTOS
262#endif 283#endif
263 284
285#ifndef HAVE_SSL_CTX_SET_TLSEXT_SERVERNAME_CALLBACK
286#define HAVE_SSL_CTX_SET_TLSEXT_SERVERNAME_CALLBACK OPENSSL_PREREQ(1,0,0)
287#endif
288
264#ifndef HAVE_SSL_CTX_SET1_CERT_STORE 289#ifndef HAVE_SSL_CTX_SET1_CERT_STORE
265#define HAVE_SSL_CTX_SET1_CERT_STORE (HAVE_SSL_CTX_set1_cert_store || 0) /* backwards compatible with old macro name */ 290#define HAVE_SSL_CTX_SET1_CERT_STORE (HAVE_SSL_CTX_set1_cert_store || 0) /* backwards compatible with old macro name */
266#endif 291#endif
@@ -293,6 +318,10 @@
293#define HAVE_SSL_SET_ALPN_PROTOS HAVE_SSL_CTX_SET_ALPN_PROTOS 318#define HAVE_SSL_SET_ALPN_PROTOS HAVE_SSL_CTX_SET_ALPN_PROTOS
294#endif 319#endif
295 320
321#ifndef HAVE_SSL_SET_CURVES_LIST
322#define HAVE_SSL_SET_CURVES_LIST (OPENSSL_PREREQ(1,0,2) || LIBRESSL_PREREQ(2,5,1))
323#endif
324
296#ifndef HAVE_SSL_SET1_PARAM 325#ifndef HAVE_SSL_SET1_PARAM
297#define HAVE_SSL_SET1_PARAM OPENSSL_PREREQ(1,0,2) 326#define HAVE_SSL_SET1_PARAM OPENSSL_PREREQ(1,0,2)
298#endif 327#endif
@@ -309,12 +338,32 @@
309#define HAVE_SSL_UP_REF OPENSSL_PREREQ(1,1,0) 338#define HAVE_SSL_UP_REF OPENSSL_PREREQ(1,1,0)
310#endif 339#endif
311 340
312#ifndef HAVE_SSLV2_CLIENT_METHOD 341#ifndef HAVE_SSL_OP_NO_SSL_MASK
313#define HAVE_SSLV2_CLIENT_METHOD (!OPENSSL_PREREQ(1,1,0) && !defined OPENSSL_NO_SSL2) 342#define HAVE_SSL_OP_NO_SSL_MASK OPENSSL_PREREQ(1,0,2)
314#endif 343#endif
315 344
316#ifndef HAVE_SSLV2_SERVER_METHOD 345#ifndef HAVE_SSL_OP_NO_DTLS_MASK
317#define HAVE_SSLV2_SERVER_METHOD (!OPENSSL_PREREQ(1,1,0) && !defined OPENSSL_NO_SSL2) 346#define HAVE_SSL_OP_NO_DTLS_MASK OPENSSL_PREREQ(1,1,0)
347#endif
348
349#ifndef HAVE_STACK_OPENSSL_STRING_FUNCS
350#define HAVE_STACK_OPENSSL_STRING_FUNCS (OPENSSL_PREREQ(1,0,0) || LIBRESSL_PREREQ(2,0,0))
351#endif
352
353#ifndef HAVE_X509_CRL_GET0_LASTUPDATE
354#define HAVE_X509_CRL_GET0_LASTUPDATE OPENSSL_PREREQ(1,1,0)
355#endif
356
357#ifndef HAVE_X509_CRL_GET0_NEXTUPDATE
358#define HAVE_X509_CRL_GET0_NEXTUPDATE OPENSSL_PREREQ(1,1,0)
359#endif
360
361#ifndef HAVE_X509_CRL_SET1_LASTUPDATE
362#define HAVE_X509_CRL_SET1_LASTUPDATE OPENSSL_PREREQ(1,1,0)
363#endif
364
365#ifndef HAVE_X509_CRL_SET1_NEXTUPDATE
366#define HAVE_X509_CRL_SET1_NEXTUPDATE OPENSSL_PREREQ(1,1,0)
318#endif 367#endif
319 368
320#ifndef HAVE_X509_GET_SIGNATURE_NID 369#ifndef HAVE_X509_GET_SIGNATURE_NID
@@ -358,7 +407,11 @@
358#endif 407#endif
359 408
360#ifndef STRERROR_R_CHAR_P 409#ifndef STRERROR_R_CHAR_P
361#define STRERROR_R_CHAR_P (defined __GLIBC__ && (_GNU_SOURCE || !(_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600))) 410#ifdef __GLIBC__
411#define STRERROR_R_CHAR_P (_GNU_SOURCE || !(_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600))
412#else
413#define STRERROR_R_CHAR_P (0)
414#endif
362#endif 415#endif
363 416
364#ifndef LIST_HEAD 417#ifndef LIST_HEAD
@@ -678,6 +731,44 @@ static void *loadfield_udata(lua_State *L, int index, const char *k, const char
678} /* loadfield_udata() */ 731} /* loadfield_udata() */
679 732
680 733
734/* Forward declaration */
735static SSL *ssl_push(lua_State *, SSL *);
736
737/* push an ssl object into lua in a way that is safe from OOM
738 * Lua 5.1 does not support normally returning values from lua_cpcall
739 * to return a value, we instead return it via an error object
740 */
741static int ssl_pushsafe_helper(lua_State *L) {
742 ssl_push(L, lua_touserdata(L, 1));
743#if LUA_VERSION_NUM <= 501
744 return lua_error(L);
745#else
746 return 1;
747#endif
748}
749
750static int ssl_pushsafe(lua_State *L, SSL *ssl) {
751 int status;
752#if LUA_VERSION_NUM <= 501
753 status = lua_cpcall(L, ssl_pushsafe_helper, ssl);
754 if (status == LUA_ERRRUN)
755 status = LUA_OK;
756 else if (status == LUA_OK)
757 /* this should be impossible */
758 status = LUA_ERRRUN;
759 else
760 lua_pop(L, 1);
761#else
762 lua_pushcfunction(L, ssl_pushsafe_helper);
763 lua_pushlightuserdata(L, ssl);
764 status = lua_pcall(L, 1, 1, 0);
765 if (status != LUA_OK)
766 lua_pop(L, 1);
767#endif
768 return status;
769}
770
771
681/* 772/*
682 * Auxiliary C routines 773 * Auxiliary C routines
683 * 774 *
@@ -1623,6 +1714,22 @@ static int compat_SSL_up_ref(SSL *ssl) {
1623} /* compat_SSL_up_ref() */ 1714} /* compat_SSL_up_ref() */
1624#endif 1715#endif
1625 1716
1717#if !HAVE_SSL_OP_NO_SSL_MASK
1718/* SSL_OP_NO_SSL_MASK was introduced in 1.0.2
1719 1.0.1 had up to TLSv1_2
1720 0.9.8-1.0.0 had up to TLSv1
1721*/
1722#ifdef SSL_OP_NO_TLSv1_2
1723#define SSL_OP_NO_SSL_MASK (SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_TLSv1|SSL_OP_NO_TLSv1_1|SSL_OP_NO_TLSv1_2)
1724#else
1725#define SSL_OP_NO_SSL_MASK (SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_TLSv1)
1726#endif
1727#endif
1728
1729#if !HAVE_SSL_OP_NO_DTLS_MASK && HAVE_DTLS_CLIENT_METHOD
1730#define SSL_OP_NO_DTLS_MASK (SSL_OP_NO_DTLSv1|SSL_OP_NO_DTLSv1_2)
1731#endif
1732
1626#if !HAVE_SSL_CTX_GET0_PARAM 1733#if !HAVE_SSL_CTX_GET0_PARAM
1627#define SSL_CTX_get0_param(ctx) compat_SSL_CTX_get0_param((ctx)) 1734#define SSL_CTX_get0_param(ctx) compat_SSL_CTX_get0_param((ctx))
1628 1735
@@ -1639,6 +1746,12 @@ static int compat_SSL_CTX_set1_param(SSL_CTX *ctx, X509_VERIFY_PARAM *vpm) {
1639} /* compat_SSL_CTX_set1_param() */ 1746} /* compat_SSL_CTX_set1_param() */
1640#endif 1747#endif
1641 1748
1749#if !HAVE_STACK_OPENSSL_STRING_FUNCS
1750#define sk_OPENSSL_STRING_num(s) sk_num(s)
1751#define sk_OPENSSL_STRING_value(s, i) sk_value((s), (i))
1752#define sk_OPENSSL_STRING_free(s) X509_email_free(s)
1753#endif
1754
1642#if !HAVE_X509_GET0_EXT 1755#if !HAVE_X509_GET0_EXT
1643#define X509_get0_ext(crt, i) X509_get_ext((crt), (i)) 1756#define X509_get0_ext(crt, i) X509_get_ext((crt), (i))
1644#endif 1757#endif
@@ -1651,6 +1764,22 @@ static int compat_SSL_CTX_set1_param(SSL_CTX *ctx, X509_VERIFY_PARAM *vpm) {
1651#define X509_CRL_get0_ext(crt, i) X509_CRL_get_ext((crt), (i)) 1764#define X509_CRL_get0_ext(crt, i) X509_CRL_get_ext((crt), (i))
1652#endif 1765#endif
1653 1766
1767#if !HAVE_X509_CRL_GET0_LASTUPDATE
1768#define X509_CRL_get0_lastUpdate(crl) ((const ASN1_TIME*)X509_CRL_get_lastUpdate(crl))
1769#endif
1770
1771#if !HAVE_X509_CRL_GET0_NEXTUPDATE
1772#define X509_CRL_get0_nextUpdate(crl) ((const ASN1_TIME*)X509_CRL_get_nextUpdate(crl))
1773#endif
1774
1775#if !HAVE_X509_CRL_SET1_LASTUPDATE
1776#define X509_CRL_set1_lastUpdate(crl, s) X509_CRL_set_lastUpdate((crl), (ASN1_TIME*)(s))
1777#endif
1778
1779#if !HAVE_X509_CRL_SET1_NEXTUPDATE
1780#define X509_CRL_set1_nextUpdate(crl, s) X509_CRL_set_nextUpdate((crl), (ASN1_TIME*)(s))
1781#endif
1782
1654#if !HAVE_X509_EXTENSION_GET0_OBJECT 1783#if !HAVE_X509_EXTENSION_GET0_OBJECT
1655#define X509_EXTENSION_get0_object(ext) X509_EXTENSION_get_object((ext)) 1784#define X509_EXTENSION_get0_object(ext) X509_EXTENSION_get_object((ext))
1656#endif 1785#endif
@@ -1784,6 +1913,7 @@ static int compat_init(void) {
1784 if (done) 1913 if (done)
1785 goto epilog; 1914 goto epilog;
1786 1915
1916#if defined compat_X509_STORE_free
1787 /* 1917 /*
1788 * We need to unconditionally install at least one external 1918 * We need to unconditionally install at least one external
1789 * application data callback. Because these can never be 1919 * application data callback. Because these can never be
@@ -1792,7 +1922,6 @@ static int compat_init(void) {
1792 if ((error = dl_anchor())) 1922 if ((error = dl_anchor()))
1793 goto epilog; 1923 goto epilog;
1794 1924
1795#if defined compat_X509_STORE_free
1796 /* 1925 /*
1797 * Test if X509_STORE_free obeys reference counts by installing an 1926 * Test if X509_STORE_free obeys reference counts by installing an
1798 * onfree callback. 1927 * onfree callback.
@@ -1929,6 +2058,7 @@ struct ex_data {
1929 2058
1930enum { 2059enum {
1931 EX_SSL_CTX_ALPN_SELECT_CB, 2060 EX_SSL_CTX_ALPN_SELECT_CB,
2061 EX_SSL_CTX_TLSEXT_SERVERNAME_CB,
1932}; 2062};
1933 2063
1934static struct ex_type { 2064static struct ex_type {
@@ -1938,6 +2068,7 @@ static struct ex_type {
1938 int (*set_ex_data)(); 2068 int (*set_ex_data)();
1939} ex_type[] = { 2069} ex_type[] = {
1940 [EX_SSL_CTX_ALPN_SELECT_CB] = { CRYPTO_EX_INDEX_SSL_CTX, -1, &SSL_CTX_get_ex_data, &SSL_CTX_set_ex_data }, 2070 [EX_SSL_CTX_ALPN_SELECT_CB] = { CRYPTO_EX_INDEX_SSL_CTX, -1, &SSL_CTX_get_ex_data, &SSL_CTX_set_ex_data },
2071 [EX_SSL_CTX_TLSEXT_SERVERNAME_CB] = { CRYPTO_EX_INDEX_SSL_CTX, -1, &SSL_CTX_get_ex_data, &SSL_CTX_set_ex_data },
1941}; 2072};
1942 2073
1943#if OPENSSL_PREREQ(1,1,0) 2074#if OPENSSL_PREREQ(1,1,0)
@@ -3081,7 +3212,8 @@ static int pk_new(lua_State *L) {
3081 if (lua_istable(L, 1) || lua_isnil(L, 1)) { 3212 if (lua_istable(L, 1) || lua_isnil(L, 1)) {
3082 int type = EVP_PKEY_RSA; 3213 int type = EVP_PKEY_RSA;
3083 unsigned bits = 1024; 3214 unsigned bits = 1024;
3084 unsigned exp = 65537; 3215 BIGNUM *exp = NULL;
3216 int generator = 2;
3085 int curve = NID_X9_62_prime192v1; 3217 int curve = NID_X9_62_prime192v1;
3086 const char *id; 3218 const char *id;
3087 const char *dhparam = NULL; 3219 const char *dhparam = NULL;
@@ -3111,23 +3243,46 @@ static int pk_new(lua_State *L) {
3111 luaL_argcheck(L, type != NID_undef, 1, lua_pushfstring(L, "%s: invalid key type", id)); 3243 luaL_argcheck(L, type != NID_undef, 1, lua_pushfstring(L, "%s: invalid key type", id));
3112 } 3244 }
3113 3245
3114 if (loadfield(L, 1, "bits", LUA_TNUMBER, &n)) { 3246 switch(type) {
3115 luaL_argcheck(L, n > 0 && n < UINT_MAX, 1, lua_pushfstring(L, "%f: `bits' invalid", n)); 3247 case EVP_PKEY_RSA:
3116 bits = (unsigned)n; 3248 if (loadfield(L, 1, "bits", LUA_TNUMBER, &n)) {
3117 } 3249 luaL_argcheck(L, n > 0 && n < UINT_MAX, 1, lua_pushfstring(L, "%f: `bits' invalid", n));
3250 bits = (unsigned)n;
3251 }
3118 3252
3119 if (loadfield(L, 1, "exp", LUA_TNUMBER, &n)) { 3253 if (!getfield(L, 1, "exp")) {
3120 luaL_argcheck(L, n > 0 && n < UINT_MAX, 1, lua_pushfstring(L, "%f: `exp' invalid", n)); 3254 exp = checkbig(L, -1);
3121 exp = (unsigned)n; 3255 } else {
3122 } 3256 /* default to 65537 */
3257 exp = bn_push(L);
3258 if (!BN_add_word(exp, 65537))
3259 return auxL_error(L, auxL_EOPENSSL, "pkey.new");
3260 }
3261 break;
3262 case EVP_PKEY_DH:
3263 /* dhparam field can contain a PEM encoded string.
3264 The "dhparam" field takes precedence over "bits" */
3265 if (loadfield(L, 1, "dhparam", LUA_TSTRING, &dhparam))
3266 break;
3123 3267
3124 if (loadfield(L, 1, "curve", LUA_TSTRING, &id)) { 3268 if (loadfield(L, 1, "bits", LUA_TNUMBER, &n)) {
3125 if (!auxS_txt2nid(&curve, id)) 3269 luaL_argcheck(L, n > 0 && n < UINT_MAX, 1, lua_pushfstring(L, "%f: `bits' invalid", n));
3126 luaL_argerror(L, 1, lua_pushfstring(L, "%s: invalid curve", id)); 3270 bits = (unsigned)n;
3127 } 3271 }
3128 3272
3129 /* dhparam field can contain a PEM encoded string. */ 3273 /* compat: DH used to use the 'exp' field for the generator */
3130 loadfield(L, 1, "dhparam", LUA_TSTRING, &dhparam); 3274 if (loadfield(L, 1, "generator", LUA_TNUMBER, &n) || loadfield(L, 1, "exp", LUA_TNUMBER, &n)) {
3275 luaL_argcheck(L, n > 0 && n <= INT_MAX, 1, lua_pushfstring(L, "%f: `exp' invalid", n));
3276 generator = (int)n;
3277 }
3278 break;
3279 case EVP_PKEY_EC:
3280 if (loadfield(L, 1, "curve", LUA_TSTRING, &id)) {
3281 if (!auxS_txt2nid(&curve, id))
3282 luaL_argerror(L, 1, lua_pushfstring(L, "%s: invalid curve", id));
3283 }
3284 break;
3285 }
3131 3286
3132creat: 3287creat:
3133 if (!(*ud = EVP_PKEY_new())) 3288 if (!(*ud = EVP_PKEY_new()))
@@ -3137,9 +3292,14 @@ creat:
3137 case EVP_PKEY_RSA: { 3292 case EVP_PKEY_RSA: {
3138 RSA *rsa; 3293 RSA *rsa;
3139 3294
3140 if (!(rsa = RSA_generate_key(bits, exp, 0, 0))) 3295 if (!(rsa = RSA_new()))
3141 return auxL_error(L, auxL_EOPENSSL, "pkey.new"); 3296 return auxL_error(L, auxL_EOPENSSL, "pkey.new");
3142 3297
3298 if (!RSA_generate_key_ex(rsa, bits, exp, 0)) {
3299 RSA_free(rsa);
3300 return auxL_error(L, auxL_EOPENSSL, "pkey.new");
3301 }
3302
3143 EVP_PKEY_set1_RSA(*ud, rsa); 3303 EVP_PKEY_set1_RSA(*ud, rsa);
3144 3304
3145 RSA_free(rsa); 3305 RSA_free(rsa);
@@ -3149,9 +3309,14 @@ creat:
3149 case EVP_PKEY_DSA: { 3309 case EVP_PKEY_DSA: {
3150 DSA *dsa; 3310 DSA *dsa;
3151 3311
3152 if (!(dsa = DSA_generate_parameters(bits, 0, 0, 0, 0, 0, 0))) 3312 if (!(dsa = DSA_new()))
3153 return auxL_error(L, auxL_EOPENSSL, "pkey.new"); 3313 return auxL_error(L, auxL_EOPENSSL, "pkey.new");
3154 3314
3315 if (!DSA_generate_parameters_ex(dsa, bits, 0, 0, 0, 0, 0)) {
3316 DSA_free(dsa);
3317 return auxL_error(L, auxL_EOPENSSL, "pkey.new");
3318 }
3319
3155 if (!DSA_generate_key(dsa)) { 3320 if (!DSA_generate_key(dsa)) {
3156 DSA_free(dsa); 3321 DSA_free(dsa);
3157 return auxL_error(L, auxL_EOPENSSL, "pkey.new"); 3322 return auxL_error(L, auxL_EOPENSSL, "pkey.new");
@@ -3179,8 +3344,15 @@ creat:
3179 BIO_free(bio); 3344 BIO_free(bio);
3180 if (!dh) 3345 if (!dh)
3181 return auxL_error(L, auxL_EOPENSSL, "pkey.new"); 3346 return auxL_error(L, auxL_EOPENSSL, "pkey.new");
3182 } else if (!(dh = DH_generate_parameters(bits, exp, 0, 0))) 3347 } else {
3183 return auxL_error(L, auxL_EOPENSSL, "pkey.new"); 3348 if (!(dh = DH_new()))
3349 return auxL_error(L, auxL_EOPENSSL, "pkey.new");
3350
3351 if (!DH_generate_parameters_ex(dh, bits, generator, 0)) {
3352 DH_free(dh);
3353 return auxL_error(L, auxL_EOPENSSL, "pkey.new");
3354 }
3355 }
3184 3356
3185 3357
3186 if (!DH_generate_key(dh)) { 3358 if (!DH_generate_key(dh)) {
@@ -4319,7 +4491,7 @@ static const auxL_IntegerReg pk_rsa_pad_opts[] = {
4319 { "RSA_NO_PADDING", RSA_NO_PADDING }, // no padding 4491 { "RSA_NO_PADDING", RSA_NO_PADDING }, // no padding
4320 { "RSA_PKCS1_OAEP_PADDING", RSA_PKCS1_OAEP_PADDING }, // OAEP padding (encrypt and decrypt only) 4492 { "RSA_PKCS1_OAEP_PADDING", RSA_PKCS1_OAEP_PADDING }, // OAEP padding (encrypt and decrypt only)
4321 { "RSA_X931_PADDING", RSA_X931_PADDING }, // (signature operations only) 4493 { "RSA_X931_PADDING", RSA_X931_PADDING }, // (signature operations only)
4322#if HAVE_RSA_PKCS1_PSS_PADDING 4494#if RSA_PKCS1_PSS_PADDING
4323 { "RSA_PKCS1_PSS_PADDING", RSA_PKCS1_PSS_PADDING }, // (sign and verify only) 4495 { "RSA_PKCS1_PSS_PADDING", RSA_PKCS1_PSS_PADDING }, // (sign and verify only)
4324#endif 4496#endif
4325 { NULL, 0 }, 4497 { NULL, 0 },
@@ -5523,17 +5695,17 @@ static _Bool scan(int *i, char **cp, int n, int signok) {
5523} /* scan() */ 5695} /* scan() */
5524 5696
5525 5697
5526static double timeutc(ASN1_TIME *time) { 5698static double timeutc(const ASN1_TIME *time) {
5527 char buf[32] = "", *cp; 5699 char buf[32] = "", *cp;
5528 struct tm tm = { 0 }; 5700 struct tm tm = { 0 };
5529 int gmtoff = 0, year, i; 5701 int gmtoff = 0, year, i;
5530 5702
5531 if (!ASN1_TIME_check(time)) 5703 if (!ASN1_TIME_check((ASN1_STRING *)time))
5532 return 0; 5704 return 0;
5533 5705
5534 cp = strncpy(buf, (const char *)ASN1_STRING_get0_data((ASN1_STRING *)time), sizeof buf - 1); 5706 cp = strncpy(buf, (const char *)ASN1_STRING_get0_data((ASN1_STRING *)time), sizeof buf - 1);
5535 5707
5536 if (ASN1_STRING_type(time) == V_ASN1_GENERALIZEDTIME) { 5708 if (ASN1_STRING_type((ASN1_STRING *)time) == V_ASN1_GENERALIZEDTIME) {
5537 if (!scan(&year, &cp, 4, 1)) 5709 if (!scan(&year, &cp, 4, 1))
5538 goto badfmt; 5710 goto badfmt;
5539 } else { 5711 } else {
@@ -5595,7 +5767,7 @@ badfmt:
5595static int xc_getLifetime(lua_State *L) { 5767static int xc_getLifetime(lua_State *L) {
5596 X509 *crt = checksimple(L, 1, X509_CERT_CLASS); 5768 X509 *crt = checksimple(L, 1, X509_CERT_CLASS);
5597 double begin = INFINITY, end = INFINITY; 5769 double begin = INFINITY, end = INFINITY;
5598 ASN1_TIME *time; 5770 const ASN1_TIME *time;
5599 5771
5600 if ((time = X509_get_notBefore(crt))) 5772 if ((time = X509_get_notBefore(crt)))
5601 begin = timeutc(time); 5773 begin = timeutc(time);
@@ -6684,10 +6856,21 @@ static int xx_new(lua_State *L) {
6684 if (!ok) 6856 if (!ok)
6685 return auxL_error(L, auxL_EOPENSSL, "x509.crl.new"); 6857 return auxL_error(L, auxL_EOPENSSL, "x509.crl.new");
6686 } else { 6858 } else {
6859 ASN1_TIME *tm;
6860
6687 if (!(*ud = X509_CRL_new())) 6861 if (!(*ud = X509_CRL_new()))
6688 return auxL_error(L, auxL_EOPENSSL, "x509.crl.new"); 6862 return auxL_error(L, auxL_EOPENSSL, "x509.crl.new");
6689 6863
6690 X509_gmtime_adj(X509_CRL_get_lastUpdate(*ud), 0); 6864 /* initialize last updated time to now */
6865 if (!(tm = ASN1_TIME_set(NULL, time(NULL))))
6866 return auxL_error(L, auxL_EOPENSSL, "x509.crl.new");
6867
6868 if (!X509_CRL_set1_lastUpdate(*ud, tm)) {
6869 ASN1_TIME_free(tm);
6870 return auxL_error(L, auxL_EOPENSSL, "x509.crl.new");
6871 }
6872
6873 ASN1_TIME_free(tm);
6691 } 6874 }
6692 6875
6693 return 1; 6876 return 1;
@@ -6724,9 +6907,9 @@ static int xx_setVersion(lua_State *L) {
6724static int xx_getLastUpdate(lua_State *L) { 6907static int xx_getLastUpdate(lua_State *L) {
6725 X509_CRL *crl = checksimple(L, 1, X509_CRL_CLASS); 6908 X509_CRL *crl = checksimple(L, 1, X509_CRL_CLASS);
6726 double updated = INFINITY; 6909 double updated = INFINITY;
6727 ASN1_TIME *time; 6910 const ASN1_TIME *time;
6728 6911
6729 if ((time = X509_CRL_get_lastUpdate(crl))) 6912 if ((time = X509_CRL_get0_lastUpdate(crl)))
6730 updated = timeutc(time); 6913 updated = timeutc(time);
6731 6914
6732 if (isfinite(updated)) 6915 if (isfinite(updated))
@@ -6741,23 +6924,30 @@ static int xx_getLastUpdate(lua_State *L) {
6741static int xx_setLastUpdate(lua_State *L) { 6924static int xx_setLastUpdate(lua_State *L) {
6742 X509_CRL *crl = checksimple(L, 1, X509_CRL_CLASS); 6925 X509_CRL *crl = checksimple(L, 1, X509_CRL_CLASS);
6743 double updated = luaL_checknumber(L, 2); 6926 double updated = luaL_checknumber(L, 2);
6927 ASN1_TIME *time;
6744 6928
6745 /* lastUpdate always present */ 6929 if (!(time = ASN1_TIME_set(NULL, updated)))
6746 if (!ASN1_TIME_set(X509_CRL_get_lastUpdate(crl), updated)) 6930 goto error;
6747 return auxL_error(L, auxL_EOPENSSL, "x509.crl:setLastUpdate"); 6931
6932 if (!X509_CRL_set1_lastUpdate(crl, time))
6933 goto error;
6748 6934
6749 lua_pushboolean(L, 1); 6935 lua_pushboolean(L, 1);
6750 6936
6751 return 1; 6937 return 1;
6938error:
6939 ASN1_TIME_free(time);
6940
6941 return auxL_error(L, auxL_EOPENSSL, "x509.crl:setLastUpdate");
6752} /* xx_setLastUpdate() */ 6942} /* xx_setLastUpdate() */
6753 6943
6754 6944
6755static int xx_getNextUpdate(lua_State *L) { 6945static int xx_getNextUpdate(lua_State *L) {
6756 X509_CRL *crl = checksimple(L, 1, X509_CRL_CLASS); 6946 X509_CRL *crl = checksimple(L, 1, X509_CRL_CLASS);
6757 double updateby = INFINITY; 6947 double updateby = INFINITY;
6758 ASN1_TIME *time; 6948 const ASN1_TIME *time;
6759 6949
6760 if ((time = X509_CRL_get_nextUpdate(crl))) 6950 if ((time = X509_CRL_get0_nextUpdate(crl)))
6761 updateby = timeutc(time); 6951 updateby = timeutc(time);
6762 6952
6763 if (isfinite(updateby)) 6953 if (isfinite(updateby))
@@ -6772,30 +6962,19 @@ static int xx_getNextUpdate(lua_State *L) {
6772static int xx_setNextUpdate(lua_State *L) { 6962static int xx_setNextUpdate(lua_State *L) {
6773 X509_CRL *crl = checksimple(L, 1, X509_CRL_CLASS); 6963 X509_CRL *crl = checksimple(L, 1, X509_CRL_CLASS);
6774 double updateby = luaL_checknumber(L, 2); 6964 double updateby = luaL_checknumber(L, 2);
6775 ASN1_TIME *time = NULL; 6965 ASN1_TIME *time;
6776
6777 if (X509_CRL_get_nextUpdate(crl)) {
6778 if (!ASN1_TIME_set(X509_CRL_get_nextUpdate(crl), updateby))
6779 goto error;
6780 } else {
6781 if (!(time = ASN1_TIME_new()))
6782 goto error;
6783
6784 if (!(ASN1_TIME_set(time, updateby)))
6785 goto error;
6786 6966
6787 if (!X509_CRL_set_nextUpdate(crl, time)) 6967 if (!(time = ASN1_TIME_set(NULL, updateby)))
6788 goto error; 6968 goto error;
6789 6969
6790 time = NULL; 6970 if (!X509_CRL_set1_nextUpdate(crl, time))
6791 } 6971 goto error;
6792 6972
6793 lua_pushboolean(L, 1); 6973 lua_pushboolean(L, 1);
6794 6974
6795 return 1; 6975 return 1;
6796error: 6976error:
6797 if (time) 6977 ASN1_TIME_free(time);
6798 ASN1_TIME_free(time);
6799 6978
6800 return auxL_error(L, auxL_EOPENSSL, "x509.crl:setNextUpdate"); 6979 return auxL_error(L, auxL_EOPENSSL, "x509.crl:setNextUpdate");
6801} /* xx_setNextUpdate() */ 6980} /* xx_setNextUpdate() */
@@ -7670,11 +7849,6 @@ int luaopen__openssl_pkcs12(lua_State *L) {
7670 * 7849 *
7671 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 7850 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
7672 7851
7673/*
7674 * NOTE: TLS methods and flags were added in tandem. For example, if the
7675 * macro SSL_OP_NO_TLSv1_1 is defined we know TLSv1_1_server_method is also
7676 * declared and defined.
7677 */
7678static int sx_new(lua_State *L) { 7852static int sx_new(lua_State *L) {
7679 static const char *const opts[] = { 7853 static const char *const opts[] = {
7680 [0] = "SSL", 7854 [0] = "SSL",
@@ -7690,81 +7864,109 @@ static int sx_new(lua_State *L) {
7690 [14] = "DTLSv1_2", [15] = "DTLSv1.2", 7864 [14] = "DTLSv1_2", [15] = "DTLSv1.2",
7691 NULL 7865 NULL
7692 }; 7866 };
7693 /* later versions of SSL declare a const qualifier on the return type */ 7867 int method_enum;
7694 __typeof__(&TLSv1_client_method) method = &TLSv1_client_method;
7695 _Bool srv; 7868 _Bool srv;
7696 SSL_CTX **ud; 7869 SSL_CTX **ud;
7697 int options = 0; 7870 int options = 0;
7698 7871
7699 lua_settop(L, 2); 7872 lua_settop(L, 2);
7873 method_enum = auxL_checkoption(L, 1, "TLS", opts, 1);
7700 srv = lua_toboolean(L, 2); 7874 srv = lua_toboolean(L, 2);
7701 7875
7702 switch (auxL_checkoption(L, 1, "TLS", opts, 1)) { 7876 switch (method_enum) {
7703 case 0: /* SSL */ 7877 case 0: /* SSL */
7704 method = (srv)? &SSLv23_server_method : &SSLv23_client_method;
7705 options = SSL_OP_NO_SSLv2; 7878 options = SSL_OP_NO_SSLv2;
7706 break; 7879 break;
7707 case 1: /* TLS */ 7880 case 1: /* TLS */
7708 method = (srv)? &SSLv23_server_method : &SSLv23_client_method;
7709 options = SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3; 7881 options = SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3;
7710 break; 7882 break;
7711#if HAVE_SSLV2_CLIENT_METHOD && HAVE_SSLV2_SERVER_METHOD
7712 case 2: /* SSLv2 */ 7883 case 2: /* SSLv2 */
7713 method = (srv)? &SSLv2_server_method : &SSLv2_client_method; 7884 options = SSL_OP_NO_SSL_MASK & ~SSL_OP_NO_SSLv2;
7714 break; 7885 break;
7715#endif
7716#ifndef OPENSSL_NO_SSL3
7717 case 3: /* SSLv3 */ 7886 case 3: /* SSLv3 */
7718 method = (srv)? &SSLv3_server_method : &SSLv3_client_method; 7887 options = SSL_OP_NO_SSL_MASK & ~SSL_OP_NO_SSLv3;
7719 break; 7888 break;
7720#endif
7721 case 4: /* SSLv23 */ 7889 case 4: /* SSLv23 */
7722 method = (srv)? &SSLv23_server_method : &SSLv23_client_method;
7723 break; 7890 break;
7724 case 5: /* TLSv1 */ 7891 case 5: /* TLSv1 */
7725 case 6: /* TLSv1.0 */ 7892 case 6: /* TLSv1.0 */
7726 method = (srv)? &TLSv1_server_method : &TLSv1_client_method; 7893 options = SSL_OP_NO_SSL_MASK & ~SSL_OP_NO_TLSv1;
7727 break; 7894 break;
7728#if defined SSL_OP_NO_TLSv1_1 7895#if defined SSL_OP_NO_TLSv1_1
7729 case 7: /* TLSv1_1 */ 7896 case 7: /* TLSv1_1 */
7730 case 8: /* TLSv1.1 */ 7897 case 8: /* TLSv1.1 */
7731 method = (srv)? &TLSv1_1_server_method : &TLSv1_1_client_method; 7898 options = SSL_OP_NO_SSL_MASK & ~SSL_OP_NO_TLSv1_1;
7732 break; 7899 break;
7733#endif 7900#endif
7734#if defined SSL_OP_NO_TLSv1_2 7901#if defined SSL_OP_NO_TLSv1_2
7735 case 9: /* TLSv1_2 */ 7902 case 9: /* TLSv1_2 */
7736 case 10: /* TLSv1.2 */ 7903 case 10: /* TLSv1.2 */
7737 method = (srv)? &TLSv1_2_server_method : &TLSv1_2_client_method; 7904 options = SSL_OP_NO_SSL_MASK & ~SSL_OP_NO_TLSv1_2;
7738 break; 7905 break;
7739#endif 7906#endif
7740#if HAVE_DTLS_CLIENT_METHOD 7907#if HAVE_DTLS_CLIENT_METHOD
7741 case 11: /* DTLS */ 7908 case 11: /* DTLS */
7742 method = (srv)? &DTLS_server_method : &DTLS_client_method;
7743 break; 7909 break;
7744#endif 7910#ifdef SSL_OP_NO_DTLSv1
7745#if HAVE_DTLSV1_CLIENT_METHOD
7746 case 12: /* DTLSv1 */ 7911 case 12: /* DTLSv1 */
7747 case 13: /* DTLSv1.0 */ 7912 case 13: /* DTLSv1.0 */
7748 method = (srv)? &DTLSv1_server_method : &DTLSv1_client_method; 7913 options = SSL_OP_NO_DTLS_MASK & ~SSL_OP_NO_DTLSv1;
7749 break; 7914 break;
7750#endif 7915#endif
7751#if HAVE_DTLSV1_2_CLIENT_METHOD 7916#ifdef SSL_OP_NO_DTLSv1_2
7752 case 14: /* DTLSv1_2 */ 7917 case 14: /* DTLSv1_2 */
7753 case 15: /* DTLSv1.2 */ 7918 case 15: /* DTLSv1.2 */
7754 method = (srv)? &DTLSv1_server_method : &DTLSv1_client_method; 7919 options = SSL_OP_NO_DTLS_MASK & ~SSL_OP_NO_DTLSv1_2;
7755 break; 7920 break;
7756#endif 7921#endif
7922#endif
7757 default: 7923 default:
7758 return luaL_argerror(L, 1, "invalid option"); 7924 return luaL_argerror(L, 1, "invalid option");
7759 } 7925 }
7760 7926
7761 ud = prepsimple(L, SSL_CTX_CLASS); 7927 ud = prepsimple(L, SSL_CTX_CLASS);
7762 7928
7763 if (!(*ud = SSL_CTX_new(method()))) 7929 switch (method_enum) {
7930 case 0: /* SSL */
7931 case 1: /* TLS */
7932 case 2: /* SSLv2 */
7933 case 3: /* SSLv3 */
7934 case 4: /* SSLv23 */
7935 case 5: /* TLSv1 */
7936 case 6: /* TLSv1.0 */
7937 case 7: /* TLSv1_1 */
7938 case 8: /* TLSv1.1 */
7939 case 9: /* TLSv1_2 */
7940 case 10: /* TLSv1.2 */
7941 *ud = SSL_CTX_new(srv?SSLv23_server_method():SSLv23_client_method());
7942 break;
7943#if HAVE_DTLS_CLIENT_METHOD
7944 case 11: /* DTLS */
7945 case 12: /* DTLSv1 */
7946 case 13: /* DTLSv1.0 */
7947 case 14: /* DTLSv1_2 */
7948 case 15: /* DTLSv1.2 */
7949 *ud = SSL_CTX_new(srv?DTLS_server_method():DTLS_client_method());
7950 break;
7951#endif
7952 default:
7953 NOTREACHED;
7954 }
7955
7956 if (!*ud)
7764 return auxL_error(L, auxL_EOPENSSL, "ssl.context.new"); 7957 return auxL_error(L, auxL_EOPENSSL, "ssl.context.new");
7765 7958
7766 SSL_CTX_set_options(*ud, options); 7959 SSL_CTX_set_options(*ud, options);
7767 7960
7961#if HAVE_SSL_CTX_SET_ECDH_AUTO
7962 /* OpenSSL 1.0.2 introduced SSL_CTX_set_ecdh_auto to automatically select
7963 * from the curves set via SSL_CTX_set1_curves_list. However as of OpenSSL
7964 * 1.1.0, the functionality was turned on permanently and the option
7965 * removed. */
7966 if (!SSL_CTX_set_ecdh_auto(*ud, 1))
7967 return auxL_error(L, auxL_EOPENSSL, "ssl.context.new");
7968#endif
7969
7768 return 1; 7970 return 1;
7769} /* sx_new() */ 7971} /* sx_new() */
7770 7972
@@ -7940,6 +8142,21 @@ static int sx_setCipherList(lua_State *L) {
7940} /* sx_setCipherList() */ 8142} /* sx_setCipherList() */
7941 8143
7942 8144
8145#if HAVE_SSL_CTX_SET_CURVES_LIST
8146static int sx_setCurvesList(lua_State *L) {
8147 SSL_CTX *ctx = checksimple(L, 1, SSL_CTX_CLASS);
8148 const char *curves = luaL_checkstring(L, 2);
8149
8150 if (!SSL_CTX_set1_curves_list(ctx, curves))
8151 return auxL_error(L, auxL_EOPENSSL, "ssl.context:setCurvesList");
8152
8153 lua_pushboolean(L, 1);
8154
8155 return 1;
8156} /* sx_setCurvesList() */
8157#endif
8158
8159
7943static int sx_setEphemeralKey(lua_State *L) { 8160static int sx_setEphemeralKey(lua_State *L) {
7944 SSL_CTX *ctx = checksimple(L, 1, SSL_CTX_CLASS); 8161 SSL_CTX *ctx = checksimple(L, 1, SSL_CTX_CLASS);
7945 EVP_PKEY *key = checksimple(L, 2, PKEY_CLASS); 8162 EVP_PKEY *key = checksimple(L, 2, PKEY_CLASS);
@@ -8013,9 +8230,8 @@ static int sx_setAlpnProtos(lua_State *L) {
8013} /* sx_setAlpnProtos() */ 8230} /* sx_setAlpnProtos() */
8014#endif 8231#endif
8015 8232
8016#if HAVE_SSL_CTX_SET_ALPN_SELECT_CB
8017static SSL *ssl_push(lua_State *, SSL *);
8018 8233
8234#if HAVE_SSL_CTX_SET_ALPN_SELECT_CB
8019static int sx_setAlpnSelect_cb(SSL *ssl, const unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *_ctx) { 8235static int sx_setAlpnSelect_cb(SSL *ssl, const unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *_ctx) {
8020 SSL_CTX *ctx = _ctx; 8236 SSL_CTX *ctx = _ctx;
8021 lua_State *L = NULL; 8237 lua_State *L = NULL;
@@ -8033,12 +8249,12 @@ static int sx_setAlpnSelect_cb(SSL *ssl, const unsigned char **out, unsigned cha
8033 8249
8034 otop = lua_gettop(L) - n; 8250 otop = lua_gettop(L) - n;
8035 8251
8036 /* TODO: Install temporary panic handler to catch OOM errors */
8037
8038 /* pass SSL object as 1st argument */ 8252 /* pass SSL object as 1st argument */
8039 ssl_push(L, ssl); 8253 if (ssl_pushsafe(L, ssl))
8254 goto fatal;
8040 lua_insert(L, otop + 3); 8255 lua_insert(L, otop + 3);
8041 8256
8257 /* TODO: Install temporary panic handler to catch OOM errors */
8042 /* pass table of protocol names as 2nd argument */ 8258 /* pass table of protocol names as 2nd argument */
8043 pushprotos(L, in, inlen); 8259 pushprotos(L, in, inlen);
8044 lua_insert(L, otop + 4); 8260 lua_insert(L, otop + 4);
@@ -8110,6 +8326,74 @@ static int sx_setAlpnSelect(lua_State *L) {
8110#endif 8326#endif
8111 8327
8112 8328
8329#if HAVE_SSL_CTX_SET_TLSEXT_SERVERNAME_CALLBACK
8330static int sx_setHostNameCallback_cb(SSL *ssl, int *ad, void *_ctx) {
8331 SSL_CTX *ctx = _ctx;
8332 lua_State *L = NULL;
8333 size_t n;
8334 int otop, status, ret = SSL_TLSEXT_ERR_ALERT_FATAL;
8335
8336 *ad = SSL_AD_INTERNAL_ERROR;
8337
8338 /* expect at least one value: closure */
8339 if ((n = ex_getdata(&L, EX_SSL_CTX_TLSEXT_SERVERNAME_CB, ctx)) < 1)
8340 return SSL_TLSEXT_ERR_ALERT_FATAL;
8341
8342 otop = lua_gettop(L) - n;
8343
8344 /* pass SSL object as 1st argument */
8345 if (ssl_pushsafe(L, ssl))
8346 goto done;
8347
8348 lua_insert(L, otop + 2);
8349
8350 if (LUA_OK != (status = lua_pcall(L, 1 + (n - 1), 2, 0)))
8351 goto done;
8352
8353 /* callback should return a boolean for OK/NOACK
8354 * or nil + an integer for a controlled error
8355 * everything else will be a fatal internal error
8356 */
8357 if (lua_isboolean(L, -2)) {
8358 ret = lua_toboolean(L, -2) ? SSL_TLSEXT_ERR_OK : SSL_TLSEXT_ERR_NOACK;
8359 } else {
8360 ret = SSL_TLSEXT_ERR_ALERT_FATAL;
8361 if (lua_isnil(L, -2) && lua_isinteger(L, -1))
8362 *ad = lua_tointeger(L, -1);
8363 }
8364
8365done:
8366 lua_settop(L, otop);
8367
8368 return ret;
8369} /* sx_setHostNameCallback_cb() */
8370
8371
8372static int sx_setHostNameCallback(lua_State *L) {
8373 SSL_CTX *ctx = checksimple(L, 1, SSL_CTX_CLASS);
8374 int error;
8375
8376 luaL_checktype(L, 2, LUA_TFUNCTION);
8377
8378 if ((error = ex_setdata(L, EX_SSL_CTX_TLSEXT_SERVERNAME_CB, ctx, lua_gettop(L) - 1))) {
8379 if (error > 0) {
8380 return luaL_error(L, "unable to set hostname selection callback: %s", aux_strerror(error));
8381 } else if (error == auxL_EOPENSSL && !ERR_peek_error()) {
8382 return luaL_error(L, "unable to set hostname selection callback: Unknown internal error");
8383 } else {
8384 return auxL_error(L, error, "ssl.context:setHostNameCallback");
8385 }
8386 }
8387 SSL_CTX_set_tlsext_servername_callback(ctx, sx_setHostNameCallback_cb);
8388 SSL_CTX_set_tlsext_servername_arg(ctx, ctx);
8389
8390 lua_pushboolean(L, 1);
8391
8392 return 1;
8393} /* sx_setHostNameCallback() */
8394#endif
8395
8396
8113int TLSEXT_STATUSTYPEs[] = { TLSEXT_STATUSTYPE_ocsp }; 8397int TLSEXT_STATUSTYPEs[] = { TLSEXT_STATUSTYPE_ocsp };
8114const char *TLSEXT_STATUSTYPEs_names[] = { "ocsp", NULL }; 8398const char *TLSEXT_STATUSTYPEs_names[] = { "ocsp", NULL };
8115#define checkTLSEXT_STATUSTYPE(L, idx) \ 8399#define checkTLSEXT_STATUSTYPE(L, idx) \
@@ -8122,7 +8406,7 @@ static int sx_setTLSextStatusType(lua_State *L) {
8122 int type = checkTLSEXT_STATUSTYPE(L, 2); 8406 int type = checkTLSEXT_STATUSTYPE(L, 2);
8123 8407
8124 if(!SSL_CTX_set_tlsext_status_type(ctx, type)) 8408 if(!SSL_CTX_set_tlsext_status_type(ctx, type))
8125 return auxL_error(L, auxL_EOPENSSL, "ssl:setTLSextStatusType"); 8409 return auxL_error(L, auxL_EOPENSSL, "ssl.context:setTLSextStatusType");
8126 8410
8127 lua_pushboolean(L, 1); 8411 lua_pushboolean(L, 1);
8128 8412
@@ -8177,6 +8461,9 @@ static const auxL_Reg sx_methods[] = {
8177 { "setCertificate", &sx_setCertificate }, 8461 { "setCertificate", &sx_setCertificate },
8178 { "setPrivateKey", &sx_setPrivateKey }, 8462 { "setPrivateKey", &sx_setPrivateKey },
8179 { "setCipherList", &sx_setCipherList }, 8463 { "setCipherList", &sx_setCipherList },
8464#if HAVE_SSL_CTX_SET_CURVES_LIST
8465 { "setCurvesList", &sx_setCurvesList },
8466#endif
8180 { "setEphemeralKey", &sx_setEphemeralKey }, 8467 { "setEphemeralKey", &sx_setEphemeralKey },
8181#if HAVE_SSL_CTX_SET_ALPN_PROTOS 8468#if HAVE_SSL_CTX_SET_ALPN_PROTOS
8182 { "setAlpnProtos", &sx_setAlpnProtos }, 8469 { "setAlpnProtos", &sx_setAlpnProtos },
@@ -8184,6 +8471,9 @@ static const auxL_Reg sx_methods[] = {
8184#if HAVE_SSL_CTX_SET_ALPN_SELECT_CB 8471#if HAVE_SSL_CTX_SET_ALPN_SELECT_CB
8185 { "setAlpnSelect", &sx_setAlpnSelect }, 8472 { "setAlpnSelect", &sx_setAlpnSelect },
8186#endif 8473#endif
8474#if HAVE_SSL_CTX_SET_TLSEXT_SERVERNAME_CALLBACK
8475 { "setHostNameCallback", &sx_setHostNameCallback },
8476#endif
8187#if HAVE_SSL_CTX_SET_TLSEXT_STATUS_TYPE 8477#if HAVE_SSL_CTX_SET_TLSEXT_STATUS_TYPE
8188 { "setTLSextStatusType", &sx_setTLSextStatusType }, 8478 { "setTLSextStatusType", &sx_setTLSextStatusType },
8189#endif 8479#endif
@@ -8374,6 +8664,33 @@ static int ssl_getParam(lua_State *L) {
8374} /* ssl_getParam() */ 8664} /* ssl_getParam() */
8375 8665
8376 8666
8667static int ssl_setVerify(lua_State *L) {
8668 SSL *ssl = checksimple(L, 1, SSL_CLASS);
8669 int mode = luaL_optinteger(L, 2, -1);
8670 int depth = luaL_optinteger(L, 3, -1);
8671
8672 if (mode != -1)
8673 SSL_set_verify(ssl, mode, 0);
8674
8675 if (depth != -1)
8676 SSL_set_verify_depth(ssl, depth);
8677
8678 lua_pushboolean(L, 1);
8679
8680 return 1;
8681} /* ssl_setVerify() */
8682
8683
8684static int ssl_getVerify(lua_State *L) {
8685 SSL *ssl = checksimple(L, 1, SSL_CLASS);
8686
8687 lua_pushinteger(L, SSL_get_verify_mode(ssl));
8688 lua_pushinteger(L, SSL_get_verify_depth(ssl));
8689
8690 return 2;
8691} /* ssl_getVerify() */
8692
8693
8377static int ssl_getVerifyResult(lua_State *L) { 8694static int ssl_getVerifyResult(lua_State *L) {
8378 SSL *ssl = checksimple(L, 1, SSL_CLASS); 8695 SSL *ssl = checksimple(L, 1, SSL_CLASS);
8379 long res = SSL_get_verify_result(ssl); 8696 long res = SSL_get_verify_result(ssl);
@@ -8383,6 +8700,44 @@ static int ssl_getVerifyResult(lua_State *L) {
8383} /* ssl_getVerifyResult() */ 8700} /* ssl_getVerifyResult() */
8384 8701
8385 8702
8703static int ssl_setCertificate(lua_State *L) {
8704 SSL *ssl = checksimple(L, 1, SSL_CLASS);
8705 X509 *crt = X509_dup(checksimple(L, 2, X509_CERT_CLASS));
8706 int ok;
8707
8708 ok = SSL_use_certificate(ssl, crt);
8709 X509_free(crt);
8710
8711 if (!ok)
8712 return auxL_error(L, auxL_EOPENSSL, "ssl:setCertificate");
8713
8714 lua_pushboolean(L, 1);
8715
8716 return 1;
8717} /* ssl_setCertificate() */
8718
8719
8720static int ssl_setPrivateKey(lua_State *L) {
8721 SSL *ssl = checksimple(L, 1, SSL_CLASS);
8722 EVP_PKEY *key = checksimple(L, 2, PKEY_CLASS);
8723 /*
8724 * NOTE: No easy way to dup the key, but a shared reference should
8725 * be okay as keys are less mutable than certificates.
8726 *
8727 * FIXME: SSL_use_PrivateKey will return true even if the
8728 * EVP_PKEY object has no private key. Instead, we'll just get a
8729 * segfault during the SSL handshake. We need to check that a
8730 * private key is actually defined in the object.
8731 */
8732 if (!SSL_use_PrivateKey(ssl, key))
8733 return auxL_error(L, auxL_EOPENSSL, "ssl:setPrivateKey");
8734
8735 lua_pushboolean(L, 1);
8736
8737 return 1;
8738} /* ssl_setPrivateKey() */
8739
8740
8386static int ssl_getPeerCertificate(lua_State *L) { 8741static int ssl_getPeerCertificate(lua_State *L) {
8387 SSL *ssl = checksimple(L, 1, SSL_CLASS); 8742 SSL *ssl = checksimple(L, 1, SSL_CLASS);
8388 X509 **x509 = prepsimple(L, X509_CERT_CLASS); 8743 X509 **x509 = prepsimple(L, X509_CERT_CLASS);
@@ -8433,6 +8788,21 @@ static int ssl_getCipherInfo(lua_State *L) {
8433} /* ssl_getCipherInfo() */ 8788} /* ssl_getCipherInfo() */
8434 8789
8435 8790
8791#if HAVE_SSL_SET_CURVES_LIST
8792static int ssl_setCurvesList(lua_State *L) {
8793 SSL *ssl = checksimple(L, 1, SSL_CLASS);
8794 const char *curves = luaL_checkstring(L, 2);
8795
8796 if (!SSL_set1_curves_list(ssl, curves))
8797 return auxL_error(L, auxL_EOPENSSL, "ssl:setCurvesList");
8798
8799 lua_pushboolean(L, 1);
8800
8801 return 1;
8802} /* ssl_setCurvesList() */
8803#endif
8804
8805
8436static int ssl_getHostName(lua_State *L) { 8806static int ssl_getHostName(lua_State *L) {
8437 SSL *ssl = checksimple(L, 1, SSL_CLASS); 8807 SSL *ssl = checksimple(L, 1, SSL_CLASS);
8438 const char *host; 8808 const char *host;
@@ -8679,10 +9049,17 @@ static const auxL_Reg ssl_methods[] = {
8679 { "clearOptions", &ssl_clearOptions }, 9049 { "clearOptions", &ssl_clearOptions },
8680 { "setParam", &ssl_setParam }, 9050 { "setParam", &ssl_setParam },
8681 { "getParam", &ssl_getParam }, 9051 { "getParam", &ssl_getParam },
9052 { "setVerify", &ssl_setVerify },
9053 { "getVerify", &ssl_getVerify },
8682 { "getVerifyResult", &ssl_getVerifyResult }, 9054 { "getVerifyResult", &ssl_getVerifyResult },
9055 { "setCertificate", &ssl_setCertificate },
9056 { "setPrivateKey", &ssl_setPrivateKey },
8683 { "getPeerCertificate", &ssl_getPeerCertificate }, 9057 { "getPeerCertificate", &ssl_getPeerCertificate },
8684 { "getPeerChain", &ssl_getPeerChain }, 9058 { "getPeerChain", &ssl_getPeerChain },
8685 { "getCipherInfo", &ssl_getCipherInfo }, 9059 { "getCipherInfo", &ssl_getCipherInfo },
9060#if HAVE_SSL_SET_CURVES_LIST
9061 { "setCurvesList", &ssl_setCurvesList },
9062#endif
8686 { "getHostName", &ssl_getHostName }, 9063 { "getHostName", &ssl_getHostName },
8687 { "setHostName", &ssl_setHostName }, 9064 { "setHostName", &ssl_setHostName },
8688 { "getVersion", &ssl_getVersion }, 9065 { "getVersion", &ssl_getVersion },
diff --git a/src/openssl.ssl.context.lua b/src/openssl.ssl.context.lua
index 2098b54..3263fb1 100644
--- a/src/openssl.ssl.context.lua
+++ b/src/openssl.ssl.context.lua
@@ -13,4 +13,18 @@ local setCipherList; setCipherList = ctx.interpose("setCipherList", function (se
13 return setCipherList(self, ciphers) 13 return setCipherList(self, ciphers)
14end) 14end)
15 15
16-- Allow passing a vararg of curves, or an array
17local setCurvesList = ctx.interpose("setCurvesList", nil)
18if setCurvesList then
19 ctx.interpose("setCurvesList", function (self, curves, ...)
20 if (...) then
21 local curves_t = pack(curves, ...)
22 curves = table.concat(curves_t, ":", 1, curves_t.n)
23 elseif type(curves) == "table" then
24 curves = table.concat(curves, ":")
25 end
26 return setCurvesList(self, curves)
27 end)
28end
29
16return ctx 30return ctx
diff --git a/src/openssl.ssl.lua b/src/openssl.ssl.lua
index 3c348f6..bf90f29 100644
--- a/src/openssl.ssl.lua
+++ b/src/openssl.ssl.lua
@@ -1,3 +1,19 @@
1local ctx = require"_openssl.ssl" 1local ssl = require"_openssl.ssl"
2 2
3return ctx 3local pack = table.pack or function(...) return { n = select("#", ...); ... } end
4
5-- Allow passing a vararg of curves, or an array
6local setCurvesList = ssl.interpose("setCurvesList", nil)
7if setCurvesList then
8 ssl.interpose("setCurvesList", function (self, curves, ...)
9 if (...) then
10 local curves_t = pack(curves, ...)
11 curves = table.concat(curves_t, ":", 1, curves_t.n)
12 elseif type(curves) == "table" then
13 curves = table.concat(curves, ":")
14 end
15 return setCurvesList(self, curves)
16 end)
17end
18
19return ssl
diff --git a/vendor/compat53/.gitignore b/vendor/compat53/.gitignore
new file mode 100644
index 0000000..67c1b76
--- /dev/null
+++ b/vendor/compat53/.gitignore
@@ -0,0 +1,10 @@
1# generated files
2*.so
3*.dll
4*.o
5*.obj
6HISTO
7
8# vim temporaries
9.*.swp
10
diff --git a/vendor/compat53/LICENSE b/vendor/compat53/LICENSE
new file mode 100644
index 0000000..511db15
--- /dev/null
+++ b/vendor/compat53/LICENSE
@@ -0,0 +1,20 @@
1The MIT License (MIT)
2
3Copyright (c) 2015 Kepler Project.
4
5Permission is hereby granted, free of charge, to any person obtaining a copy of
6this software and associated documentation files (the "Software"), to deal in
7the Software without restriction, including without limitation the rights to
8use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9the Software, and to permit persons to whom the Software is furnished to do so,
10subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in all
13copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/vendor/compat53/README.md b/vendor/compat53/README.md
new file mode 100644
index 0000000..08614a1
--- /dev/null
+++ b/vendor/compat53/README.md
@@ -0,0 +1,229 @@
1# lua-compat-5.3
2
3Lua-5.3-style APIs for Lua 5.2 and 5.1.
4
5## What is it
6
7This is a small module that aims to make it easier to write code
8in a Lua-5.3-style that is compatible with Lua 5.1, Lua 5.2, and Lua
95.3. This does *not* make Lua 5.2 (or even Lua 5.1) entirely
10compatible with Lua 5.3, but it brings the API closer to that of Lua
115.3.
12
13It includes:
14
15* _For writing Lua_: The Lua module `compat53`, which can be require'd
16 from Lua scripts and run in Lua 5.1, 5.2, and 5.3, including a
17 backport of the `utf8` module, the 5.3 `table` module, and the
18 string packing functions straight from the Lua 5.3 sources.
19* _For writing C_: A C header and file which can be linked to your
20 Lua module written in C, providing some functions from the C API
21 of Lua 5.3 that do not exist in Lua 5.2 or 5.1, making it easier to
22 write C code that compiles with all three versions of liblua.
23
24## How to use it
25
26### Lua module
27
28```lua
29require("compat53")
30```
31
32`compat53` makes changes to your global environment and does not return
33a meaningful return value, so the usual idiom of storing the return of
34`require` in a local variable makes no sense.
35
36When run under Lua 5.3, this module does nothing.
37
38When run under Lua 5.2 or 5.1, it replaces some of your standard
39functions and adds new ones to bring your environment closer to that
40of Lua 5.3. It also tries to load the backported `utf8`, `table`, and
41string packing modules automatically. If unsuccessful, pure Lua
42versions of the new `table` functions are used as a fallback, and
43[Roberto's struct library][1] is tried for string packing.
44
45#### Lua submodules
46
47```lua
48local _ENV = require("compat53.module")
49if setfenv then setfenv(1, _ENV) end
50```
51
52The `compat53.module` module does not modify the global environment,
53and so it is safe to use in modules without affecting other Lua files.
54It is supposed to be set as the current environment (see above), i.e.
55cherry picking individual functions from this module is expressly
56*not* supported!). Not all features are available when using this
57module (e.g. yieldable (x)pcall support, string/file methods, etc.),
58so it is recommended to use plain `require("compat53")` whenever
59possible.
60
61### C code
62
63There are two ways of adding the C API compatibility functions/macros to
64your project:
65* If `COMPAT53_PREFIX` is *not* `#define`d, `compat-5.3.h` `#include`s
66 `compat-5.3.c`, and all functions are made `static`. You don't have to
67 compile/link/add `compat-5.3.c` yourself. This is useful for one-file
68 projects.
69* If `COMPAT53_PREFIX` is `#define`d, all exported functions are renamed
70 behind the scenes using this prefix to avoid linker conflicts with other
71 code using this package. This doesn't change the way you call the
72 compatibility functions in your code. You have to compile and link
73 `compat-5.3.c` to your project yourself. You can change the way the
74 functions are exported using the `COMPAT53_API` macro (e.g. if you need
75 some `__declspec` magic). While it is technically possible to use
76 the "lua" prefix (and it looks better in the debugger), this is
77 discouraged because LuaJIT has started to implement its own Lua 5.2+
78 C API functions, and with the "lua" prefix you'd violate the
79 one-definition rule with recent LuaJIT versions.
80
81## What's implemented
82
83### Lua
84
85* the `utf8` module backported from the Lua 5.3 sources
86* `string.pack`, `string.packsize`, and `string.unpack` from the Lua
87 5.3 sources or from the `struct` module. (`struct` is not 100%
88 compatible to Lua 5.3's string packing!) (See [here][4])
89* `math.maxinteger` and `math.mininteger`, `math.tointeger`, `math.type`,
90 and `math.ult` (see [here][5])
91* `assert` accepts non-string error messages
92* `ipairs` respects `__index` metamethod
93* `table.move`
94* `table` library respects metamethods
95
96For Lua 5.1 additionally:
97* `load` and `loadfile` accept `mode` and `env` parameters
98* `table.pack` and `table.unpack`
99* string patterns may contain embedded zeros (but see [here][6])
100* `string.rep` accepts `sep` argument
101* `string.format` calls `tostring` on arguments for `%s`
102* `math.log` accepts base argument
103* `xpcall` takes additional arguments
104* `pcall` and `xpcall` can execute functions that yield (see
105 [here][22] for a possible problem with `coroutine.running`)
106* `pairs` respects `__pairs` metamethod (see [here][7])
107* `rawlen` (but `#` still doesn't respect `__len` for tables)
108* `package.searchers` as alias for `package.loaders`
109* `package.searchpath` (see [here][8])
110* `coroutine` functions dealing with the main coroutine (see
111 [here][22] for a possible problem with `coroutine.running`)
112* `coroutine.create` accepts functions written in C
113* return code of `os.execute` (see [here][9])
114* `io.write` and `file:write` return file handle
115* `io.lines` and `file:lines` accept format arguments (like `io.read`)
116 (see [here][10] and [here][11])
117* `debug.setmetatable` returns object
118* `debug.getuservalue` (see [here][12])
119* `debug.setuservalue` (see [here][13])
120
121### C
122
123* `lua_KContext` (see [here][14])
124* `lua_KFunction` (see [here][14])
125* `lua_dump` (extra `strip` parameter, ignored, see [here][15])
126* `lua_getfield` (return value)
127* `lua_geti` and `lua_seti`
128* `lua_getglobal` (return value)
129* `lua_getmetafield` (return value)
130* `lua_gettable` (return value)
131* `lua_getuservalue` (limited compatibility, see [here][16])
132* `lua_setuservalue` (limited compatibility, see [here][17])
133* `lua_isinteger`
134* `lua_numbertointeger`
135* `lua_callk` and `lua_pcallk` (limited compatibility, see [here][14])
136* `lua_rawget` and `lua_rawgeti` (return values)
137* `lua_rawgetp` and `lua_rawsetp`
138* `luaL_requiref` (now checks `package.loaded` first)
139* `lua_rotate`
140* `lua_stringtonumber` (see [here][18])
141
142For Lua 5.1 additionally:
143* `LUA_OK`
144* `LUA_OP*` macros for `lua_arith` and `lua_compare`
145* `lua_Unsigned`
146* `lua_absindex`
147* `lua_arith` (see [here][19])
148* `lua_compare`
149* `lua_len`, `lua_rawlen`, and `luaL_len`
150* `lua_pushstring`, `lua_pushlstring` (return value)
151* `lua_copy`
152* `lua_pushglobaltable`
153* `luaL_testudata`
154* `luaL_setfuncs`, `luaL_newlibtable`, and `luaL_newlib`
155* `luaL_setmetatable`
156* `luaL_getsubtable`
157* `luaL_traceback`
158* `luaL_execresult`
159* `luaL_fileresult`
160* `luaL_checkversion` (with empty body, only to avoid compile errors,
161 see [here][20])
162* `luaL_tolstring`
163* `luaL_buffinitsize`, `luaL_prepbuffsize`, and `luaL_pushresultsize`
164 (see [here][21])
165* `lua_pushunsigned`, `lua_tounsignedx`, `lua_tounsigned`,
166 `luaL_checkunsigned`, `luaL_optunsigned`, if
167 `LUA_COMPAT_APIINTCASTS` is defined.
168
169## What's not implemented
170
171* bit operators
172* integer division operator
173* utf8 escape sequences
174* 64 bit integers
175* `coroutine.isyieldable`
176* Lua 5.1: `_ENV`, `goto`, labels, ephemeron tables, etc. See
177 [`lua-compat-5.2`][2] for a detailed list.
178* the following C API functions/macros:
179 * `lua_isyieldable`
180 * `lua_getextraspace`
181 * `lua_arith` (new operators missing)
182 * `lua_push(v)fstring` (new formats missing)
183 * `lua_upvalueid` (5.1)
184 * `lua_upvaluejoin` (5.1)
185 * `lua_version` (5.1)
186 * `lua_yieldk` (5.1)
187 * `luaL_loadbufferx` (5.1)
188 * `luaL_loadfilex` (5.1)
189
190## See also
191
192* For Lua-5.2-style APIs under Lua 5.1, see [lua-compat-5.2][2],
193 which also is the basis for most of the code in this project.
194* For Lua-5.1-style APIs under Lua 5.0, see [Compat-5.1][3]
195
196## Credits
197
198This package contains code written by:
199
200* [The Lua Team](http://www.lua.org)
201* Philipp Janda ([@siffiejoe](http://github.com/siffiejoe))
202* Tomás Guisasola Gorham ([@tomasguisasola](http://github.com/tomasguisasola))
203* Hisham Muhammad ([@hishamhm](http://github.com/hishamhm))
204* Renato Maia ([@renatomaia](http://github.com/renatomaia))
205
206
207 [1]: http://www.inf.puc-rio.br/~roberto/struct/
208 [2]: http://github.com/keplerproject/lua-compat-5.2/
209 [3]: http://keplerproject.org/compat/
210 [4]: https://github.com/keplerproject/lua-compat-5.3/wiki/string_packing
211 [5]: https://github.com/keplerproject/lua-compat-5.3/wiki/math.type
212 [6]: https://github.com/keplerproject/lua-compat-5.3/wiki/pattern_matching
213 [7]: https://github.com/keplerproject/lua-compat-5.3/wiki/pairs
214 [8]: https://github.com/keplerproject/lua-compat-5.3/wiki/package.searchpath
215 [9]: https://github.com/keplerproject/lua-compat-5.3/wiki/os.execute
216 [10]: https://github.com/keplerproject/lua-compat-5.3/wiki/io.lines
217 [11]: https://github.com/keplerproject/lua-compat-5.3/wiki/file.lines
218 [12]: https://github.com/keplerproject/lua-compat-5.3/wiki/debug.getuservalue
219 [13]: https://github.com/keplerproject/lua-compat-5.3/wiki/debug.setuservalue
220 [14]: https://github.com/keplerproject/lua-compat-5.3/wiki/yieldable_c_functions
221 [15]: https://github.com/keplerproject/lua-compat-5.3/wiki/lua_dump
222 [16]: https://github.com/keplerproject/lua-compat-5.3/wiki/lua_getuservalue
223 [17]: https://github.com/keplerproject/lua-compat-5.3/wiki/lua_setuservalue
224 [18]: https://github.com/keplerproject/lua-compat-5.3/wiki/lua_stringtonumber
225 [19]: https://github.com/keplerproject/lua-compat-5.3/wiki/lua_arith
226 [20]: https://github.com/keplerproject/lua-compat-5.3/wiki/luaL_checkversion
227 [21]: https://github.com/keplerproject/lua-compat-5.3/wiki/luaL_Buffer
228 [22]: https://github.com/keplerproject/lua-compat-5.3/wiki/coroutine.running
229
diff --git a/vendor/compat53/c-api/compat-5.3.c b/vendor/compat53/c-api/compat-5.3.c
new file mode 100644
index 0000000..883efb8
--- /dev/null
+++ b/vendor/compat53/c-api/compat-5.3.c
@@ -0,0 +1,617 @@
1#include <stddef.h>
2#include <stdlib.h>
3#include <string.h>
4#include <ctype.h>
5#include <errno.h>
6#include "compat-5.3.h"
7
8/* don't compile it again if it already is included via compat53.h */
9#ifndef COMPAT53_C_
10#define COMPAT53_C_
11
12
13
14/* definitions for Lua 5.1 only */
15#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501
16
17
18COMPAT53_API int lua_absindex (lua_State *L, int i) {
19 if (i < 0 && i > LUA_REGISTRYINDEX)
20 i += lua_gettop(L) + 1;
21 return i;
22}
23
24
25static void compat53_call_lua (lua_State *L, char const code[], size_t len,
26 int nargs, int nret) {
27 lua_rawgetp(L, LUA_REGISTRYINDEX, (void*)code);
28 if (lua_type(L, -1) != LUA_TFUNCTION) {
29 lua_pop(L, 1);
30 if (luaL_loadbuffer(L, code, len, "=none"))
31 lua_error(L);
32 lua_pushvalue(L, -1);
33 lua_rawsetp(L, LUA_REGISTRYINDEX, (void*)code);
34 }
35 lua_insert(L, -nargs-1);
36 lua_call(L, nargs, nret);
37}
38
39
40static const char compat53_arith_code[] =
41 "local op,a,b=...\n"
42 "if op==0 then return a+b\n"
43 "elseif op==1 then return a-b\n"
44 "elseif op==2 then return a*b\n"
45 "elseif op==3 then return a/b\n"
46 "elseif op==4 then return a%b\n"
47 "elseif op==5 then return a^b\n"
48 "elseif op==6 then return -a\n"
49 "end\n";
50
51COMPAT53_API void lua_arith (lua_State *L, int op) {
52 if (op < LUA_OPADD || op > LUA_OPUNM)
53 luaL_error(L, "invalid 'op' argument for lua_arith");
54 luaL_checkstack(L, 5, "not enough stack slots");
55 if (op == LUA_OPUNM)
56 lua_pushvalue(L, -1);
57 lua_pushnumber(L, op);
58 lua_insert(L, -3);
59 compat53_call_lua(L, compat53_arith_code,
60 sizeof(compat53_arith_code)-1, 3, 1);
61}
62
63
64static const char compat53_compare_code[] =
65 "local a,b=...\n"
66 "return a<=b\n";
67
68COMPAT53_API int lua_compare (lua_State *L, int idx1, int idx2, int op) {
69 int result = 0;
70 switch (op) {
71 case LUA_OPEQ:
72 return lua_equal(L, idx1, idx2);
73 case LUA_OPLT:
74 return lua_lessthan(L, idx1, idx2);
75 case LUA_OPLE:
76 luaL_checkstack(L, 5, "not enough stack slots");
77 idx1 = lua_absindex(L, idx1);
78 idx2 = lua_absindex(L, idx2);
79 lua_pushvalue(L, idx1);
80 lua_pushvalue(L, idx2);
81 compat53_call_lua(L, compat53_compare_code,
82 sizeof(compat53_compare_code)-1, 2, 1);
83 result = lua_toboolean(L, -1);
84 lua_pop(L, 1);
85 return result;
86 default:
87 luaL_error(L, "invalid 'op' argument for lua_compare");
88 }
89 return 0;
90}
91
92
93COMPAT53_API void lua_copy (lua_State *L, int from, int to) {
94 int abs_to = lua_absindex(L, to);
95 luaL_checkstack(L, 1, "not enough stack slots");
96 lua_pushvalue(L, from);
97 lua_replace(L, abs_to);
98}
99
100
101COMPAT53_API void lua_len (lua_State *L, int i) {
102 switch (lua_type(L, i)) {
103 case LUA_TSTRING:
104 lua_pushnumber(L, (lua_Integer)lua_objlen(L, i));
105 break;
106 case LUA_TTABLE:
107 if (!luaL_callmeta(L, i, "__len"))
108 lua_pushnumber(L, (lua_Integer)lua_objlen(L, i));
109 break;
110 case LUA_TUSERDATA:
111 if (luaL_callmeta(L, i, "__len"))
112 break;
113 /* maybe fall through */
114 default:
115 luaL_error(L, "attempt to get length of a %s value",
116 lua_typename(L, lua_type(L, i)));
117 }
118}
119
120
121COMPAT53_API int lua_rawgetp (lua_State *L, int i, const void *p) {
122 int abs_i = lua_absindex(L, i);
123 lua_pushlightuserdata(L, (void*)p);
124 lua_rawget(L, abs_i);
125 return lua_type(L, -1);
126}
127
128COMPAT53_API void lua_rawsetp (lua_State *L, int i, const void *p) {
129 int abs_i = lua_absindex(L, i);
130 luaL_checkstack(L, 1, "not enough stack slots");
131 lua_pushlightuserdata(L, (void*)p);
132 lua_insert(L, -2);
133 lua_rawset(L, abs_i);
134}
135
136
137COMPAT53_API lua_Integer lua_tointegerx (lua_State *L, int i, int *isnum) {
138 lua_Integer n = lua_tointeger(L, i);
139 if (isnum != NULL) {
140 *isnum = (n != 0 || lua_isnumber(L, i));
141 }
142 return n;
143}
144
145
146COMPAT53_API lua_Number lua_tonumberx (lua_State *L, int i, int *isnum) {
147 lua_Number n = lua_tonumber(L, i);
148 if (isnum != NULL) {
149 *isnum = (n != 0 || lua_isnumber(L, i));
150 }
151 return n;
152}
153
154
155COMPAT53_API void luaL_checkversion (lua_State *L) {
156 (void)L;
157}
158
159
160COMPAT53_API void luaL_checkstack (lua_State *L, int sp, const char *msg) {
161 if (!lua_checkstack(L, sp+LUA_MINSTACK)) {
162 if (msg != NULL)
163 luaL_error(L, "stack overflow (%s)", msg);
164 else {
165 lua_pushliteral(L, "stack overflow");
166 lua_error(L);
167 }
168 }
169}
170
171
172COMPAT53_API int luaL_getsubtable (lua_State *L, int i, const char *name) {
173 int abs_i = lua_absindex(L, i);
174 luaL_checkstack(L, 3, "not enough stack slots");
175 lua_pushstring(L, name);
176 lua_gettable(L, abs_i);
177 if (lua_istable(L, -1))
178 return 1;
179 lua_pop(L, 1);
180 lua_newtable(L);
181 lua_pushstring(L, name);
182 lua_pushvalue(L, -2);
183 lua_settable(L, abs_i);
184 return 0;
185}
186
187
188COMPAT53_API lua_Integer luaL_len (lua_State *L, int i) {
189 lua_Integer res = 0;
190 int isnum = 0;
191 luaL_checkstack(L, 1, "not enough stack slots");
192 lua_len(L, i);
193 res = lua_tointegerx(L, -1, &isnum);
194 lua_pop(L, 1);
195 if (!isnum)
196 luaL_error(L, "object length is not an integer");
197 return res;
198}
199
200
201COMPAT53_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) {
202 luaL_checkstack(L, nup+1, "too many upvalues");
203 for (; l->name != NULL; l++) { /* fill the table with given functions */
204 int i;
205 lua_pushstring(L, l->name);
206 for (i = 0; i < nup; i++) /* copy upvalues to the top */
207 lua_pushvalue(L, -(nup + 1));
208 lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */
209 lua_settable(L, -(nup + 3)); /* table must be below the upvalues, the name and the closure */
210 }
211 lua_pop(L, nup); /* remove upvalues */
212}
213
214
215COMPAT53_API void luaL_setmetatable (lua_State *L, const char *tname) {
216 luaL_checkstack(L, 1, "not enough stack slots");
217 luaL_getmetatable(L, tname);
218 lua_setmetatable(L, -2);
219}
220
221
222COMPAT53_API void *luaL_testudata (lua_State *L, int i, const char *tname) {
223 void *p = lua_touserdata(L, i);
224 luaL_checkstack(L, 2, "not enough stack slots");
225 if (p == NULL || !lua_getmetatable(L, i))
226 return NULL;
227 else {
228 int res = 0;
229 luaL_getmetatable(L, tname);
230 res = lua_rawequal(L, -1, -2);
231 lua_pop(L, 2);
232 if (!res)
233 p = NULL;
234 }
235 return p;
236}
237
238
239static int compat53_countlevels (lua_State *L) {
240 lua_Debug ar;
241 int li = 1, le = 1;
242 /* find an upper bound */
243 while (lua_getstack(L, le, &ar)) { li = le; le *= 2; }
244 /* do a binary search */
245 while (li < le) {
246 int m = (li + le)/2;
247 if (lua_getstack(L, m, &ar)) li = m + 1;
248 else le = m;
249 }
250 return le - 1;
251}
252
253static int compat53_findfield (lua_State *L, int objidx, int level) {
254 if (level == 0 || !lua_istable(L, -1))
255 return 0; /* not found */
256 lua_pushnil(L); /* start 'next' loop */
257 while (lua_next(L, -2)) { /* for each pair in table */
258 if (lua_type(L, -2) == LUA_TSTRING) { /* ignore non-string keys */
259 if (lua_rawequal(L, objidx, -1)) { /* found object? */
260 lua_pop(L, 1); /* remove value (but keep name) */
261 return 1;
262 }
263 else if (compat53_findfield(L, objidx, level - 1)) { /* try recursively */
264 lua_remove(L, -2); /* remove table (but keep name) */
265 lua_pushliteral(L, ".");
266 lua_insert(L, -2); /* place '.' between the two names */
267 lua_concat(L, 3);
268 return 1;
269 }
270 }
271 lua_pop(L, 1); /* remove value */
272 }
273 return 0; /* not found */
274}
275
276static int compat53_pushglobalfuncname (lua_State *L, lua_Debug *ar) {
277 int top = lua_gettop(L);
278 lua_getinfo(L, "f", ar); /* push function */
279 lua_pushvalue(L, LUA_GLOBALSINDEX);
280 if (compat53_findfield(L, top + 1, 2)) {
281 lua_copy(L, -1, top + 1); /* move name to proper place */
282 lua_pop(L, 2); /* remove pushed values */
283 return 1;
284 }
285 else {
286 lua_settop(L, top); /* remove function and global table */
287 return 0;
288 }
289}
290
291static void compat53_pushfuncname (lua_State *L, lua_Debug *ar) {
292 if (*ar->namewhat != '\0') /* is there a name? */
293 lua_pushfstring(L, "function " LUA_QS, ar->name);
294 else if (*ar->what == 'm') /* main? */
295 lua_pushliteral(L, "main chunk");
296 else if (*ar->what == 'C') {
297 if (compat53_pushglobalfuncname(L, ar)) {
298 lua_pushfstring(L, "function " LUA_QS, lua_tostring(L, -1));
299 lua_remove(L, -2); /* remove name */
300 }
301 else
302 lua_pushliteral(L, "?");
303 }
304 else
305 lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined);
306}
307
308#define COMPAT53_LEVELS1 12 /* size of the first part of the stack */
309#define COMPAT53_LEVELS2 10 /* size of the second part of the stack */
310
311COMPAT53_API void luaL_traceback (lua_State *L, lua_State *L1,
312 const char *msg, int level) {
313 lua_Debug ar;
314 int top = lua_gettop(L);
315 int numlevels = compat53_countlevels(L1);
316 int mark = (numlevels > COMPAT53_LEVELS1 + COMPAT53_LEVELS2) ? COMPAT53_LEVELS1 : 0;
317 if (msg) lua_pushfstring(L, "%s\n", msg);
318 lua_pushliteral(L, "stack traceback:");
319 while (lua_getstack(L1, level++, &ar)) {
320 if (level == mark) { /* too many levels? */
321 lua_pushliteral(L, "\n\t..."); /* add a '...' */
322 level = numlevels - COMPAT53_LEVELS2; /* and skip to last ones */
323 }
324 else {
325 lua_getinfo(L1, "Slnt", &ar);
326 lua_pushfstring(L, "\n\t%s:", ar.short_src);
327 if (ar.currentline > 0)
328 lua_pushfstring(L, "%d:", ar.currentline);
329 lua_pushliteral(L, " in ");
330 compat53_pushfuncname(L, &ar);
331 lua_concat(L, lua_gettop(L) - top);
332 }
333 }
334 lua_concat(L, lua_gettop(L) - top);
335}
336
337
338COMPAT53_API int luaL_fileresult (lua_State *L, int stat, const char *fname) {
339 int en = errno; /* calls to Lua API may change this value */
340 if (stat) {
341 lua_pushboolean(L, 1);
342 return 1;
343 }
344 else {
345 lua_pushnil(L);
346 if (fname)
347 lua_pushfstring(L, "%s: %s", fname, strerror(en));
348 else
349 lua_pushstring(L, strerror(en));
350 lua_pushnumber(L, (lua_Number)en);
351 return 3;
352 }
353}
354
355
356#if !defined(l_inspectstat) && \
357 (defined(unix) || defined(__unix) || defined(__unix__) || \
358 defined(__TOS_AIX__) || defined(_SYSTYPE_BSD) || \
359 (defined(__APPLE__) && defined(__MACH__)))
360/* some form of unix; check feature macros in unistd.h for details */
361# include <unistd.h>
362/* check posix version; the relevant include files and macros probably
363 * were available before 2001, but I'm not sure */
364# if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L
365# include <sys/wait.h>
366# define l_inspectstat(stat,what) \
367 if (WIFEXITED(stat)) { stat = WEXITSTATUS(stat); } \
368 else if (WIFSIGNALED(stat)) { stat = WTERMSIG(stat); what = "signal"; }
369# endif
370#endif
371
372/* provide default (no-op) version */
373#if !defined(l_inspectstat)
374# define l_inspectstat(stat,what) ((void)0)
375#endif
376
377
378COMPAT53_API int luaL_execresult (lua_State *L, int stat) {
379 const char *what = "exit";
380 if (stat == -1)
381 return luaL_fileresult(L, 0, NULL);
382 else {
383 l_inspectstat(stat, what);
384 if (*what == 'e' && stat == 0)
385 lua_pushboolean(L, 1);
386 else
387 lua_pushnil(L);
388 lua_pushstring(L, what);
389 lua_pushinteger(L, stat);
390 return 3;
391 }
392}
393
394
395COMPAT53_API void luaL_buffinit (lua_State *L, luaL_Buffer_53 *B) {
396 /* make it crash if used via pointer to a 5.1-style luaL_Buffer */
397 B->b.p = NULL;
398 B->b.L = NULL;
399 B->b.lvl = 0;
400 /* reuse the buffer from the 5.1-style luaL_Buffer though! */
401 B->ptr = B->b.buffer;
402 B->capacity = LUAL_BUFFERSIZE;
403 B->nelems = 0;
404 B->L2 = L;
405}
406
407
408COMPAT53_API char *luaL_prepbuffsize (luaL_Buffer_53 *B, size_t s) {
409 if (B->capacity - B->nelems < s) { /* needs to grow */
410 char* newptr = NULL;
411 size_t newcap = B->capacity * 2;
412 if (newcap - B->nelems < s)
413 newcap = B->nelems + s;
414 if (newcap < B->capacity) /* overflow */
415 luaL_error(B->L2, "buffer too large");
416 newptr = (char*)lua_newuserdata(B->L2, newcap);
417 memcpy(newptr, B->ptr, B->nelems);
418 if (B->ptr != B->b.buffer)
419 lua_replace(B->L2, -2); /* remove old buffer */
420 B->ptr = newptr;
421 B->capacity = newcap;
422 }
423 return B->ptr+B->nelems;
424}
425
426
427COMPAT53_API void luaL_addlstring (luaL_Buffer_53 *B, const char *s, size_t l) {
428 memcpy(luaL_prepbuffsize(B, l), s, l);
429 luaL_addsize(B, l);
430}
431
432
433COMPAT53_API void luaL_addvalue (luaL_Buffer_53 *B) {
434 size_t len = 0;
435 const char *s = lua_tolstring(B->L2, -1, &len);
436 if (!s)
437 luaL_error(B->L2, "cannot convert value to string");
438 if (B->ptr != B->b.buffer)
439 lua_insert(B->L2, -2); /* userdata buffer must be at stack top */
440 luaL_addlstring(B, s, len);
441 lua_remove(B->L2, B->ptr != B->b.buffer ? -2 : -1);
442}
443
444
445void luaL_pushresult (luaL_Buffer_53 *B) {
446 lua_pushlstring(B->L2, B->ptr, B->nelems);
447 if (B->ptr != B->b.buffer)
448 lua_replace(B->L2, -2); /* remove userdata buffer */
449}
450
451
452#endif /* Lua 5.1 */
453
454
455
456/* definitions for Lua 5.1 and Lua 5.2 */
457#if defined( LUA_VERSION_NUM ) && LUA_VERSION_NUM <= 502
458
459
460COMPAT53_API int lua_geti (lua_State *L, int index, lua_Integer i) {
461 index = lua_absindex(L, index);
462 lua_pushinteger(L, i);
463 lua_gettable(L, index);
464 return lua_type(L, -1);
465}
466
467
468COMPAT53_API int lua_isinteger (lua_State *L, int index) {
469 if (lua_type(L, index) == LUA_TNUMBER) {
470 lua_Number n = lua_tonumber(L, index);
471 lua_Integer i = lua_tointeger(L, index);
472 if (i == n)
473 return 1;
474 }
475 return 0;
476}
477
478
479static void compat53_reverse (lua_State *L, int a, int b) {
480 for (; a < b; ++a, --b) {
481 lua_pushvalue(L, a);
482 lua_pushvalue(L, b);
483 lua_replace(L, a);
484 lua_replace(L, b);
485 }
486}
487
488
489COMPAT53_API void lua_rotate (lua_State *L, int idx, int n) {
490 int n_elems = 0;
491 idx = lua_absindex(L, idx);
492 n_elems = lua_gettop(L)-idx+1;
493 if (n < 0)
494 n += n_elems;
495 if ( n > 0 && n < n_elems) {
496 luaL_checkstack(L, 2, "not enough stack slots available");
497 n = n_elems - n;
498 compat53_reverse(L, idx, idx+n-1);
499 compat53_reverse(L, idx+n, idx+n_elems-1);
500 compat53_reverse(L, idx, idx+n_elems-1);
501 }
502}
503
504
505COMPAT53_API void lua_seti (lua_State *L, int index, lua_Integer i) {
506 luaL_checkstack(L, 1, "not enough stack slots available");
507 index = lua_absindex(L, index);
508 lua_pushinteger(L, i);
509 lua_insert(L, -2);
510 lua_settable(L, index);
511}
512
513
514#if !defined(lua_str2number)
515# define lua_str2number(s, p) strtod((s), (p))
516#endif
517
518COMPAT53_API size_t lua_stringtonumber (lua_State *L, const char *s) {
519 char* endptr;
520 lua_Number n = lua_str2number(s, &endptr);
521 if (endptr != s) {
522 while (*endptr != '\0' && isspace((unsigned char)*endptr))
523 ++endptr;
524 if (*endptr == '\0') {
525 lua_pushnumber(L, n);
526 return endptr - s + 1;
527 }
528 }
529 return 0;
530}
531
532
533COMPAT53_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) {
534 if (!luaL_callmeta(L, idx, "__tostring")) {
535 int t = lua_type(L, idx), tt = 0;
536 char const* name = NULL;
537 switch (t) {
538 case LUA_TNIL:
539 lua_pushliteral(L, "nil");
540 break;
541 case LUA_TSTRING:
542 case LUA_TNUMBER:
543 lua_pushvalue(L, idx);
544 break;
545 case LUA_TBOOLEAN:
546 if (lua_toboolean(L, idx))
547 lua_pushliteral(L, "true");
548 else
549 lua_pushliteral(L, "false");
550 break;
551 default:
552 tt = luaL_getmetafield(L, idx, "__name");
553 name = (tt == LUA_TSTRING) ? lua_tostring(L, -1) : lua_typename(L, t);
554 lua_pushfstring(L, "%s: %p", name, lua_topointer(L, idx));
555 if (tt != LUA_TNIL)
556 lua_replace(L, -2);
557 break;
558 }
559 } else {
560 if (!lua_isstring(L, -1))
561 luaL_error(L, "'__tostring' must return a string");
562 }
563 return lua_tolstring(L, -1, len);
564}
565
566
567COMPAT53_API void luaL_requiref (lua_State *L, const char *modname,
568 lua_CFunction openf, int glb) {
569 luaL_checkstack(L, 3, "not enough stack slots available");
570 luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED");
571 if (lua_getfield(L, -1, modname) == LUA_TNIL) {
572 lua_pop(L, 1);
573 lua_pushcfunction(L, openf);
574 lua_pushstring(L, modname);
575 lua_call(L, 1, 1);
576 lua_pushvalue(L, -1);
577 lua_setfield(L, -3, modname);
578 }
579 if (glb) {
580 lua_pushvalue(L, -1);
581 lua_setglobal(L, modname);
582 }
583 lua_replace(L, -2);
584}
585
586
587#endif /* Lua 5.1 and 5.2 */
588
589
590#endif /* COMPAT53_C_ */
591
592
593/*********************************************************************
594* This file contains parts of Lua 5.2's and Lua 5.3's source code:
595*
596* Copyright (C) 1994-2014 Lua.org, PUC-Rio.
597*
598* Permission is hereby granted, free of charge, to any person obtaining
599* a copy of this software and associated documentation files (the
600* "Software"), to deal in the Software without restriction, including
601* without limitation the rights to use, copy, modify, merge, publish,
602* distribute, sublicense, and/or sell copies of the Software, and to
603* permit persons to whom the Software is furnished to do so, subject to
604* the following conditions:
605*
606* The above copyright notice and this permission notice shall be
607* included in all copies or substantial portions of the Software.
608*
609* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
610* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
611* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
612* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
613* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
614* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
615* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
616*********************************************************************/
617
diff --git a/vendor/compat53/c-api/compat-5.3.h b/vendor/compat53/c-api/compat-5.3.h
new file mode 100644
index 0000000..bee77a1
--- /dev/null
+++ b/vendor/compat53/c-api/compat-5.3.h
@@ -0,0 +1,388 @@
1#ifndef COMPAT53_H_
2#define COMPAT53_H_
3
4#include <stddef.h>
5#include <limits.h>
6#include <string.h>
7#if defined(__cplusplus) && !defined(COMPAT53_LUA_CPP)
8extern "C" {
9#endif
10#include <lua.h>
11#include <lauxlib.h>
12#if defined(__cplusplus) && !defined(COMPAT53_LUA_CPP)
13}
14#endif
15
16
17#if defined(COMPAT53_PREFIX)
18/* - change the symbol names of functions to avoid linker conflicts
19 * - compat-5.3.c needs to be compiled (and linked) separately
20 */
21# if !defined(COMPAT53_API)
22# define COMPAT53_API extern
23# endif
24# undef COMPAT53_INCLUDE_SOURCE
25#else /* COMPAT53_PREFIX */
26/* - make all functions static and include the source.
27 * - compat-5.3.c doesn't need to be compiled (and linked) separately
28 */
29# define COMPAT53_PREFIX compat53
30# undef COMPAT53_API
31# if defined(__GNUC__) || defined(__clang__)
32# define COMPAT53_API __attribute__((__unused__)) static
33# else
34# define COMPAT53_API static
35# endif
36# define COMPAT53_INCLUDE_SOURCE
37#endif /* COMPAT53_PREFIX */
38
39#define COMPAT53_CONCAT_HELPER(a, b) a##b
40#define COMPAT53_CONCAT(a, b) COMPAT53_CONCAT_HELPER(a, b)
41
42
43
44/* declarations for Lua 5.1 */
45#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501
46
47/* XXX not implemented:
48 * lua_arith (new operators)
49 * lua_upvalueid
50 * lua_upvaluejoin
51 * lua_version
52 * lua_yieldk
53 * luaL_loadbufferx
54 * luaL_loadfilex
55 */
56
57#ifndef LUA_OK
58# define LUA_OK 0
59#endif
60#ifndef LUA_OPADD
61# define LUA_OPADD 0
62#endif
63#ifndef LUA_OPSUB
64# define LUA_OPSUB 1
65#endif
66#ifndef LUA_OPMUL
67# define LUA_OPMUL 2
68#endif
69#ifndef LUA_OPDIV
70# define LUA_OPDIV 3
71#endif
72#ifndef LUA_OPMOD
73# define LUA_OPMOD 4
74#endif
75#ifndef LUA_OPPOW
76# define LUA_OPPOW 5
77#endif
78#ifndef LUA_OPUNM
79# define LUA_OPUNM 6
80#endif
81#ifndef LUA_OPEQ
82# define LUA_OPEQ 0
83#endif
84#ifndef LUA_OPLT
85# define LUA_OPLT 1
86#endif
87#ifndef LUA_OPLE
88# define LUA_OPLE 2
89#endif
90
91typedef size_t lua_Unsigned;
92
93typedef struct luaL_Buffer_53 {
94 luaL_Buffer b; /* make incorrect code crash! */
95 char *ptr;
96 size_t nelems;
97 size_t capacity;
98 lua_State *L2;
99} luaL_Buffer_53;
100#define luaL_Buffer luaL_Buffer_53
101
102#define lua_absindex COMPAT53_CONCAT(COMPAT53_PREFIX, _absindex)
103COMPAT53_API int lua_absindex (lua_State *L, int i);
104
105#define lua_arith COMPAT53_CONCAT(COMPAT53_PREFIX, _arith)
106COMPAT53_API void lua_arith (lua_State *L, int op);
107
108#define lua_compare COMPAT53_CONCAT(COMPAT53_PREFIX, _compare)
109COMPAT53_API int lua_compare (lua_State *L, int idx1, int idx2, int op);
110
111#define lua_copy COMPAT53_CONCAT(COMPAT53_PREFIX, _copy)
112COMPAT53_API void lua_copy (lua_State *L, int from, int to);
113
114#define lua_getuservalue(L, i) \
115 (lua_getfenv((L), (i)), lua_type((L), -1))
116#define lua_setuservalue(L, i) \
117 (luaL_checktype((L), -1, LUA_TTABLE), lua_setfenv((L), (i)))
118
119#define lua_len COMPAT53_CONCAT(COMPAT53_PREFIX, _len)
120COMPAT53_API void lua_len (lua_State *L, int i);
121
122#define lua_pushstring(L, s) \
123 (lua_pushstring((L), (s)), lua_tostring((L), -1))
124
125#define lua_pushlstring(L, s, len) \
126 ((((len) == 0) ? lua_pushlstring((L), "", 0) : lua_pushlstring((L), (s), (len))), lua_tostring((L), -1))
127
128#ifndef luaL_newlibtable
129# define luaL_newlibtable(L, l) \
130 (lua_createtable((L), 0, sizeof((l))/sizeof(*(l))-1))
131#endif
132#ifndef luaL_newlib
133# define luaL_newlib(L, l) \
134 (luaL_newlibtable((L), (l)), luaL_register((L), NULL, (l)))
135#endif
136
137#define lua_pushglobaltable(L) \
138 lua_pushvalue((L), LUA_GLOBALSINDEX)
139
140#define lua_rawgetp COMPAT53_CONCAT(COMPAT53_PREFIX, _rawgetp)
141COMPAT53_API int lua_rawgetp (lua_State *L, int i, const void *p);
142
143#define lua_rawsetp COMPAT53_CONCAT(COMPAT53_PREFIX, _rawsetp)
144COMPAT53_API void lua_rawsetp(lua_State *L, int i, const void *p);
145
146#define lua_rawlen(L, i) lua_objlen((L), (i))
147
148#define lua_tointegerx COMPAT53_CONCAT(COMPAT53_PREFIX, _tointegerx)
149COMPAT53_API lua_Integer lua_tointegerx (lua_State *L, int i, int *isnum);
150
151#define lua_tonumberx COMPAT53_CONCAT(COMPAT53_PREFIX, _tonumberx)
152COMPAT53_API lua_Number lua_tonumberx (lua_State *L, int i, int *isnum);
153
154#define luaL_checkversion COMPAT53_CONCAT(COMPAT53_PREFIX, L_checkversion)
155COMPAT53_API void luaL_checkversion (lua_State *L);
156
157#define luaL_checkstack COMPAT53_CONCAT(COMPAT53_PREFIX, L_checkstack_53)
158COMPAT53_API void luaL_checkstack (lua_State *L, int sp, const char *msg);
159
160#define luaL_getsubtable COMPAT53_CONCAT(COMPAT53_PREFIX, L_getsubtable)
161COMPAT53_API int luaL_getsubtable (lua_State* L, int i, const char *name);
162
163#define luaL_len COMPAT53_CONCAT(COMPAT53_PREFIX, L_len)
164COMPAT53_API lua_Integer luaL_len (lua_State *L, int i);
165
166#define luaL_setfuncs COMPAT53_CONCAT(COMPAT53_PREFIX, L_setfuncs)
167COMPAT53_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup);
168
169#define luaL_setmetatable COMPAT53_CONCAT(COMPAT53_PREFIX, L_setmetatable)
170COMPAT53_API void luaL_setmetatable (lua_State *L, const char *tname);
171
172#define luaL_testudata COMPAT53_CONCAT(COMPAT53_PREFIX, L_testudata)
173COMPAT53_API void *luaL_testudata (lua_State *L, int i, const char *tname);
174
175#define luaL_traceback COMPAT53_CONCAT(COMPAT53_PREFIX, L_traceback)
176COMPAT53_API void luaL_traceback (lua_State *L, lua_State *L1, const char *msg, int level);
177
178#define luaL_fileresult COMPAT53_CONCAT(COMPAT53_PREFIX, L_fileresult)
179COMPAT53_API int luaL_fileresult (lua_State *L, int stat, const char *fname);
180
181#define luaL_execresult COMPAT53_CONCAT(COMPAT53_PREFIX, L_execresult)
182COMPAT53_API int luaL_execresult (lua_State *L, int stat);
183
184#define lua_callk(L, na, nr, ctx, cont) \
185 ((void)(ctx), (void)(cont), lua_call((L), (na), (nr)))
186#define lua_pcallk(L, na, nr, err, ctx, cont) \
187 ((void)(ctx), (void)(cont), lua_pcall((L), (na), (nr), (err)))
188
189#define luaL_buffinit COMPAT53_CONCAT(COMPAT53_PREFIX, _buffinit_53)
190COMPAT53_API void luaL_buffinit (lua_State *L, luaL_Buffer_53 *B);
191
192#define luaL_prepbuffsize COMPAT53_CONCAT(COMPAT53_PREFIX, _prepbufsize_53)
193COMPAT53_API char *luaL_prepbuffsize (luaL_Buffer_53 *B, size_t s);
194
195#define luaL_addlstring COMPAT53_CONCAT(COMPAT53_PREFIX, _addlstring_53)
196COMPAT53_API void luaL_addlstring (luaL_Buffer_53 *B, const char *s, size_t l);
197
198#define luaL_addvalue COMPAT53_CONCAT(COMPAT53_PREFIX, _addvalue_53)
199COMPAT53_API void luaL_addvalue (luaL_Buffer_53 *B);
200
201#define luaL_pushresult COMPAT53_CONCAT(COMPAT53_PREFIX, _pushresult_53)
202COMPAT53_API void luaL_pushresult (luaL_Buffer_53 *B);
203
204#undef luaL_buffinitsize
205#define luaL_buffinitsize(L, B, s) \
206 (luaL_buffinit((L), (B)), luaL_prepbuffsize((B), (s)))
207
208#undef luaL_prepbuffer
209#define luaL_prepbuffer(B) \
210 luaL_prepbuffsize((B), LUAL_BUFFERSIZE)
211
212#undef luaL_addchar
213#define luaL_addchar(B, c) \
214 ((void)((B)->nelems < (B)->capacity || luaL_prepbuffsize((B), 1)), \
215 ((B)->ptr[(B)->nelems++] = (c)))
216
217#undef luaL_addsize
218#define luaL_addsize(B, s) \
219 ((B)->nelems += (s))
220
221#undef luaL_addstring
222#define luaL_addstring(B, s) \
223 luaL_addlstring((B), (s), strlen((s)))
224
225#undef luaL_pushresultsize
226#define luaL_pushresultsize(B, s) \
227 (luaL_addsize((B), (s)), luaL_pushresult((B)))
228
229#if defined(LUA_COMPAT_APIINTCASTS)
230#define lua_pushunsigned(L, n) \
231 lua_pushinteger((L), (lua_Integer)(n))
232#define lua_tounsignedx(L, i, is) \
233 ((lua_Unsigned)lua_tointegerx((L), (i), (is)))
234#define lua_tounsigned(L, i) \
235 lua_tounsignedx((L), (i), NULL)
236#define luaL_checkunsigned(L, a) \
237 ((lua_Unsigned)luaL_checkinteger((L), (a)))
238#define luaL_optunsigned(L, a, d) \
239 ((lua_Unsigned)luaL_optinteger((L), (a), (lua_Integer)(d)))
240#endif
241
242#endif /* Lua 5.1 only */
243
244
245
246/* declarations for Lua 5.1 and 5.2 */
247#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM <= 502
248
249typedef int lua_KContext;
250
251typedef int (*lua_KFunction)(lua_State *L, int status, lua_KContext ctx);
252
253#define lua_dump(L, w, d, s) \
254 ((void)(s), lua_dump((L), (w), (d)))
255
256#define lua_getfield(L, i, k) \
257 (lua_getfield((L), (i), (k)), lua_type((L), -1))
258
259#define lua_gettable(L, i) \
260 (lua_gettable((L), (i)), lua_type((L), -1))
261
262#define lua_geti COMPAT53_CONCAT(COMPAT53_PREFIX, _geti)
263COMPAT53_API int lua_geti (lua_State *L, int index, lua_Integer i);
264
265#define lua_isinteger COMPAT53_CONCAT(COMPAT53_PREFIX, _isinteger)
266COMPAT53_API int lua_isinteger (lua_State *L, int index);
267
268#define lua_numbertointeger(n, p) \
269 ((*(p) = (lua_Integer)(n)), 1)
270
271#define lua_rawget(L, i) \
272 (lua_rawget((L), (i)), lua_type((L), -1))
273
274#define lua_rawgeti(L, i, n) \
275 (lua_rawgeti((L), (i), (n)), lua_type((L), -1))
276
277#define lua_rotate COMPAT53_CONCAT(COMPAT53_PREFIX, _rotate)
278COMPAT53_API void lua_rotate (lua_State *L, int idx, int n);
279
280#define lua_seti COMPAT53_CONCAT(COMPAT53_PREFIX, _seti)
281COMPAT53_API void lua_seti (lua_State *L, int index, lua_Integer i);
282
283#define lua_stringtonumber COMPAT53_CONCAT(COMPAT53_PREFIX, _stringtonumber)
284COMPAT53_API size_t lua_stringtonumber (lua_State *L, const char *s);
285
286#define luaL_tolstring COMPAT53_CONCAT(COMPAT53_PREFIX, L_tolstring)
287COMPAT53_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len);
288
289#define luaL_getmetafield(L, o, e) \
290 (luaL_getmetafield((L), (o), (e)) ? lua_type((L), -1) : LUA_TNIL)
291
292#define luaL_newmetatable(L, tn) \
293 (luaL_newmetatable((L), (tn)) ? (lua_pushstring((L), (tn)), lua_setfield((L), -2, "__name"), 1) : 0)
294
295#define luaL_requiref COMPAT53_CONCAT(COMPAT53_PREFIX, L_requiref_53)
296COMPAT53_API void luaL_requiref (lua_State *L, const char *modname,
297 lua_CFunction openf, int glb );
298
299#endif /* Lua 5.1 and Lua 5.2 */
300
301
302
303/* declarations for Lua 5.2 */
304#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 502
305
306/* XXX not implemented:
307 * lua_isyieldable
308 * lua_getextraspace
309 * lua_arith (new operators)
310 * lua_pushfstring (new formats)
311 */
312
313#define lua_getglobal(L, n) \
314 (lua_getglobal((L), (n)), lua_type((L), -1))
315
316#define lua_getuservalue(L, i) \
317 (lua_getuservalue((L), (i)), lua_type((L), -1))
318
319#define lua_pushlstring(L, s, len) \
320 (((len) == 0) ? lua_pushlstring((L), "", 0) : lua_pushlstring((L), (s), (len)))
321
322#define lua_rawgetp(L, i, p) \
323 (lua_rawgetp((L), (i), (p)), lua_type((L), -1))
324
325#define LUA_KFUNCTION(_name) \
326 static int (_name)(lua_State *L, int status, lua_KContext ctx); \
327 static int (_name ## _52)(lua_State *L) { \
328 lua_KContext ctx; \
329 int status = lua_getctx(L, &ctx); \
330 return (_name)(L, status, ctx); \
331 } \
332 static int (_name)(lua_State *L, int status, lua_KContext ctx)
333
334#define lua_pcallk(L, na, nr, err, ctx, cont) \
335 lua_pcallk((L), (na), (nr), (err), (ctx), cont ## _52)
336
337#define lua_callk(L, na, nr, ctx, cont) \
338 lua_callk((L), (na), (nr), (ctx), cont ## _52)
339
340#define lua_yieldk(L, nr, ctx, cont) \
341 lua_yieldk((L), (nr), (ctx), cont ## _52)
342
343#ifdef lua_call
344# undef lua_call
345# define lua_call(L, na, nr) \
346 (lua_callk)((L), (na), (nr), 0, NULL)
347#endif
348
349#ifdef lua_pcall
350# undef lua_pcall
351# define lua_pcall(L, na, nr, err) \
352 (lua_pcallk)((L), (na), (nr), (err), 0, NULL)
353#endif
354
355#ifdef lua_yield
356# undef lua_yield
357# define lua_yield(L, nr) \
358 (lua_yieldk)((L), (nr), 0, NULL)
359#endif
360
361#endif /* Lua 5.2 only */
362
363
364
365/* other Lua versions */
366#if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 501 || LUA_VERSION_NUM > 503
367
368# error "unsupported Lua version (i.e. not Lua 5.1, 5.2, or 5.3)"
369
370#endif /* other Lua versions except 5.1, 5.2, and 5.3 */
371
372
373
374/* helper macro for defining continuation functions (for every version
375 * *except* Lua 5.2) */
376#ifndef LUA_KFUNCTION
377#define LUA_KFUNCTION(_name) \
378 static int (_name)(lua_State *L, int status, lua_KContext ctx)
379#endif
380
381
382#if defined(COMPAT53_INCLUDE_SOURCE)
383# include "compat-5.3.c"
384#endif
385
386
387#endif /* COMPAT53_H_ */
388
diff --git a/vendor/compat53/compat53/init.lua b/vendor/compat53/compat53/init.lua
new file mode 100644
index 0000000..a7f0c80
--- /dev/null
+++ b/vendor/compat53/compat53/init.lua
@@ -0,0 +1,373 @@
1local lua_version = _VERSION:sub(-3)
2
3
4if lua_version < "5.3" then
5
6 local _G, pairs, require, select, type =
7 _G, pairs, require, select, type
8 local debug, io = debug, io
9 local unpack = lua_version == "5.1" and unpack or table.unpack
10
11 local M = require("compat53.module")
12
13 -- select the most powerful getmetatable function available
14 local gmt = type(debug) == "table" and debug.getmetatable or
15 getmetatable or function() return false end
16 -- metatable for file objects from Lua's standard io library
17 local file_meta = gmt(io.stdout)
18
19
20 -- make '*' optional for file:read and file:lines
21 if type(file_meta) == "table" and type(file_meta.__index) == "table" then
22
23 local function addasterisk(fmt)
24 if type(fmt) == "string" and fmt:sub(1, 1) ~= "*" then
25 return "*"..fmt
26 else
27 return fmt
28 end
29 end
30
31 local file_lines = file_meta.__index.lines
32 file_meta.__index.lines = function(self, ...)
33 local n = select('#', ...)
34 for i = 1, n do
35 local a = select(i, ...)
36 local b = addasterisk(a)
37 -- as an optimization we only allocate a table for the
38 -- modified format arguments when we have a '*' somewhere
39 if a ~= b then
40 local args = { ... }
41 args[i] = b
42 for j = i+1, n do
43 args[j] = addasterisk(args[j])
44 end
45 return file_lines(self, unpack(args, 1, n))
46 end
47 end
48 return file_lines(self, ...)
49 end
50
51 local file_read = file_meta.__index.read
52 file_meta.__index.read = function(self, ...)
53 local n = select('#', ...)
54 for i = 1, n do
55 local a = select(i, ...)
56 local b = addasterisk(a)
57 -- as an optimization we only allocate a table for the
58 -- modified format arguments when we have a '*' somewhere
59 if a ~= b then
60 local args = { ... }
61 args[i] = b
62 for j = i+1, n do
63 args[j] = addasterisk(args[j])
64 end
65 return file_read(self, unpack(args, 1, n))
66 end
67 end
68 return file_read(self, ...)
69 end
70
71 end -- got a valid metatable for file objects
72
73
74 -- changes for Lua 5.1 only
75 if lua_version == "5.1" then
76
77 -- cache globals
78 local error, pcall, rawset, setmetatable, tostring, xpcall =
79 error, pcall, rawset, setmetatable, tostring, xpcall
80 local coroutine, package, string = coroutine, package, string
81 local coroutine_resume = coroutine.resume
82 local coroutine_running = coroutine.running
83 local coroutine_status = coroutine.status
84 local coroutine_yield = coroutine.yield
85 local io_type = io.type
86
87
88 -- detect LuaJIT (including LUAJIT_ENABLE_LUA52COMPAT compilation flag)
89 local is_luajit = (string.dump(function() end) or ""):sub(1, 3) == "\027LJ"
90 local is_luajit52 = is_luajit and
91 #setmetatable({}, { __len = function() return 1 end }) == 1
92
93
94 -- make package.searchers available as an alias for package.loaders
95 local p_index = { searchers = package.loaders }
96 setmetatable(package, {
97 __index = p_index,
98 __newindex = function(p, k, v)
99 if k == "searchers" then
100 rawset(p, "loaders", v)
101 p_index.searchers = v
102 else
103 rawset(p, k, v)
104 end
105 end
106 })
107
108
109 if type(file_meta) == "table" and type(file_meta.__index) == "table" then
110 if not is_luajit then
111 local function helper(_, var_1, ...)
112 if var_1 == nil then
113 if (...) ~= nil then
114 error((...), 2)
115 end
116 end
117 return var_1, ...
118 end
119
120 local function lines_iterator(st)
121 return helper(st, st.f:read(unpack(st, 1, st.n)))
122 end
123
124 local file_write = file_meta.__index.write
125 file_meta.__index.write = function(self, ...)
126 local res, msg, errno = file_write(self, ...)
127 if res then
128 return self
129 else
130 return nil, msg, errno
131 end
132 end
133
134 file_meta.__index.lines = function(self, ...)
135 if io_type(self) == "closed file" then
136 error("attempt to use a closed file", 2)
137 end
138 local st = { f=self, n=select('#', ...), ... }
139 for i = 1, st.n do
140 local t = type(st[i])
141 if t == "string" then
142 local fmt = st[i]:match("^*?([aln])")
143 if not fmt then
144 error("bad argument #"..(i+1).." to 'for iterator' (invalid format)", 2)
145 end
146 st[i] = "*"..fmt
147 elseif t ~= "number" then
148 error("bad argument #"..(i+1).." to 'for iterator' (invalid format)", 2)
149 end
150 end
151 return lines_iterator, st
152 end
153 end -- not luajit
154 end -- file_meta valid
155
156
157 -- the (x)pcall implementations start a new coroutine internally
158 -- to allow yielding even in Lua 5.1. to allow for accurate
159 -- stack traces we keep track of the nested coroutine activations
160 -- in the weak tables below:
161 local weak_meta = { __mode = "kv" }
162 -- maps the internal pcall coroutines to the user coroutine that
163 -- *should* be running if pcall didn't use coroutines internally
164 local pcall_mainOf = setmetatable({}, weak_meta)
165 -- table that maps each running coroutine started by pcall to
166 -- the coroutine that resumed it (user coroutine *or* pcall
167 -- coroutine!)
168 local pcall_previous = setmetatable({}, weak_meta)
169 -- reverse of `pcall_mainOf`. maps a user coroutine to the
170 -- currently active pcall coroutine started within it
171 local pcall_callOf = setmetatable({}, weak_meta)
172 -- similar to `pcall_mainOf` but is used only while executing
173 -- the error handler of xpcall (thus no nesting is necessary!)
174 local xpcall_running = setmetatable({}, weak_meta)
175
176 -- handle debug functions
177 if type(debug) == "table" then
178 local debug_getinfo = debug.getinfo
179 local debug_traceback = debug.traceback
180
181 if not is_luajit then
182 local function calculate_trace_level(co, level)
183 if level ~= nil then
184 for out = 1, 1/0 do
185 local info = (co==nil) and debug_getinfo(out, "") or debug_getinfo(co, out, "")
186 if info == nil then
187 local max = out-1
188 if level <= max then
189 return level
190 end
191 return nil, level-max
192 end
193 end
194 end
195 return 1
196 end
197
198 local stack_pattern = "\nstack traceback:"
199 local stack_replace = ""
200 function debug.traceback(co, msg, level)
201 local lvl
202 local nilmsg
203 if type(co) ~= "thread" then
204 co, msg, level = coroutine_running(), co, msg
205 end
206 if msg == nil then
207 msg = ""
208 nilmsg = true
209 elseif type(msg) ~= "string" then
210 return msg
211 end
212 if co == nil then
213 msg = debug_traceback(msg, level or 1)
214 else
215 local xpco = xpcall_running[co]
216 if xpco ~= nil then
217 lvl, level = calculate_trace_level(xpco, level)
218 if lvl then
219 msg = debug_traceback(xpco, msg, lvl)
220 else
221 msg = msg..stack_pattern
222 end
223 lvl, level = calculate_trace_level(co, level)
224 if lvl then
225 local trace = debug_traceback(co, "", lvl)
226 msg = msg..trace:gsub(stack_pattern, stack_replace)
227 end
228 else
229 co = pcall_callOf[co] or co
230 lvl, level = calculate_trace_level(co, level)
231 if lvl then
232 msg = debug_traceback(co, msg, lvl)
233 else
234 msg = msg..stack_pattern
235 end
236 end
237 co = pcall_previous[co]
238 while co ~= nil do
239 lvl, level = calculate_trace_level(co, level)
240 if lvl then
241 local trace = debug_traceback(co, "", lvl)
242 msg = msg..trace:gsub(stack_pattern, stack_replace)
243 end
244 co = pcall_previous[co]
245 end
246 end
247 if nilmsg then
248 msg = msg:gsub("^\n", "")
249 end
250 msg = msg:gsub("\n\t%(tail call%): %?", "\000")
251 msg = msg:gsub("\n\t%.%.%.\n", "\001\n")
252 msg = msg:gsub("\n\t%.%.%.$", "\001")
253 msg = msg:gsub("(%z+)\001(%z+)", function(some, other)
254 return "\n\t(..."..#some+#other.."+ tail call(s)...)"
255 end)
256 msg = msg:gsub("\001(%z+)", function(zeros)
257 return "\n\t(..."..#zeros.."+ tail call(s)...)"
258 end)
259 msg = msg:gsub("(%z+)\001", function(zeros)
260 return "\n\t(..."..#zeros.."+ tail call(s)...)"
261 end)
262 msg = msg:gsub("%z+", function(zeros)
263 return "\n\t(..."..#zeros.." tail call(s)...)"
264 end)
265 msg = msg:gsub("\001", function()
266 return "\n\t..."
267 end)
268 return msg
269 end
270 end -- is not luajit
271 end -- debug table available
272
273
274 if not is_luajit52 then
275 local coroutine_running52 = M.coroutine.running
276 function M.coroutine.running()
277 local co, ismain = coroutine_running52()
278 if ismain then
279 return co, true
280 else
281 return pcall_mainOf[co] or co, false
282 end
283 end
284 end
285
286 if not is_luajit then
287 local function pcall_results(current, call, success, ...)
288 if coroutine_status(call) == "suspended" then
289 return pcall_results(current, call, coroutine_resume(call, coroutine_yield(...)))
290 end
291 if pcall_previous then
292 pcall_previous[call] = nil
293 local main = pcall_mainOf[call]
294 if main == current then current = nil end
295 pcall_callOf[main] = current
296 end
297 pcall_mainOf[call] = nil
298 return success, ...
299 end
300
301 local function pcall_exec(current, call, ...)
302 local main = pcall_mainOf[current] or current
303 pcall_mainOf[call] = main
304 if pcall_previous then
305 pcall_previous[call] = current
306 pcall_callOf[main] = call
307 end
308 return pcall_results(current, call, coroutine_resume(call, ...))
309 end
310
311 local coroutine_create52 = M.coroutine.create
312
313 local function pcall_coroutine(func)
314 if type(func) ~= "function" then
315 local callable = func
316 func = function (...) return callable(...) end
317 end
318 return coroutine_create52(func)
319 end
320
321 function M.pcall(func, ...)
322 local current = coroutine_running()
323 if not current then return pcall(func, ...) end
324 return pcall_exec(current, pcall_coroutine(func), ...)
325 end
326
327 local function xpcall_catch(current, call, msgh, success, ...)
328 if not success then
329 xpcall_running[current] = call
330 local ok, result = pcall(msgh, ...)
331 xpcall_running[current] = nil
332 if not ok then
333 return false, "error in error handling ("..tostring(result)..")"
334 end
335 return false, result
336 end
337 return true, ...
338 end
339
340 function M.xpcall(f, msgh, ...)
341 local current = coroutine_running()
342 if not current then
343 local args, n = { ... }, select('#', ...)
344 return xpcall(function() return f(unpack(args, 1, n)) end, msgh)
345 end
346 local call = pcall_coroutine(f)
347 return xpcall_catch(current, call, msgh, pcall_exec(current, call, ...))
348 end
349 end -- not luajit
350
351 end -- lua 5.1
352
353
354 -- handle exporting to global scope
355 local function extend_table(from, to)
356 if from ~= to then
357 for k,v in pairs(from) do
358 if type(v) == "table" and
359 type(to[k]) == "table" and
360 v ~= to[k] then
361 extend_table(v, to[k])
362 else
363 to[k] = v
364 end
365 end
366 end
367 end
368
369 extend_table(M, _G)
370
371end -- lua < 5.3
372
373-- vi: set expandtab softtabstop=3 shiftwidth=3 :
diff --git a/vendor/compat53/compat53/module.lua b/vendor/compat53/compat53/module.lua
new file mode 100644
index 0000000..30be6b5
--- /dev/null
+++ b/vendor/compat53/compat53/module.lua
@@ -0,0 +1,827 @@
1local _G, _VERSION = _G, _VERSION
2local lua_version = _VERSION:sub(-3)
3
4
5local M = _G
6
7if lua_version < "5.3" then
8
9 -- cache globals in upvalues
10 local error, ipairs, pairs, pcall, require, select, setmetatable, type =
11 error, ipairs, pairs, pcall, require, select, setmetatable, type
12 local debug, io, math, package, string, table =
13 debug, io, math, package, string, table
14 local io_lines = io.lines
15 local io_read = io.read
16 local unpack = lua_version == "5.1" and unpack or table.unpack
17
18 -- create module table
19 M = {}
20 local M_meta = {
21 __index = _G,
22 -- __newindex is set at the end
23 }
24 setmetatable(M, M_meta)
25
26 -- create subtables
27 M.io = setmetatable({}, { __index = io })
28 M.math = setmetatable({}, { __index = math })
29 M.string = setmetatable({}, { __index = string })
30 M.table = setmetatable({}, { __index = table })
31 M.utf8 = {}
32
33
34 -- select the most powerful getmetatable function available
35 local gmt = type(debug) == "table" and debug.getmetatable or
36 getmetatable or function() return false end
37
38 -- type checking functions
39 local checkinteger -- forward declararation
40
41 local function argcheck(cond, i, f, extra)
42 if not cond then
43 error("bad argument #"..i.." to '"..f.."' ("..extra..")", 0)
44 end
45 end
46
47
48 -- load utf8 library
49 local utf8_ok, utf8lib = pcall(require, "compat53.utf8")
50 if utf8_ok then
51 if lua_version == "5.1" then
52 utf8lib.charpattern = "[%z\1-\127\194-\244][\128-\191]*"
53 end
54 for k,v in pairs(utf8lib) do
55 M.utf8[k] = v
56 end
57 package.loaded["utf8"] = M.utf8
58 end
59
60
61 -- load table library
62 local table_ok, tablib = pcall(require, "compat53.table")
63 if table_ok then
64 for k,v in pairs(tablib) do
65 M.table[k] = v
66 end
67 end
68
69
70 -- load string packing functions
71 local str_ok, strlib = pcall(require, "compat53.string")
72 if str_ok then
73 for k,v in pairs(strlib) do
74 M.string[k] = v
75 end
76 end
77
78
79 -- try Roberto's struct module for string packing/unpacking if
80 -- compat53.string is unavailable
81 if not str_ok then
82 local struct_ok, struct = pcall(require, "struct")
83 if struct_ok then
84 M.string.pack = struct.pack
85 M.string.packsize = struct.size
86 M.string.unpack = struct.unpack
87 end
88 end
89
90
91 -- update math library
92 do
93 local maxint, minint = 1
94
95 while maxint+1 > maxint and 2*maxint > maxint do
96 maxint = maxint * 2
97 end
98 if 2*maxint <= maxint then
99 maxint = 2*maxint-1
100 minint = -maxint-1
101 else
102 maxint = maxint
103 minint = -maxint
104 end
105 M.math.maxinteger = maxint
106 M.math.mininteger = minint
107
108 function M.math.tointeger(n)
109 if type(n) == "number" and n <= maxint and n >= minint and n % 1 == 0 then
110 return n
111 end
112 return nil
113 end
114
115 function M.math.type(n)
116 if type(n) == "number" then
117 if n <= maxint and n >= minint and n % 1 == 0 then
118 return "integer"
119 else
120 return "float"
121 end
122 else
123 return nil
124 end
125 end
126
127 function checkinteger(x, i, f)
128 local t = type(x)
129 if t ~= "number" then
130 error("bad argument #"..i.." to '"..f..
131 "' (number expected, got "..t..")", 0)
132 elseif x > maxint or x < minint or x % 1 ~= 0 then
133 error("bad argument #"..i.." to '"..f..
134 "' (number has no integer representation)", 0)
135 else
136 return x
137 end
138 end
139
140 function M.math.ult(m, n)
141 m = checkinteger(m, "1", "math.ult")
142 n = checkinteger(n, "2", "math.ult")
143 if m >= 0 and n < 0 then
144 return true
145 elseif m < 0 and n >= 0 then
146 return false
147 else
148 return m < n
149 end
150 end
151 end
152
153
154 -- assert should allow non-string error objects
155 function M.assert(cond, ...)
156 if cond then
157 return cond, ...
158 elseif select('#', ...) > 0 then
159 error((...), 0)
160 else
161 error("assertion failed!", 0)
162 end
163 end
164
165
166 -- ipairs should respect __index metamethod
167 do
168 local function ipairs_iterator(st, var)
169 var = var + 1
170 local val = st[var]
171 if val ~= nil then
172 return var, st[var]
173 end
174 end
175 function M.ipairs(t)
176 if gmt(t) ~= nil then -- t has metatable
177 return ipairs_iterator, t, 0
178 else
179 return ipairs(t)
180 end
181 end
182 end
183
184
185 -- make '*' optional for io.read and io.lines
186 do
187 local function addasterisk(fmt)
188 if type(fmt) == "string" and fmt:sub(1, 1) ~= "*" then
189 return "*"..fmt
190 else
191 return fmt
192 end
193 end
194
195 function M.io.read(...)
196 local n = select('#', ...)
197 for i = 1, n do
198 local a = select(i, ...)
199 local b = addasterisk(a)
200 -- as an optimization we only allocate a table for the
201 -- modified format arguments when we have a '*' somewhere.
202 if a ~= b then
203 local args = { ... }
204 args[i] = b
205 for j = i+1, n do
206 args[j] = addasterisk(args[j])
207 end
208 return io_read(unpack(args, 1, n))
209 end
210 end
211 return io_read(...)
212 end
213
214 -- PUC-Rio Lua 5.1 uses a different implementation for io.lines!
215 function M.io.lines(...)
216 local n = select('#', ...)
217 for i = 2, n do
218 local a = select(i, ...)
219 local b = addasterisk(a)
220 -- as an optimization we only allocate a table for the
221 -- modified format arguments when we have a '*' somewhere.
222 if a ~= b then
223 local args = { ... }
224 args[i] = b
225 for j = i+1, n do
226 args[j] = addasterisk(args[j])
227 end
228 return io_lines(unpack(args, 1, n))
229 end
230 end
231 return io_lines(...)
232 end
233 end
234
235
236 -- update table library (if C module not available)
237 if not table_ok then
238 local table_concat = table.concat
239 local table_insert = table.insert
240 local table_remove = table.remove
241 local table_sort = table.sort
242
243 function M.table.concat(list, sep, i, j)
244 local mt = gmt(list)
245 if type(mt) == "table" and type(mt.__len) == "function" then
246 local src = list
247 list, i, j = {}, i or 1, j or mt.__len(src)
248 for k = i, j do
249 list[k] = src[k]
250 end
251 end
252 return table_concat(list, sep, i, j)
253 end
254
255 function M.table.insert(list, ...)
256 local mt = gmt(list)
257 local has_mt = type(mt) == "table"
258 local has_len = has_mt and type(mt.__len) == "function"
259 if has_mt and (has_len or mt.__index or mt.__newindex) then
260 local e = (has_len and mt.__len(list) or #list)+1
261 local nargs, pos, value = select('#', ...), ...
262 if nargs == 1 then
263 pos, value = e, pos
264 elseif nargs == 2 then
265 pos = checkinteger(pos, "2", "table.insert")
266 argcheck(1 <= pos and pos <= e, "2", "table.insert",
267 "position out of bounds" )
268 else
269 error("wrong number of arguments to 'insert'", 0)
270 end
271 for i = e-1, pos, -1 do
272 list[i+1] = list[i]
273 end
274 list[pos] = value
275 else
276 return table_insert(list, ...)
277 end
278 end
279
280 function M.table.move(a1, f, e, t, a2)
281 a2 = a2 or a1
282 f = checkinteger(f, "2", "table.move")
283 argcheck(f > 0, "2", "table.move",
284 "initial position must be positive")
285 e = checkinteger(e, "3", "table.move")
286 t = checkinteger(t, "4", "table.move")
287 if e >= f then
288 local m, n, d = 0, e-f, 1
289 if t > f then m, n, d = n, m, -1 end
290 for i = m, n, d do
291 a2[t+i] = a1[f+i]
292 end
293 end
294 return a2
295 end
296
297 function M.table.remove(list, pos)
298 local mt = gmt(list)
299 local has_mt = type(mt) == "table"
300 local has_len = has_mt and type(mt.__len) == "function"
301 if has_mt and (has_len or mt.__index or mt.__newindex) then
302 local e = (has_len and mt.__len(list) or #list)
303 pos = pos ~= nil and checkinteger(pos, "2", "table.remove") or e
304 if pos ~= e then
305 argcheck(1 <= pos and pos <= e+1, "2", "table.remove",
306 "position out of bounds" )
307 end
308 local result = list[pos]
309 while pos < e do
310 list[pos] = list[pos+1]
311 pos = pos + 1
312 end
313 list[pos] = nil
314 return result
315 else
316 return table_remove(list, pos)
317 end
318 end
319
320 do
321 local function pivot(list, cmp, a, b)
322 local m = b - a
323 if m > 2 then
324 local c = a + (m-m%2)/2
325 local x, y, z = list[a], list[b], list[c]
326 if not cmp(x, y) then
327 x, y, a, b = y, x, b, a
328 end
329 if not cmp(y, z) then
330 y, b = z, c
331 end
332 if not cmp(x, y) then
333 y, b = x, a
334 end
335 return b, y
336 else
337 return b, list[b]
338 end
339 end
340
341 local function lt_cmp(a, b)
342 return a < b
343 end
344
345 local function qsort(list, cmp, b, e)
346 if b < e then
347 local i, j, k, val = b, e, pivot(list, cmp, b, e)
348 while i < j do
349 while i < j and cmp(list[i], val) do
350 i = i + 1
351 end
352 while i < j and not cmp(list[j], val) do
353 j = j - 1
354 end
355 if i < j then
356 list[i], list[j] = list[j], list[i]
357 if i == k then k = j end -- update pivot position
358 i, j = i+1, j-1
359 end
360 end
361 if i ~= k and not cmp(list[i], val) then
362 list[i], list[k] = val, list[i]
363 k = i -- update pivot position
364 end
365 qsort(list, cmp, b, i == k and i-1 or i)
366 return qsort(list, cmp, i+1, e)
367 end
368 end
369
370 function M.table.sort(list, cmp)
371 local mt = gmt(list)
372 local has_mt = type(mt) == "table"
373 local has_len = has_mt and type(mt.__len) == "function"
374 if has_len then
375 cmp = cmp or lt_cmp
376 local len = mt.__len(list)
377 return qsort(list, cmp, 1, len)
378 else
379 return table_sort(list, cmp)
380 end
381 end
382 end
383
384 local function unpack_helper(list, i, j, ...)
385 if j < i then
386 return ...
387 else
388 return unpack_helper(list, i, j-1, list[j], ...)
389 end
390 end
391 function M.table.unpack(list, i, j)
392 local mt = gmt(list)
393 local has_mt = type(mt) == "table"
394 local has_len = has_mt and type(mt.__len) == "function"
395 if has_mt and (has_len or mt.__index) then
396 i, j = i or 1, j or (has_len and mt.__len(list)) or #list
397 return unpack_helper(list, i, j)
398 else
399 return unpack(list, i, j)
400 end
401 end
402 end -- update table library
403
404
405 -- bring Lua 5.1 (and LuaJIT) up to speed with Lua 5.2
406 if lua_version == "5.1" then
407 -- detect LuaJIT (including LUAJIT_ENABLE_LUA52COMPAT compilation flag)
408 local is_luajit = (string.dump(function() end) or ""):sub(1, 3) == "\027LJ"
409 local is_luajit52 = is_luajit and
410 #setmetatable({}, { __len = function() return 1 end }) == 1
411
412 -- cache globals in upvalues
413 local load, loadfile, loadstring, setfenv, xpcall =
414 load, loadfile, loadstring, setfenv, xpcall
415 local coroutine, os = coroutine, os
416 local coroutine_create = coroutine.create
417 local coroutine_resume = coroutine.resume
418 local coroutine_running = coroutine.running
419 local coroutine_status = coroutine.status
420 local coroutine_yield = coroutine.yield
421 local io_input = io.input
422 local io_open = io.open
423 local io_output = io.output
424 local io_write = io.write
425 local math_log = math.log
426 local os_execute = os.execute
427 local string_find = string.find
428 local string_format = string.format
429 local string_gmatch = string.gmatch
430 local string_gsub = string.gsub
431 local string_match = string.match
432 local string_rep = string.rep
433 local table_concat = table.concat
434
435 -- create subtables
436 M.coroutine = setmetatable({}, { __index = coroutine })
437 M.os = setmetatable({}, { __index = os })
438 M.package = setmetatable({}, { __index = package })
439
440 -- handle debug functions
441 if type(debug) == "table" then
442 local debug_setfenv = debug.setfenv
443 local debug_getfenv = debug.getfenv
444 local debug_setmetatable = debug.setmetatable
445
446 M.debug = setmetatable({}, { __index = debug })
447
448 if not is_luajit52 then
449 function M.debug.setuservalue(obj, value)
450 if type(obj) ~= "userdata" then
451 error("bad argument #1 to 'setuservalue' (userdata expected, got "..
452 type(obj)..")", 2)
453 end
454 if value == nil then value = _G end
455 if type(value) ~= "table" then
456 error("bad argument #2 to 'setuservalue' (table expected, got "..
457 type(value)..")", 2)
458 end
459 return debug_setfenv(obj, value)
460 end
461
462 function M.debug.getuservalue(obj)
463 if type(obj) ~= "userdata" then
464 return nil
465 else
466 local v = debug_getfenv(obj)
467 if v == _G or v == package then
468 return nil
469 end
470 return v
471 end
472 end
473
474 function M.debug.setmetatable(value, tab)
475 debug_setmetatable(value, tab)
476 return value
477 end
478 end -- not luajit with compat52 enabled
479 end -- debug table available
480
481
482 if not is_luajit52 then
483 function M.pairs(t)
484 local mt = gmt(t)
485 if type(mt) == "table" and type(mt.__pairs) == "function" then
486 return mt.__pairs(t)
487 else
488 return pairs(t)
489 end
490 end
491 end
492
493
494 if not is_luajit then
495 local function check_mode(mode, prefix)
496 local has = { text = false, binary = false }
497 for i = 1,#mode do
498 local c = mode:sub(i, i)
499 if c == "t" then has.text = true end
500 if c == "b" then has.binary = true end
501 end
502 local t = prefix:sub(1, 1) == "\27" and "binary" or "text"
503 if not has[t] then
504 return "attempt to load a "..t.." chunk (mode is '"..mode.."')"
505 end
506 end
507
508 function M.load(ld, source, mode, env)
509 mode = mode or "bt"
510 local chunk, msg
511 if type( ld ) == "string" then
512 if mode ~= "bt" then
513 local merr = check_mode(mode, ld)
514 if merr then return nil, merr end
515 end
516 chunk, msg = loadstring(ld, source)
517 else
518 local ld_type = type(ld)
519 if ld_type ~= "function" then
520 error("bad argument #1 to 'load' (function expected, got "..
521 ld_type..")", 2)
522 end
523 if mode ~= "bt" then
524 local checked, merr = false, nil
525 local function checked_ld()
526 if checked then
527 return ld()
528 else
529 checked = true
530 local v = ld()
531 merr = check_mode(mode, v or "")
532 if merr then return nil end
533 return v
534 end
535 end
536 chunk, msg = load(checked_ld, source)
537 if merr then return nil, merr end
538 else
539 chunk, msg = load(ld, source)
540 end
541 end
542 if not chunk then
543 return chunk, msg
544 end
545 if env ~= nil then
546 setfenv(chunk, env)
547 end
548 return chunk
549 end
550
551 M.loadstring = M.load
552
553 function M.loadfile(file, mode, env)
554 mode = mode or "bt"
555 if mode ~= "bt" then
556 local f = io_open(file, "rb")
557 if f then
558 local prefix = f:read(1)
559 f:close()
560 if prefix then
561 local merr = check_mode(mode, prefix)
562 if merr then return nil, merr end
563 end
564 end
565 end
566 local chunk, msg = loadfile(file)
567 if not chunk then
568 return chunk, msg
569 end
570 if env ~= nil then
571 setfenv(chunk, env)
572 end
573 return chunk
574 end
575 end -- not luajit
576
577
578 if not is_luajit52 then
579 function M.rawlen(v)
580 local t = type(v)
581 if t ~= "string" and t ~= "table" then
582 error("bad argument #1 to 'rawlen' (table or string expected)", 2)
583 end
584 return #v
585 end
586 end
587
588
589 if not is_luajit then
590 function M.xpcall(f, msgh, ...)
591 local args, n = { ... }, select('#', ...)
592 return xpcall(function() return f(unpack(args, 1, n)) end, msgh)
593 end
594 end
595
596
597 if not is_luajit52 then
598 function M.os.execute(cmd)
599 local code = os_execute(cmd)
600 -- Lua 5.1 does not report exit by signal.
601 if code == 0 then
602 return true, "exit", code
603 else
604 if package.config:sub(1, 1) == '/' then
605 code = code/256 -- only correct on Linux!
606 end
607 return nil, "exit", code
608 end
609 end
610 end
611
612
613 if not table_ok and not is_luajit52 then
614 M.table.pack = function(...)
615 return { n = select('#', ...), ... }
616 end
617 end
618
619
620 local main_coroutine = coroutine_create(function() end)
621
622 function M.coroutine.create(func)
623 local success, result = pcall(coroutine_create, func)
624 if not success then
625 if type(func) ~= "function" then
626 error("bad argument #1 (function expected)", 0)
627 end
628 result = coroutine_create(function(...) return func(...) end)
629 end
630 return result
631 end
632
633 if not is_luajit52 then
634 function M.coroutine.running()
635 local co = coroutine_running()
636 if co then
637 return co, false
638 else
639 return main_coroutine, true
640 end
641 end
642 end
643
644 function M.coroutine.yield(...)
645 local co, flag = coroutine_running()
646 if co and not flag then
647 return coroutine_yield(...)
648 else
649 error("attempt to yield from outside a coroutine", 0)
650 end
651 end
652
653 if not is_luajit then
654 function M.coroutine.resume(co, ...)
655 if co == main_coroutine then
656 return false, "cannot resume non-suspended coroutine"
657 else
658 return coroutine_resume(co, ...)
659 end
660 end
661
662 function M.coroutine.status(co)
663 local notmain = coroutine_running()
664 if co == main_coroutine then
665 return notmain and "normal" or "running"
666 else
667 return coroutine_status(co)
668 end
669 end
670 end -- not luajit
671
672
673 if not is_luajit then
674 M.math.log = function(x, base)
675 if base ~= nil then
676 return math_log(x)/math_log(base)
677 else
678 return math_log(x)
679 end
680 end
681 end
682
683
684 if not is_luajit then
685 function M.package.searchpath(name, path, sep, rep)
686 sep = (sep or "."):gsub("(%p)", "%%%1")
687 rep = (rep or package.config:sub(1, 1)):gsub("(%%)", "%%%1")
688 local pname = name:gsub(sep, rep):gsub("(%%)", "%%%1")
689 local msg = {}
690 for subpath in path:gmatch("[^;]+") do
691 local fpath = subpath:gsub("%?", pname)
692 local f = io_open(fpath, "r")
693 if f then
694 f:close()
695 return fpath
696 end
697 msg[#msg+1] = "\n\tno file '" .. fpath .. "'"
698 end
699 return nil, table_concat(msg)
700 end
701 end
702
703
704 local function fix_pattern(pattern)
705 return (string_gsub(pattern, "%z", "%%z"))
706 end
707
708 function M.string.find(s, pattern, ...)
709 return string_find(s, fix_pattern(pattern), ...)
710 end
711
712 function M.string.gmatch(s, pattern)
713 return string_gmatch(s, fix_pattern(pattern))
714 end
715
716 function M.string.gsub(s, pattern, ...)
717 return string_gsub(s, fix_pattern(pattern), ...)
718 end
719
720 function M.string.match(s, pattern, ...)
721 return string_match(s, fix_pattern(pattern), ...)
722 end
723
724 if not is_luajit then
725 function M.string.rep(s, n, sep)
726 if sep ~= nil and sep ~= "" and n >= 2 then
727 return s .. string_rep(sep..s, n-1)
728 else
729 return string_rep(s, n)
730 end
731 end
732 end
733
734 if not is_luajit then
735 do
736 local addqt = {
737 ["\n"] = "\\\n",
738 ["\\"] = "\\\\",
739 ["\""] = "\\\""
740 }
741
742 local function addquoted(c, d)
743 return (addqt[c] or string_format(d~="" and "\\%03d" or "\\%d", c:byte()))..d
744 end
745
746 function M.string.format(fmt, ...)
747 local args, n = { ... }, select('#', ...)
748 local i = 0
749 local function adjust_fmt(lead, mods, kind)
750 if #lead % 2 == 0 then
751 i = i + 1
752 if kind == "s" then
753 args[i] = _G.tostring(args[i])
754 elseif kind == "q" then
755 args[i] = '"'..string_gsub(args[i], "([%z%c\\\"\n])(%d?)", addquoted)..'"'
756 return lead.."%"..mods.."s"
757 end
758 end
759 end
760 fmt = string_gsub(fmt, "(%%*)%%([%d%.%-%+%# ]*)(%a)", adjust_fmt)
761 return string_format(fmt, unpack(args, 1, n))
762 end
763 end
764 end
765
766
767 function M.io.write(...)
768 local res, msg, errno = io_write(...)
769 if res then
770 return io_output()
771 else
772 return nil, msg, errno
773 end
774 end
775
776 if not is_luajit then
777 local function helper(st, var_1, ...)
778 if var_1 == nil then
779 if st.doclose then st.f:close() end
780 if (...) ~= nil then
781 error((...), 2)
782 end
783 end
784 return var_1, ...
785 end
786
787 local function lines_iterator(st)
788 return helper(st, st.f:read(unpack(st, 1, st.n)))
789 end
790
791 function M.io.lines(fname, ...)
792 local doclose, file, msg
793 if fname ~= nil then
794 doclose, file, msg = true, io_open(fname, "r")
795 if not file then error(msg, 2) end
796 else
797 doclose, file = false, io_input()
798 end
799 local st = { f=file, doclose=doclose, n=select('#', ...), ... }
800 for i = 1, st.n do
801 local t = type(st[i])
802 if t == "string" then
803 local fmt = st[i]:match("^%*?([aln])")
804 if not fmt then
805 error("bad argument #"..(i+1).." to 'for iterator' (invalid format)", 2)
806 end
807 st[i] = "*"..fmt
808 elseif t ~= "number" then
809 error("bad argument #"..(i+1).." to 'for iterator' (invalid format)", 2)
810 end
811 end
812 return lines_iterator, st
813 end
814 end -- not luajit
815
816 end -- lua 5.1
817
818 -- further write should be forwarded to _G
819 M_meta.__newindex = _G
820
821end -- lua < 5.3
822
823
824-- return module table
825return M
826
827-- vi: set expandtab softtabstop=3 shiftwidth=3 :
diff --git a/vendor/compat53/lprefix.h b/vendor/compat53/lprefix.h
new file mode 100644
index 0000000..0eb149f
--- /dev/null
+++ b/vendor/compat53/lprefix.h
@@ -0,0 +1,175 @@
1/*
2** $Id: lprefix.h,v 1.2 2014/12/29 16:54:13 roberto Exp $
3** Definitions for Lua code that must come before any other header file
4** See Copyright Notice in lua.h
5*/
6
7#ifndef lprefix_h
8#define lprefix_h
9
10
11/*
12** Allows POSIX/XSI stuff
13*/
14#if !defined(LUA_USE_C89) /* { */
15
16#if !defined(_XOPEN_SOURCE)
17#define _XOPEN_SOURCE 600
18#elif _XOPEN_SOURCE == 0
19#undef _XOPEN_SOURCE /* use -D_XOPEN_SOURCE=0 to undefine it */
20#endif
21
22/*
23** Allows manipulation of large files in gcc and some other compilers
24*/
25#if !defined(LUA_32BITS) && !defined(_FILE_OFFSET_BITS)
26#define _LARGEFILE_SOURCE 1
27#define _FILE_OFFSET_BITS 64
28#endif
29
30#endif /* } */
31
32
33/*
34** Windows stuff
35*/
36#if defined(_WIN32) /* { */
37
38#if !defined(_CRT_SECURE_NO_WARNINGS)
39#define _CRT_SECURE_NO_WARNINGS /* avoid warnings about ISO C functions */
40#endif
41
42#endif /* } */
43
44
45/* COMPAT53 adaptation */
46#include "c-api/compat-5.3.h"
47
48#undef LUAMOD_API
49#define LUAMOD_API extern
50
51
52#ifdef lutf8lib_c
53# define luaopen_utf8 luaopen_compat53_utf8
54/* we don't support the %U format string of lua_pushfstring!
55 * code below adapted from the Lua 5.3 sources:
56 */
57static const char *compat53_utf8_escape (lua_State* L, long x) {
58 if (x < 0x80) { /* ASCII */
59 char c = (char)x;
60 lua_pushlstring(L, &c, 1);
61 } else {
62 char buff[8] = { 0 };
63 unsigned int mfb = 0x3f;
64 int n = 1;
65 do {
66 buff[8 - (n++)] = (char)(0x80|(x & 0x3f));
67 x >>= 6;
68 mfb >>= 1;
69 } while (x > mfb);
70 buff[8-n] = (char)((~mfb << 1) | x);
71 lua_pushlstring(L, buff+8-n, n);
72 }
73 return lua_tostring(L, -1);
74}
75# define lua_pushfstring(L, fmt, l) \
76 compat53_utf8_escape(L, l)
77#endif
78
79
80#ifdef ltablib_c
81# define luaopen_table luaopen_compat53_table
82# ifndef LUA_MAXINTEGER
83/* conservative estimate: */
84# define LUA_MAXINTEGER INT_MAX
85# endif
86#endif /* ltablib_c */
87
88
89#ifdef lstrlib_c
90#include <locale.h>
91#include <lualib.h>
92/* move the string library open function out of the way (we only take
93 * the string packing functions)!
94 */
95# define luaopen_string luaopen_string_XXX
96/* used in string.format implementation, which we don't use: */
97# ifndef LUA_INTEGER_FRMLEN
98# define LUA_INTEGER_FRMLEN ""
99# define LUA_NUMBER_FRMLEN ""
100# endif
101# ifndef LUA_MININTEGER
102# define LUA_MININTEGER 0
103# endif
104# ifndef LUA_INTEGER_FMT
105# define LUA_INTEGER_FMT "%d"
106# endif
107# ifndef LUAI_UACINT
108# define LUAI_UACINT lua_Integer
109# endif
110/* different Lua 5.3 versions have conflicting variants of this macro
111 * in luaconf.h, there's a fallback implementation in lstrlib.c, and
112 * the macro isn't used for string (un)packing anyway!
113 * */
114# undef lua_number2strx
115# if LUA_VERSION_NUM < 503
116/* lstrlib assumes that lua_Integer and lua_Unsigned have the same
117 * size, so we use the unsigned equivalent of ptrdiff_t! */
118# define lua_Unsigned size_t
119# endif
120# ifndef l_mathlim
121# ifdef LUA_NUMBER_DOUBLE
122# define l_mathlim(n) (DBL_##n)
123# else
124# define l_mathlim(n) (FLT_##n)
125# endif
126# endif
127# ifndef l_mathop
128# ifdef LUA_NUMBER_DOUBLE
129# define l_mathop(op) op
130# else
131# define l_mathop(op) op##f
132# endif
133# endif
134# ifndef lua_getlocaledecpoint
135# define lua_getlocaledecpoint() (localeconv()->decimal_point[0])
136# endif
137# ifndef l_sprintf
138# if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
139# define l_sprintf(s,sz,f,i) (snprintf(s, sz, f, i))
140# else
141# define l_sprintf(s,sz,f,i) ((void)(sz), sprintf(s, f, i))
142# endif
143# endif
144
145static int str_pack (lua_State *L);
146static int str_packsize (lua_State *L);
147static int str_unpack (lua_State *L);
148LUAMOD_API int luaopen_compat53_string (lua_State *L) {
149 luaL_Reg const funcs[] = {
150 { "pack", str_pack },
151 { "packsize", str_packsize },
152 { "unpack", str_unpack },
153 { NULL, NULL }
154 };
155 luaL_newlib(L, funcs);
156 return 1;
157}
158/* fake CLANG feature detection on other compilers */
159# ifndef __has_attribute
160# define __has_attribute(x) 0
161# endif
162/* make luaopen_string(_XXX) static, so it (and all other referenced
163 * string functions) won't be included in the resulting dll
164 * (hopefully).
165 */
166# undef LUAMOD_API
167# if defined(__GNUC__) || __has_attribute(__unused__)
168# define LUAMOD_API __attribute__((__unused__)) static
169# else
170# define LUAMOD_API static
171# endif
172#endif /* lstrlib.c */
173
174#endif
175
diff --git a/vendor/compat53/lstrlib.c b/vendor/compat53/lstrlib.c
new file mode 100644
index 0000000..c7aa755
--- /dev/null
+++ b/vendor/compat53/lstrlib.c
@@ -0,0 +1,1584 @@
1/*
2** $Id: lstrlib.c,v 1.254 2016/12/22 13:08:50 roberto Exp $
3** Standard library for string operations and pattern-matching
4** See Copyright Notice in lua.h
5*/
6
7#define lstrlib_c
8#define LUA_LIB
9
10#include "lprefix.h"
11
12
13#include <ctype.h>
14#include <float.h>
15#include <limits.h>
16#include <locale.h>
17#include <stddef.h>
18#include <stdio.h>
19#include <stdlib.h>
20#include <string.h>
21
22#include "lua.h"
23
24#include "lauxlib.h"
25#include "lualib.h"
26
27
28/*
29** maximum number of captures that a pattern can do during
30** pattern-matching. This limit is arbitrary, but must fit in
31** an unsigned char.
32*/
33#if !defined(LUA_MAXCAPTURES)
34#define LUA_MAXCAPTURES 32
35#endif
36
37
38/* macro to 'unsign' a character */
39#define uchar(c) ((unsigned char)(c))
40
41
42/*
43** Some sizes are better limited to fit in 'int', but must also fit in
44** 'size_t'. (We assume that 'lua_Integer' cannot be smaller than 'int'.)
45*/
46#define MAX_SIZET ((size_t)(~(size_t)0))
47
48#define MAXSIZE \
49 (sizeof(size_t) < sizeof(int) ? MAX_SIZET : (size_t)(INT_MAX))
50
51
52
53
54static int str_len (lua_State *L) {
55 size_t l;
56 luaL_checklstring(L, 1, &l);
57 lua_pushinteger(L, (lua_Integer)l);
58 return 1;
59}
60
61
62/* translate a relative string position: negative means back from end */
63static lua_Integer posrelat (lua_Integer pos, size_t len) {
64 if (pos >= 0) return pos;
65 else if (0u - (size_t)pos > len) return 0;
66 else return (lua_Integer)len + pos + 1;
67}
68
69
70static int str_sub (lua_State *L) {
71 size_t l;
72 const char *s = luaL_checklstring(L, 1, &l);
73 lua_Integer start = posrelat(luaL_checkinteger(L, 2), l);
74 lua_Integer end = posrelat(luaL_optinteger(L, 3, -1), l);
75 if (start < 1) start = 1;
76 if (end > (lua_Integer)l) end = l;
77 if (start <= end)
78 lua_pushlstring(L, s + start - 1, (size_t)(end - start) + 1);
79 else lua_pushliteral(L, "");
80 return 1;
81}
82
83
84static int str_reverse (lua_State *L) {
85 size_t l, i;
86 luaL_Buffer b;
87 const char *s = luaL_checklstring(L, 1, &l);
88 char *p = luaL_buffinitsize(L, &b, l);
89 for (i = 0; i < l; i++)
90 p[i] = s[l - i - 1];
91 luaL_pushresultsize(&b, l);
92 return 1;
93}
94
95
96static int str_lower (lua_State *L) {
97 size_t l;
98 size_t i;
99 luaL_Buffer b;
100 const char *s = luaL_checklstring(L, 1, &l);
101 char *p = luaL_buffinitsize(L, &b, l);
102 for (i=0; i<l; i++)
103 p[i] = tolower(uchar(s[i]));
104 luaL_pushresultsize(&b, l);
105 return 1;
106}
107
108
109static int str_upper (lua_State *L) {
110 size_t l;
111 size_t i;
112 luaL_Buffer b;
113 const char *s = luaL_checklstring(L, 1, &l);
114 char *p = luaL_buffinitsize(L, &b, l);
115 for (i=0; i<l; i++)
116 p[i] = toupper(uchar(s[i]));
117 luaL_pushresultsize(&b, l);
118 return 1;
119}
120
121
122static int str_rep (lua_State *L) {
123 size_t l, lsep;
124 const char *s = luaL_checklstring(L, 1, &l);
125 lua_Integer n = luaL_checkinteger(L, 2);
126 const char *sep = luaL_optlstring(L, 3, "", &lsep);
127 if (n <= 0) lua_pushliteral(L, "");
128 else if (l + lsep < l || l + lsep > MAXSIZE / n) /* may overflow? */
129 return luaL_error(L, "resulting string too large");
130 else {
131 size_t totallen = (size_t)n * l + (size_t)(n - 1) * lsep;
132 luaL_Buffer b;
133 char *p = luaL_buffinitsize(L, &b, totallen);
134 while (n-- > 1) { /* first n-1 copies (followed by separator) */
135 memcpy(p, s, l * sizeof(char)); p += l;
136 if (lsep > 0) { /* empty 'memcpy' is not that cheap */
137 memcpy(p, sep, lsep * sizeof(char));
138 p += lsep;
139 }
140 }
141 memcpy(p, s, l * sizeof(char)); /* last copy (not followed by separator) */
142 luaL_pushresultsize(&b, totallen);
143 }
144 return 1;
145}
146
147
148static int str_byte (lua_State *L) {
149 size_t l;
150 const char *s = luaL_checklstring(L, 1, &l);
151 lua_Integer posi = posrelat(luaL_optinteger(L, 2, 1), l);
152 lua_Integer pose = posrelat(luaL_optinteger(L, 3, posi), l);
153 int n, i;
154 if (posi < 1) posi = 1;
155 if (pose > (lua_Integer)l) pose = l;
156 if (posi > pose) return 0; /* empty interval; return no values */
157 if (pose - posi >= INT_MAX) /* arithmetic overflow? */
158 return luaL_error(L, "string slice too long");
159 n = (int)(pose - posi) + 1;
160 luaL_checkstack(L, n, "string slice too long");
161 for (i=0; i<n; i++)
162 lua_pushinteger(L, uchar(s[posi+i-1]));
163 return n;
164}
165
166
167static int str_char (lua_State *L) {
168 int n = lua_gettop(L); /* number of arguments */
169 int i;
170 luaL_Buffer b;
171 char *p = luaL_buffinitsize(L, &b, n);
172 for (i=1; i<=n; i++) {
173 lua_Integer c = luaL_checkinteger(L, i);
174 luaL_argcheck(L, uchar(c) == c, i, "value out of range");
175 p[i - 1] = uchar(c);
176 }
177 luaL_pushresultsize(&b, n);
178 return 1;
179}
180
181
182static int writer (lua_State *L, const void *b, size_t size, void *B) {
183 (void)L;
184 luaL_addlstring((luaL_Buffer *) B, (const char *)b, size);
185 return 0;
186}
187
188
189static int str_dump (lua_State *L) {
190 luaL_Buffer b;
191 int strip = lua_toboolean(L, 2);
192 luaL_checktype(L, 1, LUA_TFUNCTION);
193 lua_settop(L, 1);
194 luaL_buffinit(L,&b);
195 if (lua_dump(L, writer, &b, strip) != 0)
196 return luaL_error(L, "unable to dump given function");
197 luaL_pushresult(&b);
198 return 1;
199}
200
201
202
203/*
204** {======================================================
205** PATTERN MATCHING
206** =======================================================
207*/
208
209
210#define CAP_UNFINISHED (-1)
211#define CAP_POSITION (-2)
212
213
214typedef struct MatchState {
215 const char *src_init; /* init of source string */
216 const char *src_end; /* end ('\0') of source string */
217 const char *p_end; /* end ('\0') of pattern */
218 lua_State *L;
219 int matchdepth; /* control for recursive depth (to avoid C stack overflow) */
220 unsigned char level; /* total number of captures (finished or unfinished) */
221 struct {
222 const char *init;
223 ptrdiff_t len;
224 } capture[LUA_MAXCAPTURES];
225} MatchState;
226
227
228/* recursive function */
229static const char *match (MatchState *ms, const char *s, const char *p);
230
231
232/* maximum recursion depth for 'match' */
233#if !defined(MAXCCALLS)
234#define MAXCCALLS 200
235#endif
236
237
238#define L_ESC '%'
239#define SPECIALS "^$*+?.([%-"
240
241
242static int check_capture (MatchState *ms, int l) {
243 l -= '1';
244 if (l < 0 || l >= ms->level || ms->capture[l].len == CAP_UNFINISHED)
245 return luaL_error(ms->L, "invalid capture index %%%d", l + 1);
246 return l;
247}
248
249
250static int capture_to_close (MatchState *ms) {
251 int level = ms->level;
252 for (level--; level>=0; level--)
253 if (ms->capture[level].len == CAP_UNFINISHED) return level;
254 return luaL_error(ms->L, "invalid pattern capture");
255}
256
257
258static const char *classend (MatchState *ms, const char *p) {
259 switch (*p++) {
260 case L_ESC: {
261 if (p == ms->p_end)
262 luaL_error(ms->L, "malformed pattern (ends with '%%')");
263 return p+1;
264 }
265 case '[': {
266 if (*p == '^') p++;
267 do { /* look for a ']' */
268 if (p == ms->p_end)
269 luaL_error(ms->L, "malformed pattern (missing ']')");
270 if (*(p++) == L_ESC && p < ms->p_end)
271 p++; /* skip escapes (e.g. '%]') */
272 } while (*p != ']');
273 return p+1;
274 }
275 default: {
276 return p;
277 }
278 }
279}
280
281
282static int match_class (int c, int cl) {
283 int res;
284 switch (tolower(cl)) {
285 case 'a' : res = isalpha(c); break;
286 case 'c' : res = iscntrl(c); break;
287 case 'd' : res = isdigit(c); break;
288 case 'g' : res = isgraph(c); break;
289 case 'l' : res = islower(c); break;
290 case 'p' : res = ispunct(c); break;
291 case 's' : res = isspace(c); break;
292 case 'u' : res = isupper(c); break;
293 case 'w' : res = isalnum(c); break;
294 case 'x' : res = isxdigit(c); break;
295 case 'z' : res = (c == 0); break; /* deprecated option */
296 default: return (cl == c);
297 }
298 return (islower(cl) ? res : !res);
299}
300
301
302static int matchbracketclass (int c, const char *p, const char *ec) {
303 int sig = 1;
304 if (*(p+1) == '^') {
305 sig = 0;
306 p++; /* skip the '^' */
307 }
308 while (++p < ec) {
309 if (*p == L_ESC) {
310 p++;
311 if (match_class(c, uchar(*p)))
312 return sig;
313 }
314 else if ((*(p+1) == '-') && (p+2 < ec)) {
315 p+=2;
316 if (uchar(*(p-2)) <= c && c <= uchar(*p))
317 return sig;
318 }
319 else if (uchar(*p) == c) return sig;
320 }
321 return !sig;
322}
323
324
325static int singlematch (MatchState *ms, const char *s, const char *p,
326 const char *ep) {
327 if (s >= ms->src_end)
328 return 0;
329 else {
330 int c = uchar(*s);
331 switch (*p) {
332 case '.': return 1; /* matches any char */
333 case L_ESC: return match_class(c, uchar(*(p+1)));
334 case '[': return matchbracketclass(c, p, ep-1);
335 default: return (uchar(*p) == c);
336 }
337 }
338}
339
340
341static const char *matchbalance (MatchState *ms, const char *s,
342 const char *p) {
343 if (p >= ms->p_end - 1)
344 luaL_error(ms->L, "malformed pattern (missing arguments to '%%b')");
345 if (*s != *p) return NULL;
346 else {
347 int b = *p;
348 int e = *(p+1);
349 int cont = 1;
350 while (++s < ms->src_end) {
351 if (*s == e) {
352 if (--cont == 0) return s+1;
353 }
354 else if (*s == b) cont++;
355 }
356 }
357 return NULL; /* string ends out of balance */
358}
359
360
361static const char *max_expand (MatchState *ms, const char *s,
362 const char *p, const char *ep) {
363 ptrdiff_t i = 0; /* counts maximum expand for item */
364 while (singlematch(ms, s + i, p, ep))
365 i++;
366 /* keeps trying to match with the maximum repetitions */
367 while (i>=0) {
368 const char *res = match(ms, (s+i), ep+1);
369 if (res) return res;
370 i--; /* else didn't match; reduce 1 repetition to try again */
371 }
372 return NULL;
373}
374
375
376static const char *min_expand (MatchState *ms, const char *s,
377 const char *p, const char *ep) {
378 for (;;) {
379 const char *res = match(ms, s, ep+1);
380 if (res != NULL)
381 return res;
382 else if (singlematch(ms, s, p, ep))
383 s++; /* try with one more repetition */
384 else return NULL;
385 }
386}
387
388
389static const char *start_capture (MatchState *ms, const char *s,
390 const char *p, int what) {
391 const char *res;
392 int level = ms->level;
393 if (level >= LUA_MAXCAPTURES) luaL_error(ms->L, "too many captures");
394 ms->capture[level].init = s;
395 ms->capture[level].len = what;
396 ms->level = level+1;
397 if ((res=match(ms, s, p)) == NULL) /* match failed? */
398 ms->level--; /* undo capture */
399 return res;
400}
401
402
403static const char *end_capture (MatchState *ms, const char *s,
404 const char *p) {
405 int l = capture_to_close(ms);
406 const char *res;
407 ms->capture[l].len = s - ms->capture[l].init; /* close capture */
408 if ((res = match(ms, s, p)) == NULL) /* match failed? */
409 ms->capture[l].len = CAP_UNFINISHED; /* undo capture */
410 return res;
411}
412
413
414static const char *match_capture (MatchState *ms, const char *s, int l) {
415 size_t len;
416 l = check_capture(ms, l);
417 len = ms->capture[l].len;
418 if ((size_t)(ms->src_end-s) >= len &&
419 memcmp(ms->capture[l].init, s, len) == 0)
420 return s+len;
421 else return NULL;
422}
423
424
425static const char *match (MatchState *ms, const char *s, const char *p) {
426 if (ms->matchdepth-- == 0)
427 luaL_error(ms->L, "pattern too complex");
428 init: /* using goto's to optimize tail recursion */
429 if (p != ms->p_end) { /* end of pattern? */
430 switch (*p) {
431 case '(': { /* start capture */
432 if (*(p + 1) == ')') /* position capture? */
433 s = start_capture(ms, s, p + 2, CAP_POSITION);
434 else
435 s = start_capture(ms, s, p + 1, CAP_UNFINISHED);
436 break;
437 }
438 case ')': { /* end capture */
439 s = end_capture(ms, s, p + 1);
440 break;
441 }
442 case '$': {
443 if ((p + 1) != ms->p_end) /* is the '$' the last char in pattern? */
444 goto dflt; /* no; go to default */
445 s = (s == ms->src_end) ? s : NULL; /* check end of string */
446 break;
447 }
448 case L_ESC: { /* escaped sequences not in the format class[*+?-]? */
449 switch (*(p + 1)) {
450 case 'b': { /* balanced string? */
451 s = matchbalance(ms, s, p + 2);
452 if (s != NULL) {
453 p += 4; goto init; /* return match(ms, s, p + 4); */
454 } /* else fail (s == NULL) */
455 break;
456 }
457 case 'f': { /* frontier? */
458 const char *ep; char previous;
459 p += 2;
460 if (*p != '[')
461 luaL_error(ms->L, "missing '[' after '%%f' in pattern");
462 ep = classend(ms, p); /* points to what is next */
463 previous = (s == ms->src_init) ? '\0' : *(s - 1);
464 if (!matchbracketclass(uchar(previous), p, ep - 1) &&
465 matchbracketclass(uchar(*s), p, ep - 1)) {
466 p = ep; goto init; /* return match(ms, s, ep); */
467 }
468 s = NULL; /* match failed */
469 break;
470 }
471 case '0': case '1': case '2': case '3':
472 case '4': case '5': case '6': case '7':
473 case '8': case '9': { /* capture results (%0-%9)? */
474 s = match_capture(ms, s, uchar(*(p + 1)));
475 if (s != NULL) {
476 p += 2; goto init; /* return match(ms, s, p + 2) */
477 }
478 break;
479 }
480 default: goto dflt;
481 }
482 break;
483 }
484 default: dflt: { /* pattern class plus optional suffix */
485 const char *ep = classend(ms, p); /* points to optional suffix */
486 /* does not match at least once? */
487 if (!singlematch(ms, s, p, ep)) {
488 if (*ep == '*' || *ep == '?' || *ep == '-') { /* accept empty? */
489 p = ep + 1; goto init; /* return match(ms, s, ep + 1); */
490 }
491 else /* '+' or no suffix */
492 s = NULL; /* fail */
493 }
494 else { /* matched once */
495 switch (*ep) { /* handle optional suffix */
496 case '?': { /* optional */
497 const char *res;
498 if ((res = match(ms, s + 1, ep + 1)) != NULL)
499 s = res;
500 else {
501 p = ep + 1; goto init; /* else return match(ms, s, ep + 1); */
502 }
503 break;
504 }
505 case '+': /* 1 or more repetitions */
506 s++; /* 1 match already done */
507 /* FALLTHROUGH */
508 case '*': /* 0 or more repetitions */
509 s = max_expand(ms, s, p, ep);
510 break;
511 case '-': /* 0 or more repetitions (minimum) */
512 s = min_expand(ms, s, p, ep);
513 break;
514 default: /* no suffix */
515 s++; p = ep; goto init; /* return match(ms, s + 1, ep); */
516 }
517 }
518 break;
519 }
520 }
521 }
522 ms->matchdepth++;
523 return s;
524}
525
526
527
528static const char *lmemfind (const char *s1, size_t l1,
529 const char *s2, size_t l2) {
530 if (l2 == 0) return s1; /* empty strings are everywhere */
531 else if (l2 > l1) return NULL; /* avoids a negative 'l1' */
532 else {
533 const char *init; /* to search for a '*s2' inside 's1' */
534 l2--; /* 1st char will be checked by 'memchr' */
535 l1 = l1-l2; /* 's2' cannot be found after that */
536 while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) {
537 init++; /* 1st char is already checked */
538 if (memcmp(init, s2+1, l2) == 0)
539 return init-1;
540 else { /* correct 'l1' and 's1' to try again */
541 l1 -= init-s1;
542 s1 = init;
543 }
544 }
545 return NULL; /* not found */
546 }
547}
548
549
550static void push_onecapture (MatchState *ms, int i, const char *s,
551 const char *e) {
552 if (i >= ms->level) {
553 if (i == 0) /* ms->level == 0, too */
554 lua_pushlstring(ms->L, s, e - s); /* add whole match */
555 else
556 luaL_error(ms->L, "invalid capture index %%%d", i + 1);
557 }
558 else {
559 ptrdiff_t l = ms->capture[i].len;
560 if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture");
561 if (l == CAP_POSITION)
562 lua_pushinteger(ms->L, (ms->capture[i].init - ms->src_init) + 1);
563 else
564 lua_pushlstring(ms->L, ms->capture[i].init, l);
565 }
566}
567
568
569static int push_captures (MatchState *ms, const char *s, const char *e) {
570 int i;
571 int nlevels = (ms->level == 0 && s) ? 1 : ms->level;
572 luaL_checkstack(ms->L, nlevels, "too many captures");
573 for (i = 0; i < nlevels; i++)
574 push_onecapture(ms, i, s, e);
575 return nlevels; /* number of strings pushed */
576}
577
578
579/* check whether pattern has no special characters */
580static int nospecials (const char *p, size_t l) {
581 size_t upto = 0;
582 do {
583 if (strpbrk(p + upto, SPECIALS))
584 return 0; /* pattern has a special character */
585 upto += strlen(p + upto) + 1; /* may have more after \0 */
586 } while (upto <= l);
587 return 1; /* no special chars found */
588}
589
590
591static void prepstate (MatchState *ms, lua_State *L,
592 const char *s, size_t ls, const char *p, size_t lp) {
593 ms->L = L;
594 ms->matchdepth = MAXCCALLS;
595 ms->src_init = s;
596 ms->src_end = s + ls;
597 ms->p_end = p + lp;
598}
599
600
601static void reprepstate (MatchState *ms) {
602 ms->level = 0;
603 lua_assert(ms->matchdepth == MAXCCALLS);
604}
605
606
607static int str_find_aux (lua_State *L, int find) {
608 size_t ls, lp;
609 const char *s = luaL_checklstring(L, 1, &ls);
610 const char *p = luaL_checklstring(L, 2, &lp);
611 lua_Integer init = posrelat(luaL_optinteger(L, 3, 1), ls);
612 if (init < 1) init = 1;
613 else if (init > (lua_Integer)ls + 1) { /* start after string's end? */
614 lua_pushnil(L); /* cannot find anything */
615 return 1;
616 }
617 /* explicit request or no special characters? */
618 if (find && (lua_toboolean(L, 4) || nospecials(p, lp))) {
619 /* do a plain search */
620 const char *s2 = lmemfind(s + init - 1, ls - (size_t)init + 1, p, lp);
621 if (s2) {
622 lua_pushinteger(L, (s2 - s) + 1);
623 lua_pushinteger(L, (s2 - s) + lp);
624 return 2;
625 }
626 }
627 else {
628 MatchState ms;
629 const char *s1 = s + init - 1;
630 int anchor = (*p == '^');
631 if (anchor) {
632 p++; lp--; /* skip anchor character */
633 }
634 prepstate(&ms, L, s, ls, p, lp);
635 do {
636 const char *res;
637 reprepstate(&ms);
638 if ((res=match(&ms, s1, p)) != NULL) {
639 if (find) {
640 lua_pushinteger(L, (s1 - s) + 1); /* start */
641 lua_pushinteger(L, res - s); /* end */
642 return push_captures(&ms, NULL, 0) + 2;
643 }
644 else
645 return push_captures(&ms, s1, res);
646 }
647 } while (s1++ < ms.src_end && !anchor);
648 }
649 lua_pushnil(L); /* not found */
650 return 1;
651}
652
653
654static int str_find (lua_State *L) {
655 return str_find_aux(L, 1);
656}
657
658
659static int str_match (lua_State *L) {
660 return str_find_aux(L, 0);
661}
662
663
664/* state for 'gmatch' */
665typedef struct GMatchState {
666 const char *src; /* current position */
667 const char *p; /* pattern */
668 const char *lastmatch; /* end of last match */
669 MatchState ms; /* match state */
670} GMatchState;
671
672
673static int gmatch_aux (lua_State *L) {
674 GMatchState *gm = (GMatchState *)lua_touserdata(L, lua_upvalueindex(3));
675 const char *src;
676 gm->ms.L = L;
677 for (src = gm->src; src <= gm->ms.src_end; src++) {
678 const char *e;
679 reprepstate(&gm->ms);
680 if ((e = match(&gm->ms, src, gm->p)) != NULL && e != gm->lastmatch) {
681 gm->src = gm->lastmatch = e;
682 return push_captures(&gm->ms, src, e);
683 }
684 }
685 return 0; /* not found */
686}
687
688
689static int gmatch (lua_State *L) {
690 size_t ls, lp;
691 const char *s = luaL_checklstring(L, 1, &ls);
692 const char *p = luaL_checklstring(L, 2, &lp);
693 GMatchState *gm;
694 lua_settop(L, 2); /* keep them on closure to avoid being collected */
695 gm = (GMatchState *)lua_newuserdata(L, sizeof(GMatchState));
696 prepstate(&gm->ms, L, s, ls, p, lp);
697 gm->src = s; gm->p = p; gm->lastmatch = NULL;
698 lua_pushcclosure(L, gmatch_aux, 3);
699 return 1;
700}
701
702
703static void add_s (MatchState *ms, luaL_Buffer *b, const char *s,
704 const char *e) {
705 size_t l, i;
706 lua_State *L = ms->L;
707 const char *news = lua_tolstring(L, 3, &l);
708 for (i = 0; i < l; i++) {
709 if (news[i] != L_ESC)
710 luaL_addchar(b, news[i]);
711 else {
712 i++; /* skip ESC */
713 if (!isdigit(uchar(news[i]))) {
714 if (news[i] != L_ESC)
715 luaL_error(L, "invalid use of '%c' in replacement string", L_ESC);
716 luaL_addchar(b, news[i]);
717 }
718 else if (news[i] == '0')
719 luaL_addlstring(b, s, e - s);
720 else {
721 push_onecapture(ms, news[i] - '1', s, e);
722 luaL_tolstring(L, -1, NULL); /* if number, convert it to string */
723 lua_remove(L, -2); /* remove original value */
724 luaL_addvalue(b); /* add capture to accumulated result */
725 }
726 }
727 }
728}
729
730
731static void add_value (MatchState *ms, luaL_Buffer *b, const char *s,
732 const char *e, int tr) {
733 lua_State *L = ms->L;
734 switch (tr) {
735 case LUA_TFUNCTION: {
736 int n;
737 lua_pushvalue(L, 3);
738 n = push_captures(ms, s, e);
739 lua_call(L, n, 1);
740 break;
741 }
742 case LUA_TTABLE: {
743 push_onecapture(ms, 0, s, e);
744 lua_gettable(L, 3);
745 break;
746 }
747 default: { /* LUA_TNUMBER or LUA_TSTRING */
748 add_s(ms, b, s, e);
749 return;
750 }
751 }
752 if (!lua_toboolean(L, -1)) { /* nil or false? */
753 lua_pop(L, 1);
754 lua_pushlstring(L, s, e - s); /* keep original text */
755 }
756 else if (!lua_isstring(L, -1))
757 luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1));
758 luaL_addvalue(b); /* add result to accumulator */
759}
760
761
762static int str_gsub (lua_State *L) {
763 size_t srcl, lp;
764 const char *src = luaL_checklstring(L, 1, &srcl); /* subject */
765 const char *p = luaL_checklstring(L, 2, &lp); /* pattern */
766 const char *lastmatch = NULL; /* end of last match */
767 int tr = lua_type(L, 3); /* replacement type */
768 lua_Integer max_s = luaL_optinteger(L, 4, srcl + 1); /* max replacements */
769 int anchor = (*p == '^');
770 lua_Integer n = 0; /* replacement count */
771 MatchState ms;
772 luaL_Buffer b;
773 luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING ||
774 tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3,
775 "string/function/table expected");
776 luaL_buffinit(L, &b);
777 if (anchor) {
778 p++; lp--; /* skip anchor character */
779 }
780 prepstate(&ms, L, src, srcl, p, lp);
781 while (n < max_s) {
782 const char *e;
783 reprepstate(&ms); /* (re)prepare state for new match */
784 if ((e = match(&ms, src, p)) != NULL && e != lastmatch) { /* match? */
785 n++;
786 add_value(&ms, &b, src, e, tr); /* add replacement to buffer */
787 src = lastmatch = e;
788 }
789 else if (src < ms.src_end) /* otherwise, skip one character */
790 luaL_addchar(&b, *src++);
791 else break; /* end of subject */
792 if (anchor) break;
793 }
794 luaL_addlstring(&b, src, ms.src_end-src);
795 luaL_pushresult(&b);
796 lua_pushinteger(L, n); /* number of substitutions */
797 return 2;
798}
799
800/* }====================================================== */
801
802
803
804/*
805** {======================================================
806** STRING FORMAT
807** =======================================================
808*/
809
810#if !defined(lua_number2strx) /* { */
811
812/*
813** Hexadecimal floating-point formatter
814*/
815
816#include <math.h>
817
818#define SIZELENMOD (sizeof(LUA_NUMBER_FRMLEN)/sizeof(char))
819
820
821/*
822** Number of bits that goes into the first digit. It can be any value
823** between 1 and 4; the following definition tries to align the number
824** to nibble boundaries by making what is left after that first digit a
825** multiple of 4.
826*/
827#define L_NBFD ((l_mathlim(MANT_DIG) - 1)%4 + 1)
828
829
830/*
831** Add integer part of 'x' to buffer and return new 'x'
832*/
833static lua_Number adddigit (char *buff, int n, lua_Number x) {
834 lua_Number dd = l_mathop(floor)(x); /* get integer part from 'x' */
835 int d = (int)dd;
836 buff[n] = (d < 10 ? d + '0' : d - 10 + 'a'); /* add to buffer */
837 return x - dd; /* return what is left */
838}
839
840
841static int num2straux (char *buff, int sz, lua_Number x) {
842 /* if 'inf' or 'NaN', format it like '%g' */
843 if (x != x || x == (lua_Number)HUGE_VAL || x == -(lua_Number)HUGE_VAL)
844 return l_sprintf(buff, sz, LUA_NUMBER_FMT, (LUAI_UACNUMBER)x);
845 else if (x == 0) { /* can be -0... */
846 /* create "0" or "-0" followed by exponent */
847 return l_sprintf(buff, sz, LUA_NUMBER_FMT "x0p+0", (LUAI_UACNUMBER)x);
848 }
849 else {
850 int e;
851 lua_Number m = l_mathop(frexp)(x, &e); /* 'x' fraction and exponent */
852 int n = 0; /* character count */
853 if (m < 0) { /* is number negative? */
854 buff[n++] = '-'; /* add signal */
855 m = -m; /* make it positive */
856 }
857 buff[n++] = '0'; buff[n++] = 'x'; /* add "0x" */
858 m = adddigit(buff, n++, m * (1 << L_NBFD)); /* add first digit */
859 e -= L_NBFD; /* this digit goes before the radix point */
860 if (m > 0) { /* more digits? */
861 buff[n++] = lua_getlocaledecpoint(); /* add radix point */
862 do { /* add as many digits as needed */
863 m = adddigit(buff, n++, m * 16);
864 } while (m > 0);
865 }
866 n += l_sprintf(buff + n, sz - n, "p%+d", e); /* add exponent */
867 lua_assert(n < sz);
868 return n;
869 }
870}
871
872
873static int lua_number2strx (lua_State *L, char *buff, int sz,
874 const char *fmt, lua_Number x) {
875 int n = num2straux(buff, sz, x);
876 if (fmt[SIZELENMOD] == 'A') {
877 int i;
878 for (i = 0; i < n; i++)
879 buff[i] = toupper(uchar(buff[i]));
880 }
881 else if (fmt[SIZELENMOD] != 'a')
882 luaL_error(L, "modifiers for format '%%a'/'%%A' not implemented");
883 return n;
884}
885
886#endif /* } */
887
888
889/*
890** Maximum size of each formatted item. This maximum size is produced
891** by format('%.99f', -maxfloat), and is equal to 99 + 3 ('-', '.',
892** and '\0') + number of decimal digits to represent maxfloat (which
893** is maximum exponent + 1). (99+3+1 then rounded to 120 for "extra
894** expenses", such as locale-dependent stuff)
895*/
896#define MAX_ITEM (120 + l_mathlim(MAX_10_EXP))
897
898
899/* valid flags in a format specification */
900#define FLAGS "-+ #0"
901
902/*
903** maximum size of each format specification (such as "%-099.99d")
904*/
905#define MAX_FORMAT 32
906
907
908static void addquoted (luaL_Buffer *b, const char *s, size_t len) {
909 luaL_addchar(b, '"');
910 while (len--) {
911 if (*s == '"' || *s == '\\' || *s == '\n') {
912 luaL_addchar(b, '\\');
913 luaL_addchar(b, *s);
914 }
915 else if (iscntrl(uchar(*s))) {
916 char buff[10];
917 if (!isdigit(uchar(*(s+1))))
918 l_sprintf(buff, sizeof(buff), "\\%d", (int)uchar(*s));
919 else
920 l_sprintf(buff, sizeof(buff), "\\%03d", (int)uchar(*s));
921 luaL_addstring(b, buff);
922 }
923 else
924 luaL_addchar(b, *s);
925 s++;
926 }
927 luaL_addchar(b, '"');
928}
929
930
931/*
932** Ensures the 'buff' string uses a dot as the radix character.
933*/
934static void checkdp (char *buff, int nb) {
935 if (memchr(buff, '.', nb) == NULL) { /* no dot? */
936 char point = lua_getlocaledecpoint(); /* try locale point */
937 char *ppoint = (char *)memchr(buff, point, nb);
938 if (ppoint) *ppoint = '.'; /* change it to a dot */
939 }
940}
941
942
943static void addliteral (lua_State *L, luaL_Buffer *b, int arg) {
944 switch (lua_type(L, arg)) {
945 case LUA_TSTRING: {
946 size_t len;
947 const char *s = lua_tolstring(L, arg, &len);
948 addquoted(b, s, len);
949 break;
950 }
951 case LUA_TNUMBER: {
952 char *buff = luaL_prepbuffsize(b, MAX_ITEM);
953 int nb;
954 if (!lua_isinteger(L, arg)) { /* float? */
955 lua_Number n = lua_tonumber(L, arg); /* write as hexa ('%a') */
956 nb = lua_number2strx(L, buff, MAX_ITEM, "%" LUA_NUMBER_FRMLEN "a", n);
957 checkdp(buff, nb); /* ensure it uses a dot */
958 }
959 else { /* integers */
960 lua_Integer n = lua_tointeger(L, arg);
961 const char *format = (n == LUA_MININTEGER) /* corner case? */
962 ? "0x%" LUA_INTEGER_FRMLEN "x" /* use hexa */
963 : LUA_INTEGER_FMT; /* else use default format */
964 nb = l_sprintf(buff, MAX_ITEM, format, (LUAI_UACINT)n);
965 }
966 luaL_addsize(b, nb);
967 break;
968 }
969 case LUA_TNIL: case LUA_TBOOLEAN: {
970 luaL_tolstring(L, arg, NULL);
971 luaL_addvalue(b);
972 break;
973 }
974 default: {
975 luaL_argerror(L, arg, "value has no literal form");
976 }
977 }
978}
979
980
981static const char *scanformat (lua_State *L, const char *strfrmt, char *form) {
982 const char *p = strfrmt;
983 while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */
984 if ((size_t)(p - strfrmt) >= sizeof(FLAGS)/sizeof(char))
985 luaL_error(L, "invalid format (repeated flags)");
986 if (isdigit(uchar(*p))) p++; /* skip width */
987 if (isdigit(uchar(*p))) p++; /* (2 digits at most) */
988 if (*p == '.') {
989 p++;
990 if (isdigit(uchar(*p))) p++; /* skip precision */
991 if (isdigit(uchar(*p))) p++; /* (2 digits at most) */
992 }
993 if (isdigit(uchar(*p)))
994 luaL_error(L, "invalid format (width or precision too long)");
995 *(form++) = '%';
996 memcpy(form, strfrmt, ((p - strfrmt) + 1) * sizeof(char));
997 form += (p - strfrmt) + 1;
998 *form = '\0';
999 return p;
1000}
1001
1002
1003/*
1004** add length modifier into formats
1005*/
1006static void addlenmod (char *form, const char *lenmod) {
1007 size_t l = strlen(form);
1008 size_t lm = strlen(lenmod);
1009 char spec = form[l - 1];
1010 strcpy(form + l - 1, lenmod);
1011 form[l + lm - 1] = spec;
1012 form[l + lm] = '\0';
1013}
1014
1015
1016static int str_format (lua_State *L) {
1017 int top = lua_gettop(L);
1018 int arg = 1;
1019 size_t sfl;
1020 const char *strfrmt = luaL_checklstring(L, arg, &sfl);
1021 const char *strfrmt_end = strfrmt+sfl;
1022 luaL_Buffer b;
1023 luaL_buffinit(L, &b);
1024 while (strfrmt < strfrmt_end) {
1025 if (*strfrmt != L_ESC)
1026 luaL_addchar(&b, *strfrmt++);
1027 else if (*++strfrmt == L_ESC)
1028 luaL_addchar(&b, *strfrmt++); /* %% */
1029 else { /* format item */
1030 char form[MAX_FORMAT]; /* to store the format ('%...') */
1031 char *buff = luaL_prepbuffsize(&b, MAX_ITEM); /* to put formatted item */
1032 int nb = 0; /* number of bytes in added item */
1033 if (++arg > top)
1034 luaL_argerror(L, arg, "no value");
1035 strfrmt = scanformat(L, strfrmt, form);
1036 switch (*strfrmt++) {
1037 case 'c': {
1038 nb = l_sprintf(buff, MAX_ITEM, form, (int)luaL_checkinteger(L, arg));
1039 break;
1040 }
1041 case 'd': case 'i':
1042 case 'o': case 'u': case 'x': case 'X': {
1043 lua_Integer n = luaL_checkinteger(L, arg);
1044 addlenmod(form, LUA_INTEGER_FRMLEN);
1045 nb = l_sprintf(buff, MAX_ITEM, form, (LUAI_UACINT)n);
1046 break;
1047 }
1048 case 'a': case 'A':
1049 addlenmod(form, LUA_NUMBER_FRMLEN);
1050 nb = lua_number2strx(L, buff, MAX_ITEM, form,
1051 luaL_checknumber(L, arg));
1052 break;
1053 case 'e': case 'E': case 'f':
1054 case 'g': case 'G': {
1055 lua_Number n = luaL_checknumber(L, arg);
1056 addlenmod(form, LUA_NUMBER_FRMLEN);
1057 nb = l_sprintf(buff, MAX_ITEM, form, (LUAI_UACNUMBER)n);
1058 break;
1059 }
1060 case 'q': {
1061 addliteral(L, &b, arg);
1062 break;
1063 }
1064 case 's': {
1065 size_t l;
1066 const char *s = luaL_tolstring(L, arg, &l);
1067 if (form[2] == '\0') /* no modifiers? */
1068 luaL_addvalue(&b); /* keep entire string */
1069 else {
1070 luaL_argcheck(L, l == strlen(s), arg, "string contains zeros");
1071 if (!strchr(form, '.') && l >= 100) {
1072 /* no precision and string is too long to be formatted */
1073 luaL_addvalue(&b); /* keep entire string */
1074 }
1075 else { /* format the string into 'buff' */
1076 nb = l_sprintf(buff, MAX_ITEM, form, s);
1077 lua_pop(L, 1); /* remove result from 'luaL_tolstring' */
1078 }
1079 }
1080 break;
1081 }
1082 default: { /* also treat cases 'pnLlh' */
1083 return luaL_error(L, "invalid option '%%%c' to 'format'",
1084 *(strfrmt - 1));
1085 }
1086 }
1087 lua_assert(nb < MAX_ITEM);
1088 luaL_addsize(&b, nb);
1089 }
1090 }
1091 luaL_pushresult(&b);
1092 return 1;
1093}
1094
1095/* }====================================================== */
1096
1097
1098/*
1099** {======================================================
1100** PACK/UNPACK
1101** =======================================================
1102*/
1103
1104
1105/* value used for padding */
1106#if !defined(LUAL_PACKPADBYTE)
1107#define LUAL_PACKPADBYTE 0x00
1108#endif
1109
1110/* maximum size for the binary representation of an integer */
1111#define MAXINTSIZE 16
1112
1113/* number of bits in a character */
1114#define NB CHAR_BIT
1115
1116/* mask for one character (NB 1's) */
1117#define MC ((1 << NB) - 1)
1118
1119/* size of a lua_Integer */
1120#define SZINT ((int)sizeof(lua_Integer))
1121
1122
1123/* dummy union to get native endianness */
1124static const union {
1125 int dummy;
1126 char little; /* true iff machine is little endian */
1127} nativeendian = {1};
1128
1129
1130/* dummy structure to get native alignment requirements */
1131struct cD {
1132 char c;
1133 union { double d; void *p; lua_Integer i; lua_Number n; } u;
1134};
1135
1136#define MAXALIGN (offsetof(struct cD, u))
1137
1138
1139/*
1140** Union for serializing floats
1141*/
1142typedef union Ftypes {
1143 float f;
1144 double d;
1145 lua_Number n;
1146 char buff[5 * sizeof(lua_Number)]; /* enough for any float type */
1147} Ftypes;
1148
1149
1150/*
1151** information to pack/unpack stuff
1152*/
1153typedef struct Header {
1154 lua_State *L;
1155 int islittle;
1156 int maxalign;
1157} Header;
1158
1159
1160/*
1161** options for pack/unpack
1162*/
1163typedef enum KOption {
1164 Kint, /* signed integers */
1165 Kuint, /* unsigned integers */
1166 Kfloat, /* floating-point numbers */
1167 Kchar, /* fixed-length strings */
1168 Kstring, /* strings with prefixed length */
1169 Kzstr, /* zero-terminated strings */
1170 Kpadding, /* padding */
1171 Kpaddalign, /* padding for alignment */
1172 Knop /* no-op (configuration or spaces) */
1173} KOption;
1174
1175
1176/*
1177** Read an integer numeral from string 'fmt' or return 'df' if
1178** there is no numeral
1179*/
1180static int digit (int c) { return '0' <= c && c <= '9'; }
1181
1182static int getnum (const char **fmt, int df) {
1183 if (!digit(**fmt)) /* no number? */
1184 return df; /* return default value */
1185 else {
1186 int a = 0;
1187 do {
1188 a = a*10 + (*((*fmt)++) - '0');
1189 } while (digit(**fmt) && a <= ((int)MAXSIZE - 9)/10);
1190 return a;
1191 }
1192}
1193
1194
1195/*
1196** Read an integer numeral and raises an error if it is larger
1197** than the maximum size for integers.
1198*/
1199static int getnumlimit (Header *h, const char **fmt, int df) {
1200 int sz = getnum(fmt, df);
1201 if (sz > MAXINTSIZE || sz <= 0)
1202 luaL_error(h->L, "integral size (%d) out of limits [1,%d]",
1203 sz, MAXINTSIZE);
1204 return sz;
1205}
1206
1207
1208/*
1209** Initialize Header
1210*/
1211static void initheader (lua_State *L, Header *h) {
1212 h->L = L;
1213 h->islittle = nativeendian.little;
1214 h->maxalign = 1;
1215}
1216
1217
1218/*
1219** Read and classify next option. 'size' is filled with option's size.
1220*/
1221static KOption getoption (Header *h, const char **fmt, int *size) {
1222 int opt = *((*fmt)++);
1223 *size = 0; /* default */
1224 switch (opt) {
1225 case 'b': *size = sizeof(char); return Kint;
1226 case 'B': *size = sizeof(char); return Kuint;
1227 case 'h': *size = sizeof(short); return Kint;
1228 case 'H': *size = sizeof(short); return Kuint;
1229 case 'l': *size = sizeof(long); return Kint;
1230 case 'L': *size = sizeof(long); return Kuint;
1231 case 'j': *size = sizeof(lua_Integer); return Kint;
1232 case 'J': *size = sizeof(lua_Integer); return Kuint;
1233 case 'T': *size = sizeof(size_t); return Kuint;
1234 case 'f': *size = sizeof(float); return Kfloat;
1235 case 'd': *size = sizeof(double); return Kfloat;
1236 case 'n': *size = sizeof(lua_Number); return Kfloat;
1237 case 'i': *size = getnumlimit(h, fmt, sizeof(int)); return Kint;
1238 case 'I': *size = getnumlimit(h, fmt, sizeof(int)); return Kuint;
1239 case 's': *size = getnumlimit(h, fmt, sizeof(size_t)); return Kstring;
1240 case 'c':
1241 *size = getnum(fmt, -1);
1242 if (*size == -1)
1243 luaL_error(h->L, "missing size for format option 'c'");
1244 return Kchar;
1245 case 'z': return Kzstr;
1246 case 'x': *size = 1; return Kpadding;
1247 case 'X': return Kpaddalign;
1248 case ' ': break;
1249 case '<': h->islittle = 1; break;
1250 case '>': h->islittle = 0; break;
1251 case '=': h->islittle = nativeendian.little; break;
1252 case '!': h->maxalign = getnumlimit(h, fmt, MAXALIGN); break;
1253 default: luaL_error(h->L, "invalid format option '%c'", opt);
1254 }
1255 return Knop;
1256}
1257
1258
1259/*
1260** Read, classify, and fill other details about the next option.
1261** 'psize' is filled with option's size, 'notoalign' with its
1262** alignment requirements.
1263** Local variable 'size' gets the size to be aligned. (Kpadal option
1264** always gets its full alignment, other options are limited by
1265** the maximum alignment ('maxalign'). Kchar option needs no alignment
1266** despite its size.
1267*/
1268static KOption getdetails (Header *h, size_t totalsize,
1269 const char **fmt, int *psize, int *ntoalign) {
1270 KOption opt = getoption(h, fmt, psize);
1271 int align = *psize; /* usually, alignment follows size */
1272 if (opt == Kpaddalign) { /* 'X' gets alignment from following option */
1273 if (**fmt == '\0' || getoption(h, fmt, &align) == Kchar || align == 0)
1274 luaL_argerror(h->L, 1, "invalid next option for option 'X'");
1275 }
1276 if (align <= 1 || opt == Kchar) /* need no alignment? */
1277 *ntoalign = 0;
1278 else {
1279 if (align > h->maxalign) /* enforce maximum alignment */
1280 align = h->maxalign;
1281 if ((align & (align - 1)) != 0) /* is 'align' not a power of 2? */
1282 luaL_argerror(h->L, 1, "format asks for alignment not power of 2");
1283 *ntoalign = (align - (int)(totalsize & (align - 1))) & (align - 1);
1284 }
1285 return opt;
1286}
1287
1288
1289/*
1290** Pack integer 'n' with 'size' bytes and 'islittle' endianness.
1291** The final 'if' handles the case when 'size' is larger than
1292** the size of a Lua integer, correcting the extra sign-extension
1293** bytes if necessary (by default they would be zeros).
1294*/
1295static void packint (luaL_Buffer *b, lua_Unsigned n,
1296 int islittle, int size, int neg) {
1297 char *buff = luaL_prepbuffsize(b, size);
1298 int i;
1299 buff[islittle ? 0 : size - 1] = (char)(n & MC); /* first byte */
1300 for (i = 1; i < size; i++) {
1301 n >>= NB;
1302 buff[islittle ? i : size - 1 - i] = (char)(n & MC);
1303 }
1304 if (neg && size > SZINT) { /* negative number need sign extension? */
1305 for (i = SZINT; i < size; i++) /* correct extra bytes */
1306 buff[islittle ? i : size - 1 - i] = (char)MC;
1307 }
1308 luaL_addsize(b, size); /* add result to buffer */
1309}
1310
1311
1312/*
1313** Copy 'size' bytes from 'src' to 'dest', correcting endianness if
1314** given 'islittle' is different from native endianness.
1315*/
1316static void copywithendian (volatile char *dest, volatile const char *src,
1317 int size, int islittle) {
1318 if (islittle == nativeendian.little) {
1319 while (size-- != 0)
1320 *(dest++) = *(src++);
1321 }
1322 else {
1323 dest += size - 1;
1324 while (size-- != 0)
1325 *(dest--) = *(src++);
1326 }
1327}
1328
1329
1330static int str_pack (lua_State *L) {
1331 luaL_Buffer b;
1332 Header h;
1333 const char *fmt = luaL_checkstring(L, 1); /* format string */
1334 int arg = 1; /* current argument to pack */
1335 size_t totalsize = 0; /* accumulate total size of result */
1336 initheader(L, &h);
1337 lua_pushnil(L); /* mark to separate arguments from string buffer */
1338 luaL_buffinit(L, &b);
1339 while (*fmt != '\0') {
1340 int size, ntoalign;
1341 KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign);
1342 totalsize += ntoalign + size;
1343 while (ntoalign-- > 0)
1344 luaL_addchar(&b, LUAL_PACKPADBYTE); /* fill alignment */
1345 arg++;
1346 switch (opt) {
1347 case Kint: { /* signed integers */
1348 lua_Integer n = luaL_checkinteger(L, arg);
1349 if (size < SZINT) { /* need overflow check? */
1350 lua_Integer lim = (lua_Integer)1 << ((size * NB) - 1);
1351 luaL_argcheck(L, -lim <= n && n < lim, arg, "integer overflow");
1352 }
1353 packint(&b, (lua_Unsigned)n, h.islittle, size, (n < 0));
1354 break;
1355 }
1356 case Kuint: { /* unsigned integers */
1357 lua_Integer n = luaL_checkinteger(L, arg);
1358 if (size < SZINT) /* need overflow check? */
1359 luaL_argcheck(L, (lua_Unsigned)n < ((lua_Unsigned)1 << (size * NB)),
1360 arg, "unsigned overflow");
1361 packint(&b, (lua_Unsigned)n, h.islittle, size, 0);
1362 break;
1363 }
1364 case Kfloat: { /* floating-point options */
1365 volatile Ftypes u;
1366 char *buff = luaL_prepbuffsize(&b, size);
1367 lua_Number n = luaL_checknumber(L, arg); /* get argument */
1368 if (size == sizeof(u.f)) u.f = (float)n; /* copy it into 'u' */
1369 else if (size == sizeof(u.d)) u.d = (double)n;
1370 else u.n = n;
1371 /* move 'u' to final result, correcting endianness if needed */
1372 copywithendian(buff, u.buff, size, h.islittle);
1373 luaL_addsize(&b, size);
1374 break;
1375 }
1376 case Kchar: { /* fixed-size string */
1377 size_t len;
1378 const char *s = luaL_checklstring(L, arg, &len);
1379 luaL_argcheck(L, len <= (size_t)size, arg,
1380 "string longer than given size");
1381 luaL_addlstring(&b, s, len); /* add string */
1382 while (len++ < (size_t)size) /* pad extra space */
1383 luaL_addchar(&b, LUAL_PACKPADBYTE);
1384 break;
1385 }
1386 case Kstring: { /* strings with length count */
1387 size_t len;
1388 const char *s = luaL_checklstring(L, arg, &len);
1389 luaL_argcheck(L, size >= (int)sizeof(size_t) ||
1390 len < ((size_t)1 << (size * NB)),
1391 arg, "string length does not fit in given size");
1392 packint(&b, (lua_Unsigned)len, h.islittle, size, 0); /* pack length */
1393 luaL_addlstring(&b, s, len);
1394 totalsize += len;
1395 break;
1396 }
1397 case Kzstr: { /* zero-terminated string */
1398 size_t len;
1399 const char *s = luaL_checklstring(L, arg, &len);
1400 luaL_argcheck(L, strlen(s) == len, arg, "string contains zeros");
1401 luaL_addlstring(&b, s, len);
1402 luaL_addchar(&b, '\0'); /* add zero at the end */
1403 totalsize += len + 1;
1404 break;
1405 }
1406 case Kpadding: luaL_addchar(&b, LUAL_PACKPADBYTE); /* FALLTHROUGH */
1407 case Kpaddalign: case Knop:
1408 arg--; /* undo increment */
1409 break;
1410 }
1411 }
1412 luaL_pushresult(&b);
1413 return 1;
1414}
1415
1416
1417static int str_packsize (lua_State *L) {
1418 Header h;
1419 const char *fmt = luaL_checkstring(L, 1); /* format string */
1420 size_t totalsize = 0; /* accumulate total size of result */
1421 initheader(L, &h);
1422 while (*fmt != '\0') {
1423 int size, ntoalign;
1424 KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign);
1425 size += ntoalign; /* total space used by option */
1426 luaL_argcheck(L, totalsize <= MAXSIZE - size, 1,
1427 "format result too large");
1428 totalsize += size;
1429 switch (opt) {
1430 case Kstring: /* strings with length count */
1431 case Kzstr: /* zero-terminated string */
1432 luaL_argerror(L, 1, "variable-length format");
1433 /* call never return, but to avoid warnings: *//* FALLTHROUGH */
1434 default: break;
1435 }
1436 }
1437 lua_pushinteger(L, (lua_Integer)totalsize);
1438 return 1;
1439}
1440
1441
1442/*
1443** Unpack an integer with 'size' bytes and 'islittle' endianness.
1444** If size is smaller than the size of a Lua integer and integer
1445** is signed, must do sign extension (propagating the sign to the
1446** higher bits); if size is larger than the size of a Lua integer,
1447** it must check the unread bytes to see whether they do not cause an
1448** overflow.
1449*/
1450static lua_Integer unpackint (lua_State *L, const char *str,
1451 int islittle, int size, int issigned) {
1452 lua_Unsigned res = 0;
1453 int i;
1454 int limit = (size <= SZINT) ? size : SZINT;
1455 for (i = limit - 1; i >= 0; i--) {
1456 res <<= NB;
1457 res |= (lua_Unsigned)(unsigned char)str[islittle ? i : size - 1 - i];
1458 }
1459 if (size < SZINT) { /* real size smaller than lua_Integer? */
1460 if (issigned) { /* needs sign extension? */
1461 lua_Unsigned mask = (lua_Unsigned)1 << (size*NB - 1);
1462 res = ((res ^ mask) - mask); /* do sign extension */
1463 }
1464 }
1465 else if (size > SZINT) { /* must check unread bytes */
1466 int mask = (!issigned || (lua_Integer)res >= 0) ? 0 : MC;
1467 for (i = limit; i < size; i++) {
1468 if ((unsigned char)str[islittle ? i : size - 1 - i] != mask)
1469 luaL_error(L, "%d-byte integer does not fit into Lua Integer", size);
1470 }
1471 }
1472 return (lua_Integer)res;
1473}
1474
1475
1476static int str_unpack (lua_State *L) {
1477 Header h;
1478 const char *fmt = luaL_checkstring(L, 1);
1479 size_t ld;
1480 const char *data = luaL_checklstring(L, 2, &ld);
1481 size_t pos = (size_t)posrelat(luaL_optinteger(L, 3, 1), ld) - 1;
1482 int n = 0; /* number of results */
1483 luaL_argcheck(L, pos <= ld, 3, "initial position out of string");
1484 initheader(L, &h);
1485 while (*fmt != '\0') {
1486 int size, ntoalign;
1487 KOption opt = getdetails(&h, pos, &fmt, &size, &ntoalign);
1488 if ((size_t)ntoalign + size > ~pos || pos + ntoalign + size > ld)
1489 luaL_argerror(L, 2, "data string too short");
1490 pos += ntoalign; /* skip alignment */
1491 /* stack space for item + next position */
1492 luaL_checkstack(L, 2, "too many results");
1493 n++;
1494 switch (opt) {
1495 case Kint:
1496 case Kuint: {
1497 lua_Integer res = unpackint(L, data + pos, h.islittle, size,
1498 (opt == Kint));
1499 lua_pushinteger(L, res);
1500 break;
1501 }
1502 case Kfloat: {
1503 volatile Ftypes u;
1504 lua_Number num;
1505 copywithendian(u.buff, data + pos, size, h.islittle);
1506 if (size == sizeof(u.f)) num = (lua_Number)u.f;
1507 else if (size == sizeof(u.d)) num = (lua_Number)u.d;
1508 else num = u.n;
1509 lua_pushnumber(L, num);
1510 break;
1511 }
1512 case Kchar: {
1513 lua_pushlstring(L, data + pos, size);
1514 break;
1515 }
1516 case Kstring: {
1517 size_t len = (size_t)unpackint(L, data + pos, h.islittle, size, 0);
1518 luaL_argcheck(L, pos + len + size <= ld, 2, "data string too short");
1519 lua_pushlstring(L, data + pos + size, len);
1520 pos += len; /* skip string */
1521 break;
1522 }
1523 case Kzstr: {
1524 size_t len = (int)strlen(data + pos);
1525 lua_pushlstring(L, data + pos, len);
1526 pos += len + 1; /* skip string plus final '\0' */
1527 break;
1528 }
1529 case Kpaddalign: case Kpadding: case Knop:
1530 n--; /* undo increment */
1531 break;
1532 }
1533 pos += size;
1534 }
1535 lua_pushinteger(L, pos + 1); /* next position */
1536 return n + 1;
1537}
1538
1539/* }====================================================== */
1540
1541
1542static const luaL_Reg strlib[] = {
1543 {"byte", str_byte},
1544 {"char", str_char},
1545 {"dump", str_dump},
1546 {"find", str_find},
1547 {"format", str_format},
1548 {"gmatch", gmatch},
1549 {"gsub", str_gsub},
1550 {"len", str_len},
1551 {"lower", str_lower},
1552 {"match", str_match},
1553 {"rep", str_rep},
1554 {"reverse", str_reverse},
1555 {"sub", str_sub},
1556 {"upper", str_upper},
1557 {"pack", str_pack},
1558 {"packsize", str_packsize},
1559 {"unpack", str_unpack},
1560 {NULL, NULL}
1561};
1562
1563
1564static void createmetatable (lua_State *L) {
1565 lua_createtable(L, 0, 1); /* table to be metatable for strings */
1566 lua_pushliteral(L, ""); /* dummy string */
1567 lua_pushvalue(L, -2); /* copy table */
1568 lua_setmetatable(L, -2); /* set table as metatable for strings */
1569 lua_pop(L, 1); /* pop dummy string */
1570 lua_pushvalue(L, -2); /* get string library */
1571 lua_setfield(L, -2, "__index"); /* metatable.__index = string */
1572 lua_pop(L, 1); /* pop metatable */
1573}
1574
1575
1576/*
1577** Open string library
1578*/
1579LUAMOD_API int luaopen_string (lua_State *L) {
1580 luaL_newlib(L, strlib);
1581 createmetatable(L);
1582 return 1;
1583}
1584
diff --git a/vendor/compat53/ltablib.c b/vendor/compat53/ltablib.c
new file mode 100644
index 0000000..98b2f87
--- /dev/null
+++ b/vendor/compat53/ltablib.c
@@ -0,0 +1,450 @@
1/*
2** $Id: ltablib.c,v 1.93 2016/02/25 19:41:54 roberto Exp $
3** Library for Table Manipulation
4** See Copyright Notice in lua.h
5*/
6
7#define ltablib_c
8#define LUA_LIB
9
10#include "lprefix.h"
11
12
13#include <limits.h>
14#include <stddef.h>
15#include <string.h>
16
17#include "lua.h"
18
19#include "lauxlib.h"
20#include "lualib.h"
21
22
23/*
24** Operations that an object must define to mimic a table
25** (some functions only need some of them)
26*/
27#define TAB_R 1 /* read */
28#define TAB_W 2 /* write */
29#define TAB_L 4 /* length */
30#define TAB_RW (TAB_R | TAB_W) /* read/write */
31
32
33#define aux_getn(L,n,w) (checktab(L, n, (w) | TAB_L), luaL_len(L, n))
34
35
36static int checkfield (lua_State *L, const char *key, int n) {
37 lua_pushstring(L, key);
38 return (lua_rawget(L, -n) != LUA_TNIL);
39}
40
41
42/*
43** Check that 'arg' either is a table or can behave like one (that is,
44** has a metatable with the required metamethods)
45*/
46static void checktab (lua_State *L, int arg, int what) {
47 if (lua_type(L, arg) != LUA_TTABLE) { /* is it not a table? */
48 int n = 1; /* number of elements to pop */
49 if (lua_getmetatable(L, arg) && /* must have metatable */
50 (!(what & TAB_R) || checkfield(L, "__index", ++n)) &&
51 (!(what & TAB_W) || checkfield(L, "__newindex", ++n)) &&
52 (!(what & TAB_L) || checkfield(L, "__len", ++n))) {
53 lua_pop(L, n); /* pop metatable and tested metamethods */
54 }
55 else
56 luaL_checktype(L, arg, LUA_TTABLE); /* force an error */
57 }
58}
59
60
61#if defined(LUA_COMPAT_MAXN)
62static int maxn (lua_State *L) {
63 lua_Number max = 0;
64 luaL_checktype(L, 1, LUA_TTABLE);
65 lua_pushnil(L); /* first key */
66 while (lua_next(L, 1)) {
67 lua_pop(L, 1); /* remove value */
68 if (lua_type(L, -1) == LUA_TNUMBER) {
69 lua_Number v = lua_tonumber(L, -1);
70 if (v > max) max = v;
71 }
72 }
73 lua_pushnumber(L, max);
74 return 1;
75}
76#endif
77
78
79static int tinsert (lua_State *L) {
80 lua_Integer e = aux_getn(L, 1, TAB_RW) + 1; /* first empty element */
81 lua_Integer pos; /* where to insert new element */
82 switch (lua_gettop(L)) {
83 case 2: { /* called with only 2 arguments */
84 pos = e; /* insert new element at the end */
85 break;
86 }
87 case 3: {
88 lua_Integer i;
89 pos = luaL_checkinteger(L, 2); /* 2nd argument is the position */
90 luaL_argcheck(L, 1 <= pos && pos <= e, 2, "position out of bounds");
91 for (i = e; i > pos; i--) { /* move up elements */
92 lua_geti(L, 1, i - 1);
93 lua_seti(L, 1, i); /* t[i] = t[i - 1] */
94 }
95 break;
96 }
97 default: {
98 return luaL_error(L, "wrong number of arguments to 'insert'");
99 }
100 }
101 lua_seti(L, 1, pos); /* t[pos] = v */
102 return 0;
103}
104
105
106static int tremove (lua_State *L) {
107 lua_Integer size = aux_getn(L, 1, TAB_RW);
108 lua_Integer pos = luaL_optinteger(L, 2, size);
109 if (pos != size) /* validate 'pos' if given */
110 luaL_argcheck(L, 1 <= pos && pos <= size + 1, 1, "position out of bounds");
111 lua_geti(L, 1, pos); /* result = t[pos] */
112 for ( ; pos < size; pos++) {
113 lua_geti(L, 1, pos + 1);
114 lua_seti(L, 1, pos); /* t[pos] = t[pos + 1] */
115 }
116 lua_pushnil(L);
117 lua_seti(L, 1, pos); /* t[pos] = nil */
118 return 1;
119}
120
121
122/*
123** Copy elements (1[f], ..., 1[e]) into (tt[t], tt[t+1], ...). Whenever
124** possible, copy in increasing order, which is better for rehashing.
125** "possible" means destination after original range, or smaller
126** than origin, or copying to another table.
127*/
128static int tmove (lua_State *L) {
129 lua_Integer f = luaL_checkinteger(L, 2);
130 lua_Integer e = luaL_checkinteger(L, 3);
131 lua_Integer t = luaL_checkinteger(L, 4);
132 int tt = !lua_isnoneornil(L, 5) ? 5 : 1; /* destination table */
133 checktab(L, 1, TAB_R);
134 checktab(L, tt, TAB_W);
135 if (e >= f) { /* otherwise, nothing to move */
136 lua_Integer n, i;
137 luaL_argcheck(L, f > 0 || e < LUA_MAXINTEGER + f, 3,
138 "too many elements to move");
139 n = e - f + 1; /* number of elements to move */
140 luaL_argcheck(L, t <= LUA_MAXINTEGER - n + 1, 4,
141 "destination wrap around");
142 if (t > e || t <= f || (tt != 1 && !lua_compare(L, 1, tt, LUA_OPEQ))) {
143 for (i = 0; i < n; i++) {
144 lua_geti(L, 1, f + i);
145 lua_seti(L, tt, t + i);
146 }
147 }
148 else {
149 for (i = n - 1; i >= 0; i--) {
150 lua_geti(L, 1, f + i);
151 lua_seti(L, tt, t + i);
152 }
153 }
154 }
155 lua_pushvalue(L, tt); /* return destination table */
156 return 1;
157}
158
159
160static void addfield (lua_State *L, luaL_Buffer *b, lua_Integer i) {
161 lua_geti(L, 1, i);
162 if (!lua_isstring(L, -1))
163 luaL_error(L, "invalid value (%s) at index %d in table for 'concat'",
164 luaL_typename(L, -1), i);
165 luaL_addvalue(b);
166}
167
168
169static int tconcat (lua_State *L) {
170 luaL_Buffer b;
171 lua_Integer last = aux_getn(L, 1, TAB_R);
172 size_t lsep;
173 const char *sep = luaL_optlstring(L, 2, "", &lsep);
174 lua_Integer i = luaL_optinteger(L, 3, 1);
175 last = luaL_optinteger(L, 4, last);
176 luaL_buffinit(L, &b);
177 for (; i < last; i++) {
178 addfield(L, &b, i);
179 luaL_addlstring(&b, sep, lsep);
180 }
181 if (i == last) /* add last value (if interval was not empty) */
182 addfield(L, &b, i);
183 luaL_pushresult(&b);
184 return 1;
185}
186
187
188/*
189** {======================================================
190** Pack/unpack
191** =======================================================
192*/
193
194static int pack (lua_State *L) {
195 int i;
196 int n = lua_gettop(L); /* number of elements to pack */
197 lua_createtable(L, n, 1); /* create result table */
198 lua_insert(L, 1); /* put it at index 1 */
199 for (i = n; i >= 1; i--) /* assign elements */
200 lua_seti(L, 1, i);
201 lua_pushinteger(L, n);
202 lua_setfield(L, 1, "n"); /* t.n = number of elements */
203 return 1; /* return table */
204}
205
206
207static int unpack (lua_State *L) {
208 lua_Unsigned n;
209 lua_Integer i = luaL_optinteger(L, 2, 1);
210 lua_Integer e = luaL_opt(L, luaL_checkinteger, 3, luaL_len(L, 1));
211 if (i > e) return 0; /* empty range */
212 n = (lua_Unsigned)e - i; /* number of elements minus 1 (avoid overflows) */
213 if (n >= (unsigned int)INT_MAX || !lua_checkstack(L, (int)(++n)))
214 return luaL_error(L, "too many results to unpack");
215 for (; i < e; i++) { /* push arg[i..e - 1] (to avoid overflows) */
216 lua_geti(L, 1, i);
217 }
218 lua_geti(L, 1, e); /* push last element */
219 return (int)n;
220}
221
222/* }====================================================== */
223
224
225
226/*
227** {======================================================
228** Quicksort
229** (based on 'Algorithms in MODULA-3', Robert Sedgewick;
230** Addison-Wesley, 1993.)
231** =======================================================
232*/
233
234
235/* type for array indices */
236typedef unsigned int IdxT;
237
238
239/*
240** Produce a "random" 'unsigned int' to randomize pivot choice. This
241** macro is used only when 'sort' detects a big imbalance in the result
242** of a partition. (If you don't want/need this "randomness", ~0 is a
243** good choice.)
244*/
245#if !defined(l_randomizePivot) /* { */
246
247#include <time.h>
248
249/* size of 'e' measured in number of 'unsigned int's */
250#define sof(e) (sizeof(e) / sizeof(unsigned int))
251
252/*
253** Use 'time' and 'clock' as sources of "randomness". Because we don't
254** know the types 'clock_t' and 'time_t', we cannot cast them to
255** anything without risking overflows. A safe way to use their values
256** is to copy them to an array of a known type and use the array values.
257*/
258static unsigned int l_randomizePivot (void) {
259 clock_t c = clock();
260 time_t t = time(NULL);
261 unsigned int buff[sof(c) + sof(t)];
262 unsigned int i, rnd = 0;
263 memcpy(buff, &c, sof(c) * sizeof(unsigned int));
264 memcpy(buff + sof(c), &t, sof(t) * sizeof(unsigned int));
265 for (i = 0; i < sof(buff); i++)
266 rnd += buff[i];
267 return rnd;
268}
269
270#endif /* } */
271
272
273/* arrays larger than 'RANLIMIT' may use randomized pivots */
274#define RANLIMIT 100u
275
276
277static void set2 (lua_State *L, IdxT i, IdxT j) {
278 lua_seti(L, 1, i);
279 lua_seti(L, 1, j);
280}
281
282
283/*
284** Return true iff value at stack index 'a' is less than the value at
285** index 'b' (according to the order of the sort).
286*/
287static int sort_comp (lua_State *L, int a, int b) {
288 if (lua_isnil(L, 2)) /* no function? */
289 return lua_compare(L, a, b, LUA_OPLT); /* a < b */
290 else { /* function */
291 int res;
292 lua_pushvalue(L, 2); /* push function */
293 lua_pushvalue(L, a-1); /* -1 to compensate function */
294 lua_pushvalue(L, b-2); /* -2 to compensate function and 'a' */
295 lua_call(L, 2, 1); /* call function */
296 res = lua_toboolean(L, -1); /* get result */
297 lua_pop(L, 1); /* pop result */
298 return res;
299 }
300}
301
302
303/*
304** Does the partition: Pivot P is at the top of the stack.
305** precondition: a[lo] <= P == a[up-1] <= a[up],
306** so it only needs to do the partition from lo + 1 to up - 2.
307** Pos-condition: a[lo .. i - 1] <= a[i] == P <= a[i + 1 .. up]
308** returns 'i'.
309*/
310static IdxT partition (lua_State *L, IdxT lo, IdxT up) {
311 IdxT i = lo; /* will be incremented before first use */
312 IdxT j = up - 1; /* will be decremented before first use */
313 /* loop invariant: a[lo .. i] <= P <= a[j .. up] */
314 for (;;) {
315 /* next loop: repeat ++i while a[i] < P */
316 while (lua_geti(L, 1, ++i), sort_comp(L, -1, -2)) {
317 if (i == up - 1) /* a[i] < P but a[up - 1] == P ?? */
318 luaL_error(L, "invalid order function for sorting");
319 lua_pop(L, 1); /* remove a[i] */
320 }
321 /* after the loop, a[i] >= P and a[lo .. i - 1] < P */
322 /* next loop: repeat --j while P < a[j] */
323 while (lua_geti(L, 1, --j), sort_comp(L, -3, -1)) {
324 if (j < i) /* j < i but a[j] > P ?? */
325 luaL_error(L, "invalid order function for sorting");
326 lua_pop(L, 1); /* remove a[j] */
327 }
328 /* after the loop, a[j] <= P and a[j + 1 .. up] >= P */
329 if (j < i) { /* no elements out of place? */
330 /* a[lo .. i - 1] <= P <= a[j + 1 .. i .. up] */
331 lua_pop(L, 1); /* pop a[j] */
332 /* swap pivot (a[up - 1]) with a[i] to satisfy pos-condition */
333 set2(L, up - 1, i);
334 return i;
335 }
336 /* otherwise, swap a[i] - a[j] to restore invariant and repeat */
337 set2(L, i, j);
338 }
339}
340
341
342/*
343** Choose an element in the middle (2nd-3th quarters) of [lo,up]
344** "randomized" by 'rnd'
345*/
346static IdxT choosePivot (IdxT lo, IdxT up, unsigned int rnd) {
347 IdxT r4 = (up - lo) / 4; /* range/4 */
348 IdxT p = rnd % (r4 * 2) + (lo + r4);
349 lua_assert(lo + r4 <= p && p <= up - r4);
350 return p;
351}
352
353
354/*
355** QuickSort algorithm (recursive function)
356*/
357static void auxsort (lua_State *L, IdxT lo, IdxT up,
358 unsigned int rnd) {
359 while (lo < up) { /* loop for tail recursion */
360 IdxT p; /* Pivot index */
361 IdxT n; /* to be used later */
362 /* sort elements 'lo', 'p', and 'up' */
363 lua_geti(L, 1, lo);
364 lua_geti(L, 1, up);
365 if (sort_comp(L, -1, -2)) /* a[up] < a[lo]? */
366 set2(L, lo, up); /* swap a[lo] - a[up] */
367 else
368 lua_pop(L, 2); /* remove both values */
369 if (up - lo == 1) /* only 2 elements? */
370 return; /* already sorted */
371 if (up - lo < RANLIMIT || rnd == 0) /* small interval or no randomize? */
372 p = (lo + up)/2; /* middle element is a good pivot */
373 else /* for larger intervals, it is worth a random pivot */
374 p = choosePivot(lo, up, rnd);
375 lua_geti(L, 1, p);
376 lua_geti(L, 1, lo);
377 if (sort_comp(L, -2, -1)) /* a[p] < a[lo]? */
378 set2(L, p, lo); /* swap a[p] - a[lo] */
379 else {
380 lua_pop(L, 1); /* remove a[lo] */
381 lua_geti(L, 1, up);
382 if (sort_comp(L, -1, -2)) /* a[up] < a[p]? */
383 set2(L, p, up); /* swap a[up] - a[p] */
384 else
385 lua_pop(L, 2);
386 }
387 if (up - lo == 2) /* only 3 elements? */
388 return; /* already sorted */
389 lua_geti(L, 1, p); /* get middle element (Pivot) */
390 lua_pushvalue(L, -1); /* push Pivot */
391 lua_geti(L, 1, up - 1); /* push a[up - 1] */
392 set2(L, p, up - 1); /* swap Pivot (a[p]) with a[up - 1] */
393 p = partition(L, lo, up);
394 /* a[lo .. p - 1] <= a[p] == P <= a[p + 1 .. up] */
395 if (p - lo < up - p) { /* lower interval is smaller? */
396 auxsort(L, lo, p - 1, rnd); /* call recursively for lower interval */
397 n = p - lo; /* size of smaller interval */
398 lo = p + 1; /* tail call for [p + 1 .. up] (upper interval) */
399 }
400 else {
401 auxsort(L, p + 1, up, rnd); /* call recursively for upper interval */
402 n = up - p; /* size of smaller interval */
403 up = p - 1; /* tail call for [lo .. p - 1] (lower interval) */
404 }
405 if ((up - lo) / 128 > n) /* partition too imbalanced? */
406 rnd = l_randomizePivot(); /* try a new randomization */
407 } /* tail call auxsort(L, lo, up, rnd) */
408}
409
410
411static int sort (lua_State *L) {
412 lua_Integer n = aux_getn(L, 1, TAB_RW);
413 if (n > 1) { /* non-trivial interval? */
414 luaL_argcheck(L, n < INT_MAX, 1, "array too big");
415 if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */
416 luaL_checktype(L, 2, LUA_TFUNCTION); /* must be a function */
417 lua_settop(L, 2); /* make sure there are two arguments */
418 auxsort(L, 1, (IdxT)n, 0);
419 }
420 return 0;
421}
422
423/* }====================================================== */
424
425
426static const luaL_Reg tab_funcs[] = {
427 {"concat", tconcat},
428#if defined(LUA_COMPAT_MAXN)
429 {"maxn", maxn},
430#endif
431 {"insert", tinsert},
432 {"pack", pack},
433 {"unpack", unpack},
434 {"remove", tremove},
435 {"move", tmove},
436 {"sort", sort},
437 {NULL, NULL}
438};
439
440
441LUAMOD_API int luaopen_table (lua_State *L) {
442 luaL_newlib(L, tab_funcs);
443#if defined(LUA_COMPAT_UNPACK)
444 /* _G.unpack = table.unpack */
445 lua_getfield(L, -1, "unpack");
446 lua_setglobal(L, "unpack");
447#endif
448 return 1;
449}
450
diff --git a/vendor/compat53/lutf8lib.c b/vendor/compat53/lutf8lib.c
new file mode 100644
index 0000000..de9e3dc
--- /dev/null
+++ b/vendor/compat53/lutf8lib.c
@@ -0,0 +1,256 @@
1/*
2** $Id: lutf8lib.c,v 1.16 2016/12/22 13:08:50 roberto Exp $
3** Standard library for UTF-8 manipulation
4** See Copyright Notice in lua.h
5*/
6
7#define lutf8lib_c
8#define LUA_LIB
9
10#include "lprefix.h"
11
12
13#include <assert.h>
14#include <limits.h>
15#include <stdlib.h>
16#include <string.h>
17
18#include "lua.h"
19
20#include "lauxlib.h"
21#include "lualib.h"
22
23#define MAXUNICODE 0x10FFFF
24
25#define iscont(p) ((*(p) & 0xC0) == 0x80)
26
27
28/* from strlib */
29/* translate a relative string position: negative means back from end */
30static lua_Integer u_posrelat (lua_Integer pos, size_t len) {
31 if (pos >= 0) return pos;
32 else if (0u - (size_t)pos > len) return 0;
33 else return (lua_Integer)len + pos + 1;
34}
35
36
37/*
38** Decode one UTF-8 sequence, returning NULL if byte sequence is invalid.
39*/
40static const char *utf8_decode (const char *o, int *val) {
41 static const unsigned int limits[] = {0xFF, 0x7F, 0x7FF, 0xFFFF};
42 const unsigned char *s = (const unsigned char *)o;
43 unsigned int c = s[0];
44 unsigned int res = 0; /* final result */
45 if (c < 0x80) /* ascii? */
46 res = c;
47 else {
48 int count = 0; /* to count number of continuation bytes */
49 while (c & 0x40) { /* still have continuation bytes? */
50 int cc = s[++count]; /* read next byte */
51 if ((cc & 0xC0) != 0x80) /* not a continuation byte? */
52 return NULL; /* invalid byte sequence */
53 res = (res << 6) | (cc & 0x3F); /* add lower 6 bits from cont. byte */
54 c <<= 1; /* to test next bit */
55 }
56 res |= ((c & 0x7F) << (count * 5)); /* add first byte */
57 if (count > 3 || res > MAXUNICODE || res <= limits[count])
58 return NULL; /* invalid byte sequence */
59 s += count; /* skip continuation bytes read */
60 }
61 if (val) *val = res;
62 return (const char *)s + 1; /* +1 to include first byte */
63}
64
65
66/*
67** utf8len(s [, i [, j]]) --> number of characters that start in the
68** range [i,j], or nil + current position if 's' is not well formed in
69** that interval
70*/
71static int utflen (lua_State *L) {
72 int n = 0;
73 size_t len;
74 const char *s = luaL_checklstring(L, 1, &len);
75 lua_Integer posi = u_posrelat(luaL_optinteger(L, 2, 1), len);
76 lua_Integer posj = u_posrelat(luaL_optinteger(L, 3, -1), len);
77 luaL_argcheck(L, 1 <= posi && --posi <= (lua_Integer)len, 2,
78 "initial position out of string");
79 luaL_argcheck(L, --posj < (lua_Integer)len, 3,
80 "final position out of string");
81 while (posi <= posj) {
82 const char *s1 = utf8_decode(s + posi, NULL);
83 if (s1 == NULL) { /* conversion error? */
84 lua_pushnil(L); /* return nil ... */
85 lua_pushinteger(L, posi + 1); /* ... and current position */
86 return 2;
87 }
88 posi = s1 - s;
89 n++;
90 }
91 lua_pushinteger(L, n);
92 return 1;
93}
94
95
96/*
97** codepoint(s, [i, [j]]) -> returns codepoints for all characters
98** that start in the range [i,j]
99*/
100static int codepoint (lua_State *L) {
101 size_t len;
102 const char *s = luaL_checklstring(L, 1, &len);
103 lua_Integer posi = u_posrelat(luaL_optinteger(L, 2, 1), len);
104 lua_Integer pose = u_posrelat(luaL_optinteger(L, 3, posi), len);
105 int n;
106 const char *se;
107 luaL_argcheck(L, posi >= 1, 2, "out of range");
108 luaL_argcheck(L, pose <= (lua_Integer)len, 3, "out of range");
109 if (posi > pose) return 0; /* empty interval; return no values */
110 if (pose - posi >= INT_MAX) /* (lua_Integer -> int) overflow? */
111 return luaL_error(L, "string slice too long");
112 n = (int)(pose - posi) + 1;
113 luaL_checkstack(L, n, "string slice too long");
114 n = 0;
115 se = s + pose;
116 for (s += posi - 1; s < se;) {
117 int code;
118 s = utf8_decode(s, &code);
119 if (s == NULL)
120 return luaL_error(L, "invalid UTF-8 code");
121 lua_pushinteger(L, code);
122 n++;
123 }
124 return n;
125}
126
127
128static void pushutfchar (lua_State *L, int arg) {
129 lua_Integer code = luaL_checkinteger(L, arg);
130 luaL_argcheck(L, 0 <= code && code <= MAXUNICODE, arg, "value out of range");
131 lua_pushfstring(L, "%U", (long)code);
132}
133
134
135/*
136** utfchar(n1, n2, ...) -> char(n1)..char(n2)...
137*/
138static int utfchar (lua_State *L) {
139 int n = lua_gettop(L); /* number of arguments */
140 if (n == 1) /* optimize common case of single char */
141 pushutfchar(L, 1);
142 else {
143 int i;
144 luaL_Buffer b;
145 luaL_buffinit(L, &b);
146 for (i = 1; i <= n; i++) {
147 pushutfchar(L, i);
148 luaL_addvalue(&b);
149 }
150 luaL_pushresult(&b);
151 }
152 return 1;
153}
154
155
156/*
157** offset(s, n, [i]) -> index where n-th character counting from
158** position 'i' starts; 0 means character at 'i'.
159*/
160static int byteoffset (lua_State *L) {
161 size_t len;
162 const char *s = luaL_checklstring(L, 1, &len);
163 lua_Integer n = luaL_checkinteger(L, 2);
164 lua_Integer posi = (n >= 0) ? 1 : len + 1;
165 posi = u_posrelat(luaL_optinteger(L, 3, posi), len);
166 luaL_argcheck(L, 1 <= posi && --posi <= (lua_Integer)len, 3,
167 "position out of range");
168 if (n == 0) {
169 /* find beginning of current byte sequence */
170 while (posi > 0 && iscont(s + posi)) posi--;
171 }
172 else {
173 if (iscont(s + posi))
174 luaL_error(L, "initial position is a continuation byte");
175 if (n < 0) {
176 while (n < 0 && posi > 0) { /* move back */
177 do { /* find beginning of previous character */
178 posi--;
179 } while (posi > 0 && iscont(s + posi));
180 n++;
181 }
182 }
183 else {
184 n--; /* do not move for 1st character */
185 while (n > 0 && posi < (lua_Integer)len) {
186 do { /* find beginning of next character */
187 posi++;
188 } while (iscont(s + posi)); /* (cannot pass final '\0') */
189 n--;
190 }
191 }
192 }
193 if (n == 0) /* did it find given character? */
194 lua_pushinteger(L, posi + 1);
195 else /* no such character */
196 lua_pushnil(L);
197 return 1;
198}
199
200
201static int iter_aux (lua_State *L) {
202 size_t len;
203 const char *s = luaL_checklstring(L, 1, &len);
204 lua_Integer n = lua_tointeger(L, 2) - 1;
205 if (n < 0) /* first iteration? */
206 n = 0; /* start from here */
207 else if (n < (lua_Integer)len) {
208 n++; /* skip current byte */
209 while (iscont(s + n)) n++; /* and its continuations */
210 }
211 if (n >= (lua_Integer)len)
212 return 0; /* no more codepoints */
213 else {
214 int code;
215 const char *next = utf8_decode(s + n, &code);
216 if (next == NULL || iscont(next))
217 return luaL_error(L, "invalid UTF-8 code");
218 lua_pushinteger(L, n + 1);
219 lua_pushinteger(L, code);
220 return 2;
221 }
222}
223
224
225static int iter_codes (lua_State *L) {
226 luaL_checkstring(L, 1);
227 lua_pushcfunction(L, iter_aux);
228 lua_pushvalue(L, 1);
229 lua_pushinteger(L, 0);
230 return 3;
231}
232
233
234/* pattern to match a single UTF-8 character */
235#define UTF8PATT "[\0-\x7F\xC2-\xF4][\x80-\xBF]*"
236
237
238static const luaL_Reg funcs[] = {
239 {"offset", byteoffset},
240 {"codepoint", codepoint},
241 {"char", utfchar},
242 {"len", utflen},
243 {"codes", iter_codes},
244 /* placeholders */
245 {"charpattern", NULL},
246 {NULL, NULL}
247};
248
249
250LUAMOD_API int luaopen_utf8 (lua_State *L) {
251 luaL_newlib(L, funcs);
252 lua_pushlstring(L, UTF8PATT, sizeof(UTF8PATT)/sizeof(char) - 1);
253 lua_setfield(L, -2, "charpattern");
254 return 1;
255}
256
diff --git a/vendor/compat53/rockspecs/compat53-0.1-1.rockspec b/vendor/compat53/rockspecs/compat53-0.1-1.rockspec
new file mode 100644
index 0000000..0ff56b0
--- /dev/null
+++ b/vendor/compat53/rockspecs/compat53-0.1-1.rockspec
@@ -0,0 +1,31 @@
1package = "compat53"
2version = "0.1-1"
3source = {
4 url = "https://github.com/keplerproject/lua-compat-5.3/archive/v0.1.zip",
5 dir = "lua-compat-5.3-0.1",
6}
7description = {
8 summary = "Compatibility module providing Lua-5.3-style APIs for Lua 5.2 and 5.1",
9 detailed = [[
10 This is a small module that aims to make it easier to write Lua
11 code in a Lua-5.3-style that runs on Lua 5.3, 5.2, and 5.1.
12 It does *not* make Lua 5.2 (or even 5.1) entirely compatible
13 with Lua 5.3, but it brings the API closer to that of Lua 5.3.
14 ]],
15 homepage = "https://github.com/keplerproject/lua-compat-5.3",
16 license = "MIT"
17}
18dependencies = {
19 "lua >= 5.1, < 5.4",
20 --"struct" -- make Roberto's struct module optional
21}
22build = {
23 type = "builtin",
24 modules = {
25 ["compat53"] = "compat53.lua",
26 ["compat53.utf8"] = "lutf8lib.c",
27 ["compat53.table"] = "ltablib.c",
28 ["compat53.string"] = "lstrlib.c",
29 }
30}
31
diff --git a/vendor/compat53/rockspecs/compat53-0.2-1.rockspec b/vendor/compat53/rockspecs/compat53-0.2-1.rockspec
new file mode 100644
index 0000000..1b3c80e
--- /dev/null
+++ b/vendor/compat53/rockspecs/compat53-0.2-1.rockspec
@@ -0,0 +1,32 @@
1package = "compat53"
2version = "0.2-1"
3source = {
4 url = "https://github.com/keplerproject/lua-compat-5.3/archive/v0.2.zip",
5 dir = "lua-compat-5.3-0.2",
6}
7description = {
8 summary = "Compatibility module providing Lua-5.3-style APIs for Lua 5.2 and 5.1",
9 detailed = [[
10 This is a small module that aims to make it easier to write Lua
11 code in a Lua-5.3-style that runs on Lua 5.3, 5.2, and 5.1.
12 It does *not* make Lua 5.2 (or even 5.1) entirely compatible
13 with Lua 5.3, but it brings the API closer to that of Lua 5.3.
14 ]],
15 homepage = "https://github.com/keplerproject/lua-compat-5.3",
16 license = "MIT"
17}
18dependencies = {
19 "lua >= 5.1, < 5.4",
20 --"struct" -- make Roberto's struct module optional
21}
22build = {
23 type = "builtin",
24 modules = {
25 ["compat53.init"] = "compat53/init.lua",
26 ["compat53.module"] = "compat53/module.lua",
27 ["compat53.utf8"] = "lutf8lib.c",
28 ["compat53.table"] = "ltablib.c",
29 ["compat53.string"] = "lstrlib.c",
30 }
31}
32
diff --git a/vendor/compat53/rockspecs/compat53-0.3-1.rockspec b/vendor/compat53/rockspecs/compat53-0.3-1.rockspec
new file mode 100644
index 0000000..43f53d2
--- /dev/null
+++ b/vendor/compat53/rockspecs/compat53-0.3-1.rockspec
@@ -0,0 +1,32 @@
1package = "compat53"
2version = "0.3-1"
3source = {
4 url = "https://github.com/keplerproject/lua-compat-5.3/archive/v0.3.zip",
5 dir = "lua-compat-5.3-0.3",
6}
7description = {
8 summary = "Compatibility module providing Lua-5.3-style APIs for Lua 5.2 and 5.1",
9 detailed = [[
10 This is a small module that aims to make it easier to write Lua
11 code in a Lua-5.3-style that runs on Lua 5.3, 5.2, and 5.1.
12 It does *not* make Lua 5.2 (or even 5.1) entirely compatible
13 with Lua 5.3, but it brings the API closer to that of Lua 5.3.
14 ]],
15 homepage = "https://github.com/keplerproject/lua-compat-5.3",
16 license = "MIT"
17}
18dependencies = {
19 "lua >= 5.1, < 5.4",
20 --"struct" -- make Roberto's struct module optional
21}
22build = {
23 type = "builtin",
24 modules = {
25 ["compat53.init"] = "compat53/init.lua",
26 ["compat53.module"] = "compat53/module.lua",
27 ["compat53.utf8"] = "lutf8lib.c",
28 ["compat53.table"] = "ltablib.c",
29 ["compat53.string"] = "lstrlib.c",
30 }
31}
32
diff --git a/vendor/compat53/rockspecs/compat53-0.4-1.rockspec b/vendor/compat53/rockspecs/compat53-0.4-1.rockspec
new file mode 100644
index 0000000..9331e19
--- /dev/null
+++ b/vendor/compat53/rockspecs/compat53-0.4-1.rockspec
@@ -0,0 +1,32 @@
1package = "compat53"
2version = "0.4-1"
3source = {
4 url = "https://github.com/keplerproject/lua-compat-5.3/archive/v0.4.zip",
5 dir = "lua-compat-5.3-0.4",
6}
7description = {
8 summary = "Compatibility module providing Lua-5.3-style APIs for Lua 5.2 and 5.1",
9 detailed = [[
10 This is a small module that aims to make it easier to write Lua
11 code in a Lua-5.3-style that runs on Lua 5.3, 5.2, and 5.1.
12 It does *not* make Lua 5.2 (or even 5.1) entirely compatible
13 with Lua 5.3, but it brings the API closer to that of Lua 5.3.
14 ]],
15 homepage = "https://github.com/keplerproject/lua-compat-5.3",
16 license = "MIT"
17}
18dependencies = {
19 "lua >= 5.1, < 5.4",
20 --"struct" -- make Roberto's struct module optional
21}
22build = {
23 type = "builtin",
24 modules = {
25 ["compat53.init"] = "compat53/init.lua",
26 ["compat53.module"] = "compat53/module.lua",
27 ["compat53.utf8"] = "lutf8lib.c",
28 ["compat53.table"] = "ltablib.c",
29 ["compat53.string"] = "lstrlib.c",
30 }
31}
32
diff --git a/vendor/compat53/rockspecs/compat53-0.5-1.rockspec b/vendor/compat53/rockspecs/compat53-0.5-1.rockspec
new file mode 100644
index 0000000..3cceccd
--- /dev/null
+++ b/vendor/compat53/rockspecs/compat53-0.5-1.rockspec
@@ -0,0 +1,32 @@
1package = "compat53"
2version = "0.5-1"
3source = {
4 url = "https://github.com/keplerproject/lua-compat-5.3/archive/v0.5.zip",
5 dir = "lua-compat-5.3-0.5",
6}
7description = {
8 summary = "Compatibility module providing Lua-5.3-style APIs for Lua 5.2 and 5.1",
9 detailed = [[
10 This is a small module that aims to make it easier to write Lua
11 code in a Lua-5.3-style that runs on Lua 5.3, 5.2, and 5.1.
12 It does *not* make Lua 5.2 (or even 5.1) entirely compatible
13 with Lua 5.3, but it brings the API closer to that of Lua 5.3.
14 ]],
15 homepage = "https://github.com/keplerproject/lua-compat-5.3",
16 license = "MIT"
17}
18dependencies = {
19 "lua >= 5.1, < 5.4",
20 --"struct" -- make Roberto's struct module optional
21}
22build = {
23 type = "builtin",
24 modules = {
25 ["compat53.init"] = "compat53/init.lua",
26 ["compat53.module"] = "compat53/module.lua",
27 ["compat53.utf8"] = "lutf8lib.c",
28 ["compat53.table"] = "ltablib.c",
29 ["compat53.string"] = "lstrlib.c",
30 }
31}
32
diff --git a/vendor/compat53/rockspecs/compat53-scm-0.rockspec b/vendor/compat53/rockspecs/compat53-scm-0.rockspec
new file mode 100644
index 0000000..317e18c
--- /dev/null
+++ b/vendor/compat53/rockspecs/compat53-scm-0.rockspec
@@ -0,0 +1,32 @@
1package = "compat53"
2version = "scm-0"
3source = {
4 url = "https://github.com/keplerproject/lua-compat-5.3/archive/master.zip",
5 dir = "lua-compat-5.3-master",
6}
7description = {
8 summary = "Compatibility module providing Lua-5.3-style APIs for Lua 5.2 and 5.1",
9 detailed = [[
10 This is a small module that aims to make it easier to write Lua
11 code in a Lua-5.3-style that runs on Lua 5.3, 5.2, and 5.1.
12 It does *not* make Lua 5.2 (or even 5.1) entirely compatible
13 with Lua 5.3, but it brings the API closer to that of Lua 5.3.
14 ]],
15 homepage = "https://github.com/keplerproject/lua-compat-5.3",
16 license = "MIT"
17}
18dependencies = {
19 "lua >= 5.1, < 5.4",
20 --"struct" -- make Roberto's struct module optional
21}
22build = {
23 type = "builtin",
24 modules = {
25 ["compat53.init"] = "compat53/init.lua",
26 ["compat53.module"] = "compat53/module.lua",
27 ["compat53.utf8"] = "lutf8lib.c",
28 ["compat53.table"] = "ltablib.c",
29 ["compat53.string"] = "lstrlib.c",
30 }
31}
32
diff --git a/vendor/compat53/tests/test.lua b/vendor/compat53/tests/test.lua
new file mode 100755
index 0000000..582f55e
--- /dev/null
+++ b/vendor/compat53/tests/test.lua
@@ -0,0 +1,789 @@
1#!/usr/bin/env lua
2
3local F, tproxy, writefile, noprint, ___
4do
5 local type, unpack = type, table.unpack or unpack
6 local assert, io = assert, io
7 function F(...)
8 local args, n = { ... }, select('#', ...)
9 for i = 1, n do
10 local t = type(args[i])
11 if t ~= "string" and t ~= "number" and t ~= "boolean" then
12 args[i] = t
13 end
14 end
15 return unpack(args, 1, n)
16 end
17 function tproxy(t)
18 return setmetatable({}, {
19 __index = t,
20 __newindex = t,
21 __len = function() return #t end,
22 }), t
23 end
24 function writefile(name, contents, bin)
25 local f = assert(io.open(name, bin and "wb" or "w"))
26 f:write(contents)
27 f:close()
28 end
29 function noprint() end
30 local sep = ("="):rep(70)
31 function ___()
32 print(sep)
33 end
34end
35
36local V = _VERSION:gsub("^.*(%d+)%.(%d+)$", "%1%2")
37if jit then V = "jit" end
38
39local mode = "global"
40if arg[1] == "module" then
41 mode = "module"
42end
43
44
45package.path = "../?.lua;../?/init.lua"
46package.cpath = "./?-"..V..".so;./?-"..V..".dll;./?.so;./?.dll"
47if mode == "module" then
48 print("testing Lua API using `compat53.module` ...")
49 _ENV = require("compat53.module")
50 if setfenv then setfenv(1, _ENV) end
51else
52 print("testing Lua API using `compat53` ...")
53 require("compat53")
54end
55
56
57___''
58do
59 print("assert", F(pcall(assert, false)))
60 print("assert", F(pcall(assert, false, nil)))
61 print("assert", F(pcall(assert, false, "error msg")))
62 print("assert", F(pcall(assert, nil, {})))
63 print("assert", F(pcall(assert, 1, 2, 3)))
64end
65
66
67___''
68do
69 local t = setmetatable({}, { __index = { 1, false, "three" } })
70 for i,v in ipairs(t) do
71 print("ipairs", i, v)
72 end
73end
74
75
76___''
77do
78 local p, t = tproxy{ "a", "b", "c" }
79 print("table.concat", table.concat(p))
80 print("table.concat", table.concat(p, ",", 2))
81 print("table.concat", table.concat(p, ".", 1, 2))
82 print("table.concat", table.concat(t))
83 print("table.concat", table.concat(t, ",", 2))
84 print("table.concat", table.concat(t, ".", 1, 2))
85end
86
87
88___''
89do
90 local p, t = tproxy{ "a", "b", "c" }
91 table.insert(p, "d")
92 print("table.insert", next(p), t[4])
93 table.insert(p, 1, "z")
94 print("table.insert", next(p), t[1], t[2])
95 table.insert(p, 2, "y")
96 print("table.insert", next(p), t[1], t[2], p[3])
97 t = { "a", "b", "c" }
98 table.insert(t, "d")
99 print("table.insert", t[1], t[2], t[3], t[4])
100 table.insert(t, 1, "z")
101 print("table.insert", t[1], t[2], t[3], t[4], t[5])
102 table.insert(t, 2, "y")
103 print("table.insert", t[1], t[2], t[3], t[4], t[5])
104end
105
106
107___''
108do
109 local ps, s = tproxy{ "a", "b", "c", "d" }
110 local pd, d = tproxy{ "A", "B", "C", "D" }
111 table.move(ps, 1, 4, 1, pd)
112 print("table.move", next(pd), d[1], d[2], d[3], d[4])
113 pd, d = tproxy{ "A", "B", "C", "D" }
114 table.move(ps, 2, 4, 1, pd)
115 print("table.move", next(pd), d[1], d[2], d[3], d[4])
116 pd, d = tproxy{ "A", "B", "C", "D" }
117 table.move(ps, 2, 3, 4, pd)
118 print("table.move", next(pd), d[1], d[2], d[3], d[4], d[5])
119 table.move(ps, 2, 4, 1)
120 print("table.move", next(ps), s[1], s[2], s[3], s[4])
121 ps, s = tproxy{ "a", "b", "c", "d" }
122 table.move(ps, 2, 3, 4)
123 print("table.move", next(ps), s[1], s[2], s[3], s[4], s[5])
124 s = { "a", "b", "c", "d" }
125 d = { "A", "B", "C", "D" }
126 table.move(s, 1, 4, 1, d)
127 print("table.move", d[1], d[2], d[3], d[4])
128 d = { "A", "B", "C", "D" }
129 table.move(s, 2, 4, 1, d)
130 print("table.move", d[1], d[2], d[3], d[4])
131 d = { "A", "B", "C", "D" }
132 table.move(s, 2, 3, 4, d)
133 print("table.move", d[1], d[2], d[3], d[4], d[5])
134 table.move(s, 2, 4, 1)
135 print("table.move", s[1], s[2], s[3], s[4])
136 s = { "a", "b", "c", "d" }
137 table.move(s, 2, 3, 4)
138 print("table.move", s[1], s[2], s[3], s[4], s[5])
139end
140
141
142___''
143do
144 local p, t = tproxy{ "a", "b", "c", "d", "e" }
145 print("table.remove", table.remove(p))
146 print("table.remove", next(p), t[1], t[2], t[3], t[4], t[5])
147 print("table.remove", table.remove(p, 1))
148 print("table.remove", next(p), t[1], t[2], t[3], t[4])
149 print("table.remove", table.remove(p, 2))
150 print("table.remove", next(p), t[1], t[2], t[3])
151 print("table.remove", table.remove(p, 3))
152 print("table.remove", next(p), t[1], t[2], t[3])
153 p, t = tproxy{}
154 print("table.remove", table.remove(p))
155 print("table.remove", next(p), next(t))
156 t = { "a", "b", "c", "d", "e" }
157 print("table.remove", table.remove(t))
158 print("table.remove", t[1], t[2], t[3], t[4], t[5])
159 print("table.remove", table.remove(t, 1))
160 print("table.remove", t[1], t[2], t[3], t[4])
161 print("table.remove", table.remove(t, 2))
162 print("table.remove", t[1], t[2], t[3])
163 print("table.remove", table.remove(t, 3))
164 print("table.remove", t[1], t[2], t[3])
165 t = {}
166 print("table.remove", table.remove(t))
167 print("table.remove", next(t))
168end
169
170___''
171do
172 local p, t = tproxy{ 3, 1, 5, 2, 8, 5, 2, 9, 7, 4 }
173 table.sort(p)
174 print("table.sort", next(p))
175 for i,v in ipairs(t) do
176 print("table.sort", i, v)
177 end
178 table.sort(p)
179 print("table.sort", next(p))
180 for i,v in ipairs(t) do
181 print("table.sort", i, v)
182 end
183 p, t = tproxy{ 9, 8, 7, 6, 5, 4, 3, 2, 1 }
184 table.sort(p)
185 print("table.sort", next(p))
186 for i,v in ipairs(t) do
187 print("table.sort", i, v)
188 end
189 table.sort(p, function(a, b) return a > b end)
190 print("table.sort", next(p))
191 for i,v in ipairs(t) do
192 print("table.sort", i, v)
193 end
194 p, t = tproxy{ 1, 1, 1, 1, 1 }
195 print("table.sort", next(p))
196 for i,v in ipairs(t) do
197 print("table.sort", i, v)
198 end
199 t = { 3, 1, 5, 2, 8, 5, 2, 9, 7, 4 }
200 table.sort(t)
201 for i,v in ipairs(t) do
202 print("table.sort", i, v)
203 end
204 table.sort(t, function(a, b) return a > b end)
205 for i,v in ipairs(t) do
206 print("table.sort", i, v)
207 end
208end
209
210
211___''
212do
213 local p, t = tproxy{ "a", "b", "c" }
214 print("table.unpack", table.unpack(p))
215 print("table.unpack", table.unpack(p, 2))
216 print("table.unpack", table.unpack(p, 1, 2))
217 print("table.unpack", table.unpack(t))
218 print("table.unpack", table.unpack(t, 2))
219 print("table.unpack", table.unpack(t, 1, 2))
220end
221
222
223___''
224print("math.maxinteger", math.maxinteger+1 > math.maxinteger)
225print("math.mininteger", math.mininteger-1 < math.mininteger)
226
227
228___''
229print("math.tointeger", math.tointeger(0))
230print("math.tointeger", math.tointeger(math.pi))
231print("math.tointeger", math.tointeger("hello"))
232print("math.tointeger", math.tointeger(math.maxinteger+2.0))
233print("math.tointeger", math.tointeger(math.mininteger*2.0))
234
235
236___''
237print("math.type", math.type(0))
238print("math.type", math.type(math.pi))
239print("math.type", math.type("hello"))
240
241
242___''
243print("math.ult", math.ult(1, 2), math.ult(2, 1))
244print("math.ult", math.ult(-1, 2), math.ult(2, -1))
245print("math.ult", math.ult(-1, -2), math.ult(-2, -1))
246print("math.ult", pcall(math.ult, "x", 2))
247print("math.ult", pcall(math.ult, 1, 2.1))
248___''
249
250
251if utf8.len then
252 local unpack = table.unpack or unpack
253 local function utf8rt(s)
254 local t = { utf8.codepoint(s, 1, #s) }
255 local ps, cs = {}, {}
256 for p,c in utf8.codes(s) do
257 ps[#ps+1], cs[#cs+1] = p, c
258 end
259 print("utf8.codes", unpack(ps))
260 print("utf8.codes", unpack(cs))
261 print("utf8.codepoint", unpack(t))
262 print("utf8.len", utf8.len(s), #t, #s)
263 print("utf8.char", utf8.char(unpack(t)))
264 end
265 utf8rt("äöüßÄÖÜ")
266 utf8rt("abcdefg")
267 ___''
268 local s = "äöüßÄÖÜ"
269 print("utf8.offset", utf8.offset(s, 1, 1))
270 print("utf8.offset", utf8.offset(s, 2, 1))
271 print("utf8.offset", utf8.offset(s, 3, 1))
272 print("utf8.offset", pcall(utf8.offset, s, 3, 2))
273 print("utf8.offset", utf8.offset(s, 3, 3))
274 print("utf8.offset", utf8.offset(s, -1, 7))
275 print("utf8.offset", utf8.offset(s, -2, 7))
276 print("utf8.offset", utf8.offset(s, -3, 7))
277 print("utf8.offset", utf8.offset(s, -1))
278 ___''
279else
280 print("XXX: utf8 module not available")
281end
282
283
284if string.pack then
285 local format = "bBhHlLjJdc3z"
286 local s = string.pack(format, -128, 255, -32768, 65535, -2147483648, 4294967295, -32768, 65536, 1.25, "abc", "defgh")
287 print("string.unpack", string.unpack(format, s))
288 ___''
289else
290 print("XXX: string packing not available")
291end
292
293
294print("testing Lua API for Lua 5.1 ...")
295
296___''
297print("debug.getuservalue()", F(debug.getuservalue(false)))
298print("debug.setuservalue()", pcall(function()
299 debug.setuservalue(false, {})
300end))
301print("debug.setmetatable()", F(debug.setmetatable({}, {})))
302
303
304___''
305do
306 local t = setmetatable({}, {
307 __pairs = function() return pairs({ a = "a" }) end,
308 })
309 for k,v in pairs(t) do
310 print("pairs()", k, v)
311 end
312end
313
314
315___''
316do
317 local code = "print('hello world')\n"
318 local badcode = "print('blub\n"
319 print("load()", pcall(function() load(true) end))
320 print("load()", F(load(badcode)))
321 print("load()", F(load(code)))
322 print("load()", F(load(code, "[L]")))
323 print("load()", F(load(code, "[L]", "b")))
324 print("load()", F(load(code, "[L]", "t")))
325 print("load()", F(load(code, "[L]", "bt")))
326 local f = load(code, "[L]", "bt", {})
327 print("load()", pcall(f))
328 f = load(code, "[L]", "bt", { print = noprint })
329 print("load()", pcall(f))
330 local bytecode = string.dump(f)
331 print("load()", F(load(bytecode)))
332 print("load()", F(load(bytecode, "[L]")))
333 print("load()", F(load(bytecode, "[L]", "b")))
334 print("load()", F(load(bytecode, "[L]", "t")))
335 print("load()", F(load(bytecode, "[L]", "bt")))
336 f = load(bytecode, "[L]", "bt", {})
337 print("load()", pcall(f))
338 f = load(bytecode, "[L]", "bt", { print = noprint })
339 print("load()", pcall(f))
340 local function make_loader(code)
341 local mid = math.floor( #code/2 )
342 local array = { code:sub(1, mid), code:sub(mid+1) }
343 local i = 0
344 return function()
345 i = i + 1
346 return array[i]
347 end
348 end
349 print("load()", F(load(make_loader(badcode))))
350 print("load()", F(load(make_loader(code))))
351 print("load()", F(load(make_loader(code), "[L]")))
352 print("load()", F(load(make_loader(code), "[L]", "b")))
353 print("load()", F(load(make_loader(code), "[L]", "t")))
354 print("load()", F(load(make_loader(code), "[L]", "bt")))
355 f = load(make_loader(code), "[L]", "bt", {})
356 print("load()", pcall(f))
357 f = load(make_loader(code), "[L]", "bt", { print = noprint })
358 print("load()", pcall(f))
359 print("load()", F(load(make_loader(bytecode))))
360 print("load()", F(load(make_loader(bytecode), "[L]")))
361 print("load()", F(load(make_loader(bytecode), "[L]", "b")))
362 print("load()", F(load(make_loader(bytecode), "[L]", "t")))
363 print("load()", F(load(make_loader(bytecode), "[L]", "bt")))
364 f = load(make_loader(bytecode), "[L]", "bt", {})
365 print("load()", pcall(f))
366 f = load(make_loader(bytecode), "[L]", "bt", { print = noprint })
367 print("load()", pcall(f))
368 writefile("good.lua", code)
369 writefile("bad.lua", badcode)
370 writefile("good.luac", bytecode, true)
371 print("loadfile()", F(loadfile("bad.lua")))
372 print("loadfile()", F(loadfile("good.lua")))
373 print("loadfile()", F(loadfile("good.lua", "b")))
374 print("loadfile()", F(loadfile("good.lua", "t")))
375 print("loadfile()", F(loadfile("good.lua", "bt")))
376 f = loadfile("good.lua", "bt", {})
377 print("loadfile()", pcall(f))
378 f = loadfile("good.lua", "bt", { print = noprint })
379 print("loadfile()", pcall(f))
380 print("loadfile()", F(loadfile("good.luac")))
381 print("loadfile()", F(loadfile("good.luac", "b")))
382 print("loadfile()", F(loadfile("good.luac", "t")))
383 print("loadfile()", F(loadfile("good.luac", "bt")))
384 f = loadfile("good.luac", "bt", {})
385 print("loadfile()", pcall(f))
386 f = loadfile("good.luac", "bt", { print = noprint })
387 print("loadfile()", pcall(f))
388 os.remove("good.lua")
389 os.remove("bad.lua")
390 os.remove("good.luac")
391end
392
393
394___''
395do
396 local function func(throw)
397 if throw then
398 error("argh")
399 else
400 return 1, 2, 3
401 end
402 end
403 local function tb(err) return "|"..err.."|" end
404 print("xpcall()", xpcall(func, debug.traceback, false))
405 print("xpcall()", xpcall(func, debug.traceback, true))
406 print("xpcall()", xpcall(func, tb, true))
407 if mode ~= "module" then
408 local function func2(cb)
409 print("xpcall()", xpcall(cb, debug.traceback, "str"))
410 end
411 local function func3(cb)
412 print("pcall()", pcall(cb, "str"))
413 end
414 local function cb(arg)
415 coroutine.yield(2)
416 return arg
417 end
418 local c = coroutine.wrap(func2)
419 print("xpcall()", c(cb))
420 print("xpcall()", c())
421 local c = coroutine.wrap(func3)
422 print("pcall()", c(cb))
423 print("pcall()", c())
424 end
425end
426
427
428___''
429do
430 local t = setmetatable({ 1 }, { __len = function() return 5 end })
431 print("rawlen()", rawlen(t), rawlen("123"))
432end
433
434
435___''
436print("os.execute()", os.execute("exit 1"))
437io.flush()
438print("os.execute()", os.execute("echo 'hello world!'"))
439io.flush()
440print("os.execute()", os.execute("no_such_file"))
441
442
443___''
444do
445 local t = table.pack("a", nil, "b", nil)
446 print("table.(un)pack()", t.n, table.unpack(t, 1, t.n))
447end
448
449
450___''
451do
452 print("coroutine.running()", F(coroutine.wrap(function()
453 return coroutine.running()
454 end)()))
455 print("coroutine.running()", F(coroutine.running()))
456 local main_co, co1, co2 = coroutine.running()
457 -- coroutine.yield
458 if mode ~= "module" then
459 print("coroutine.yield()", pcall(function()
460 coroutine.yield(1, 2, 3)
461 end))
462 end
463 print("coroutine.yield()", coroutine.wrap(function()
464 coroutine.yield(1, 2, 3)
465 end)())
466 print("coroutine.resume()", coroutine.resume(main_co, 1, 2, 3))
467 co1 = coroutine.create(function(a, b, c)
468 print("coroutine.resume()", a, b, c)
469 return a, b, c
470 end)
471 print("coroutine.resume()", coroutine.resume(co1, 1, 2, 3))
472 co1 = coroutine.create(function()
473 print("coroutine.status()", "[co1] main is", coroutine.status(main_co))
474 print("coroutine.status()", "[co1] co2 is", coroutine.status(co2))
475 end)
476 co2 = coroutine.create(function()
477 print("coroutine.status()", "[co2] main is", coroutine.status(main_co))
478 print("coroutine.status()", "[co2] co2 is", coroutine.status(co2))
479 coroutine.yield()
480 coroutine.resume(co1)
481 end)
482 print("coroutine.status()", coroutine.status(main_co))
483 print("coroutine.status()", coroutine.status(co2))
484 coroutine.resume(co2)
485 print("coroutine.status()", F(coroutine.status(co2)))
486 coroutine.resume(co2)
487 print("coroutine.status()", F(coroutine.status(co2)))
488end
489
490
491___''
492print("math.log()", math.log(1000))
493print("math.log()", math.log(1000, 10))
494
495
496___''
497do
498 local path, prefix = "./?.lua;?/init.lua;../?.lua", "package.searchpath()"
499 print(prefix, package.searchpath("no.such.module", path))
500 print(prefix, package.searchpath("no.such.module", ""))
501 print(prefix, package.searchpath("compat53", path))
502 print(prefix, package.searchpath("no:such:module", path, ":", "|"))
503end
504
505
506___''
507if mode ~= "module" then
508 local function mod_func() return {} end
509 local function my_searcher(name)
510 if name == "my.module" then
511 print("package.searchers", "my.module found")
512 return mod_func
513 end
514 end
515 local function my_searcher2(name)
516 if name == "my.module" then
517 print("package.searchers", "my.module found 2")
518 return mod_func
519 end
520 end
521 table.insert(package.searchers, my_searcher)
522 require("my.module")
523 package.loaded["my.module"] = nil
524 local new_s = { my_searcher2 }
525 for i,f in ipairs(package.searchers) do
526 new_s[i+1] = f
527 end
528 package.searchers = new_s
529 require("my.module")
530end
531
532
533___''
534do
535 print("string.find()", string.find("abc\0abc\0abc", "[^a\0]+"))
536 print("string.find()", string.find("abc\0abc\0abc", "%w+\0", 5))
537 for x in string.gmatch("abc\0def\0ghi", "[^\0]+") do
538 print("string.gmatch()", x)
539 end
540 for x in string.gmatch("abc\0def\0ghi", "%w*\0") do
541 print("string.gmatch()", #x)
542 end
543 print("string.gsub()", string.gsub("abc\0def\0ghi", "[\0]", "X"))
544 print("string.gsub()", string.gsub("abc\0def\0ghi", "%w*\0", "X"))
545 print("string.gsub()", string.gsub("abc\0def\0ghi", "%A", "X"))
546 print("string.match()", string.match("abc\0abc\0abc", "([^\0a]+)"))
547 print("string.match()", #string.match("abc\0abc\0abc", ".*\0"))
548 print("string.rep()", string.rep("a", 0))
549 print("string.rep()", string.rep("b", 1))
550 print("string.rep()", string.rep("c", 4))
551 print("string.rep()", string.rep("a", 0, "|"))
552 print("string.rep()", string.rep("b", 1, "|"))
553 print("string.rep()", string.rep("c", 4, "|"))
554 local _tostring = tostring
555 function tostring(v)
556 if type(v) == "number" then
557 return "(".._tostring(v)..")"
558 else
559 return _tostring(v)
560 end
561 end
562 print("string.format()", string.format("%q", "\"\\\0000\0010\002\r\n0\t0\""))
563 print("string.format()", string.format("%12.3fx%%sxx%.6s", 3.1, {}))
564 print("string.format()", string.format("%-3f %%%s %%s", 3.1, true))
565 print("string.format()", string.format("% 3.2g %%d %%%s", 3.1, nil))
566 print("string.format()", string.format("%+3d %%d %%%%%10.6s", 3, io.stdout))
567 print("string.format()", pcall(function()
568 print("string.format()", string.format("%d %%s", {}))
569 end))
570 tostring = _tostring
571end
572
573
574___''
575do
576 print("io.write()", io.type(io.write("hello world\n")))
577 local f = assert(io.tmpfile())
578 print("file:write()", io.type(f:write("hello world\n")))
579 f:close()
580end
581
582
583___''
584do
585 writefile("data.txt", "123 18.8 hello world\ni'm here\n")
586 io.input("data.txt")
587 print("io.read()", io.read("*n", "*number", "*l", "*a"))
588 io.input("data.txt")
589 print("io.read()", io.read("n", "number", "l", "a"))
590 io.input(io.stdin)
591 if mode ~= "module" then
592 local f = assert(io.open("data.txt", "r"))
593 print("file:read()", f:read("*n", "*number", "*l", "*a"))
594 f:close()
595 f = assert(io.open("data.txt", "r"))
596 print("file:read()", f:read("n", "number", "l", "a"))
597 f:close()
598 end
599 os.remove("data.txt")
600end
601
602
603___''
604do
605 writefile("data.txt", "123 18.8 hello world\ni'm here\n")
606 for a,b in io.lines("test.lua", 2, "*l") do
607 print("io.lines()", a, b)
608 break
609 end
610 for l in io.lines("test.lua") do
611 print("io.lines()", l)
612 break
613 end
614 for n1,n2,rest in io.lines("data.txt", "*n", "n", "*a") do
615 print("io.lines()", n1, n2, rest)
616 end
617 for l in io.lines("data.txt") do
618 print("io.lines()", l)
619 end
620 print("io.lines()", pcall(function()
621 for l in io.lines("data.txt", "*x") do print(l) end
622 end))
623 print("io.lines()", pcall(function()
624 for l in io.lines("no_such_file.txt") do print(l) end
625 end))
626 if mode ~= "module" then
627 local f = assert(io.open("test.lua", "r"))
628 for a,b in f:lines(2, "*l") do
629 print("file:lines()", a, b)
630 break
631 end
632 f:close()
633 f = assert(io.open("data.txt", "r"))
634 for n1,n2,rest in f:lines("*n", "n", "*a") do
635 print("file:lines()", n1, n2, rest)
636 end
637 f:close()
638 f = assert(io.open("data.txt", "r"))
639 for l in f:lines() do
640 print("file:lines()", l)
641 end
642 f:close()
643 print("file:lines()", pcall(function()
644 for l in f:lines() do print(l) end
645 end))
646 print("file:lines()", pcall(function()
647 local f = assert(io.open("data.txt", "r"))
648 for l in f:lines("*l", "*x") do print(l) end
649 f:close()
650 end))
651 end
652 os.remove("data.txt")
653end
654___''
655
656
657print("testing C API ...")
658local mod = require("testmod")
659___''
660print(mod.isinteger(1))
661print(mod.isinteger(0))
662print(mod.isinteger(1234567))
663print(mod.isinteger(12.3))
664print(mod.isinteger(math.huge))
665print(mod.isinteger(math.sqrt(-1)))
666
667
668___''
669print(mod.rotate(1, 1, 2, 3, 4, 5, 6))
670print(mod.rotate(-1, 1, 2, 3, 4, 5, 6))
671print(mod.rotate(4, 1, 2, 3, 4, 5, 6))
672print(mod.rotate(-4, 1, 2, 3, 4, 5, 6))
673
674
675___''
676print(mod.strtonum("+123"))
677print(mod.strtonum(" 123 "))
678print(mod.strtonum("-1.23"))
679print(mod.strtonum(" 123 abc"))
680print(mod.strtonum("jkl"))
681
682
683___''
684local a, b, c = mod.requiref()
685print( type(a), type(b), type(c),
686 a.boolean, b.boolean, c.boolean,
687 type(requiref1), type(requiref2), type(requiref3))
688
689___''
690local proxy, backend = {}, {}
691setmetatable(proxy, { __index = backend, __newindex = backend })
692print(rawget(proxy, 1), rawget(backend, 1))
693print(mod.getseti(proxy, 1))
694print(rawget(proxy, 1), rawget(backend, 1))
695print(mod.getseti(proxy, 1))
696print(rawget(proxy, 1), rawget(backend, 1))
697
698-- tests for Lua 5.1
699___''
700print(mod.tonumber(12))
701print(mod.tonumber("12"))
702print(mod.tonumber("0"))
703print(mod.tonumber(false))
704print(mod.tonumber("error"))
705
706___''
707print(mod.tointeger(12))
708print(mod.tointeger("12"))
709print(mod.tointeger("0"))
710print( "aaa" )
711print(mod.tointeger(math.pi))
712print( "bbb" )
713print(mod.tointeger(false))
714print(mod.tointeger("error"))
715
716___''
717print(mod.len("123"))
718print(mod.len({ 1, 2, 3}))
719print(pcall(mod.len, true))
720local ud, meta = mod.newproxy()
721meta.__len = function() return 5 end
722print(mod.len(ud))
723meta.__len = function() return true end
724print(pcall(mod.len, ud))
725
726___''
727print(mod.copy(true, "string", {}, 1))
728
729___''
730print(mod.rawxetp())
731print(mod.rawxetp("I'm back"))
732
733___''
734print(F(mod.globals()), mod.globals() == _G)
735
736___''
737local t = {}
738print(F(mod.subtable(t)))
739local x, msg = mod.subtable(t)
740print(F(x, msg, x == t.xxx))
741
742___''
743print(F(mod.udata()))
744print(mod.udata("nosuchtype"))
745
746___''
747print(F(mod.uservalue()))
748
749___''
750print(mod.getupvalues())
751
752___''
753print(mod.absindex("hi", true))
754
755___''
756print(mod.arith(2, 1))
757print(mod.arith(3, 5))
758
759___''
760print(mod.compare(1, 1))
761print(mod.compare(2, 1))
762print(mod.compare(1, 2))
763
764___''
765print(mod.tolstring("string"))
766local t = setmetatable({}, {
767 __tostring = function(v) return "mytable" end
768})
769print(mod.tolstring(t))
770local t = setmetatable({}, {
771 __tostring = function(v) return nil end
772})
773print(pcall(mod.tolstring, t))
774local ud, meta = mod.newproxy()
775meta.__name = "XXX"
776print(mod.tolstring(ud):gsub(":.*$", ": yyy"))
777
778___''
779print(mod.pushstring())
780
781___''
782print(mod.buffer())
783
784___''
785print(mod.exec("exit 0"))
786print(mod.exec("exit 1"))
787print(mod.exec("exit 25"))
788___''
789
diff --git a/vendor/compat53/tests/testmod.c b/vendor/compat53/tests/testmod.c
new file mode 100644
index 0000000..868136b
--- /dev/null
+++ b/vendor/compat53/tests/testmod.c
@@ -0,0 +1,318 @@
1#include <stdio.h>
2#include <stdlib.h>
3#include <lua.h>
4#include <lauxlib.h>
5#include "compat-5.3.h"
6
7
8static int test_isinteger (lua_State *L) {
9 lua_pushboolean(L, lua_isinteger(L, 1));
10 return 1;
11}
12
13
14static int test_rotate (lua_State *L) {
15 int r = luaL_checkint(L, 1);
16 int n = lua_gettop(L)-1;
17 luaL_argcheck(L, (r < 0 ? -r : r) <= n, 1, "not enough arguments");
18 lua_rotate(L, 2, r);
19 return n;
20}
21
22
23static int test_str2num (lua_State *L) {
24 const char *s = luaL_checkstring(L, 1);
25 size_t len = lua_stringtonumber(L, s);
26 if (len == 0)
27 lua_pushnumber(L, 0);
28 lua_pushinteger(L, (lua_Integer)len);
29 return 2;
30}
31
32
33static int my_mod (lua_State *L ) {
34 lua_newtable(L);
35 lua_pushboolean(L, 1);
36 lua_setfield(L, -2, "boolean");
37 return 1;
38}
39
40static int test_requiref (lua_State *L) {
41 lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
42 lua_newtable(L);
43 lua_pushboolean(L, 0);
44 lua_setfield(L, -2, "boolean");
45 lua_setfield(L, -2, "requiref3");
46 lua_pop(L, 1);
47 luaL_requiref(L, "requiref1", my_mod, 0);
48 luaL_requiref(L, "requiref2", my_mod, 1);
49 luaL_requiref(L, "requiref3", my_mod, 1);
50 return 3;
51}
52
53static int test_getseti (lua_State *L) {
54 lua_Integer k = luaL_checkinteger(L, 2);
55 lua_Integer n = 0;
56 if (lua_geti(L, 1, k) == LUA_TNUMBER) {
57 n = lua_tointeger(L, -1);
58 } else {
59 lua_pop(L, 1);
60 lua_pushinteger(L, n);
61 }
62 lua_pushinteger(L, n+1);
63 lua_seti(L, 1, k);
64 return 1;
65}
66
67
68/* additional tests for Lua5.1 */
69#define NUP 3
70
71static int test_newproxy (lua_State *L) {
72 lua_settop(L, 0);
73 lua_newuserdata(L, 0);
74 lua_newtable(L);
75 lua_pushvalue(L, -1);
76 lua_pushboolean(L, 1);
77 lua_setfield(L, -2, "__gc");
78 lua_setmetatable(L, -3);
79 return 2;
80}
81
82static int test_absindex (lua_State *L) {
83 int i = 1;
84 for (i = 1; i <= NUP; ++i)
85 lua_pushvalue(L, lua_absindex(L, lua_upvalueindex(i)));
86 lua_pushvalue(L, lua_absindex(L, LUA_REGISTRYINDEX));
87 lua_pushstring(L, lua_typename(L, lua_type(L, lua_absindex(L, -1))));
88 lua_replace(L, lua_absindex(L, -2));
89 lua_pushvalue(L, lua_absindex(L, -2));
90 lua_pushvalue(L, lua_absindex(L, -4));
91 lua_pushvalue(L, lua_absindex(L, -6));
92 i += 3;
93 lua_pushvalue(L, lua_absindex(L, 1));
94 lua_pushvalue(L, lua_absindex(L, 2));
95 lua_pushvalue(L, lua_absindex(L, 3));
96 i += 3;
97 return i;
98}
99
100static int test_arith (lua_State *L) {
101 lua_settop(L, 2);
102 lua_pushvalue(L, 1);
103 lua_pushvalue(L, 2);
104 lua_arith(L, LUA_OPADD);
105 lua_pushvalue(L, 1);
106 lua_pushvalue(L, 2);
107 lua_arith(L, LUA_OPSUB);
108 lua_pushvalue(L, 1);
109 lua_pushvalue(L, 2);
110 lua_arith(L, LUA_OPMUL);
111 lua_pushvalue(L, 1);
112 lua_pushvalue(L, 2);
113 lua_arith(L, LUA_OPDIV);
114 lua_pushvalue(L, 1);
115 lua_pushvalue(L, 2);
116 lua_arith(L, LUA_OPMOD);
117 lua_pushvalue(L, 1);
118 lua_pushvalue(L, 2);
119 lua_arith(L, LUA_OPPOW);
120 lua_pushvalue(L, 1);
121 lua_arith(L, LUA_OPUNM);
122 return lua_gettop(L)-2;
123}
124
125static int test_compare (lua_State *L) {
126 luaL_checknumber(L, 1);
127 luaL_checknumber(L, 2);
128 lua_settop(L, 2);
129 lua_pushboolean(L, lua_compare(L, 1, 2, LUA_OPEQ));
130 lua_pushboolean(L, lua_compare(L, 1, 2, LUA_OPLT));
131 lua_pushboolean(L, lua_compare(L, 1, 2, LUA_OPLE));
132 return 3;
133}
134
135static int test_globals (lua_State *L) {
136 lua_pushglobaltable(L);
137 return 1;
138}
139
140static int test_tonumber (lua_State *L) {
141 int isnum = 0;
142 lua_Number n = lua_tonumberx(L, 1, &isnum);
143 if (!isnum)
144 lua_pushnil(L);
145 else
146 lua_pushnumber(L, n);
147 return 1;
148}
149
150static int test_tointeger (lua_State *L) {
151 int isnum = 0;
152 lua_Integer n = lua_tointegerx(L, 1, &isnum);
153 if (!isnum)
154 lua_pushnil(L);
155 else
156 lua_pushinteger(L, n);
157 return 1;
158}
159
160static int test_len (lua_State *L) {
161 luaL_checkany(L, 1);
162 lua_len(L, 1);
163 lua_pushinteger(L, luaL_len(L, 1));
164 return 2;
165}
166
167static int test_copy (lua_State *L) {
168 int args = lua_gettop(L);
169 if (args >= 2) {
170 int i = 0;
171 for (i = args-1; i > 0; --i)
172 lua_copy(L, args, i);
173 }
174 return args;
175}
176
177/* need an address */
178static char const dummy = 0;
179
180static int test_rawxetp (lua_State *L) {
181 if (lua_gettop(L) > 0)
182 lua_pushvalue(L, 1);
183 else
184 lua_pushliteral(L, "hello again");
185 lua_rawsetp(L, LUA_REGISTRYINDEX, &dummy);
186 lua_settop(L, 0);
187 lua_rawgetp(L, LUA_REGISTRYINDEX, &dummy);
188 return 1;
189}
190
191static int test_udata (lua_State *L) {
192 const char *tname = luaL_optstring(L, 1, "utype1");
193 void *u1 = lua_newuserdata(L, 1);
194 int u1pos = lua_gettop(L);
195 void *u2 = lua_newuserdata(L, 1);
196 int u2pos = lua_gettop(L);
197 luaL_newmetatable(L, "utype1");
198 luaL_newmetatable(L, "utype2");
199 lua_pop(L, 2);
200 luaL_setmetatable(L, "utype2");
201 lua_pushvalue(L, u1pos);
202 luaL_setmetatable(L, "utype1");
203 lua_pop(L, 1);
204 (void)u1;
205 (void)u2;
206 lua_pushlightuserdata(L, luaL_testudata(L, u1pos, tname));
207 lua_pushlightuserdata(L, luaL_testudata(L, u2pos, tname));
208 luaL_getmetatable(L, "utype1");
209 lua_getfield(L, -1, "__name");
210 lua_replace(L, -2);
211 return 3;
212}
213
214static int test_subtable (lua_State *L) {
215 luaL_checktype(L, 1, LUA_TTABLE);
216 lua_settop(L, 1);
217 if (luaL_getsubtable(L, 1, "xxx")) {
218 lua_pushliteral(L, "oldtable");
219 } else {
220 lua_pushliteral(L, "newtable");
221 }
222 return 2;
223}
224
225static int test_uservalue (lua_State *L) {
226 void *udata = lua_newuserdata(L, 1);
227 int ui = lua_gettop(L);
228 lua_newtable(L);
229 lua_setuservalue(L, ui);
230 lua_getuservalue(L, ui);
231 (void)udata;
232 return 1;
233}
234
235static int test_upvalues (lua_State *L) {
236 int i = 1;
237 for (i = 1; i <= NUP; ++i)
238 lua_pushvalue(L, lua_upvalueindex(i));
239 return NUP;
240}
241
242static int test_tolstring (lua_State *L) {
243 size_t len = 0;
244 luaL_tolstring(L, 1, &len);
245 lua_pushinteger(L, (int)len);
246 return 2;
247}
248
249static int test_pushstring (lua_State *L) {
250 lua_pushstring(L, lua_pushliteral(L, "abc"));
251 lua_pushstring(L, lua_pushlstring(L, "abc", 2));
252 lua_pushstring(L, lua_pushlstring(L, NULL, 0));
253 lua_pushstring(L, lua_pushstring(L, "abc"));
254 lua_pushboolean(L, NULL == lua_pushstring(L, NULL));
255 return 10;
256}
257
258static int test_buffer (lua_State *L) {
259 luaL_Buffer b;
260 char *p = luaL_buffinitsize(L, &b, LUAL_BUFFERSIZE+1);
261 p[0] = 'a';
262 p[1] = 'b';
263 luaL_addsize(&b, 2);
264 luaL_addstring(&b, "c");
265 lua_pushliteral(L, "d");
266 luaL_addvalue(&b);
267 luaL_addchar(&b, 'e');
268 luaL_pushresult(&b);
269 return 1;
270}
271
272static int test_exec (lua_State *L) {
273 const char *cmd = luaL_checkstring(L, 1);
274 return luaL_execresult(L, system(cmd));
275}
276
277
278static const luaL_Reg funcs[] = {
279 { "isinteger", test_isinteger },
280 { "rotate", test_rotate },
281 { "strtonum", test_str2num },
282 { "requiref", test_requiref },
283 { "getseti", test_getseti },
284 { "newproxy", test_newproxy },
285 { "arith", test_arith },
286 { "compare", test_compare },
287 { "tonumber", test_tonumber },
288 { "tointeger", test_tointeger },
289 { "len", test_len },
290 { "copy", test_copy },
291 { "rawxetp", test_rawxetp },
292 { "subtable", test_subtable },
293 { "udata", test_udata },
294 { "uservalue", test_uservalue },
295 { "globals", test_globals },
296 { "tolstring", test_tolstring },
297 { "pushstring", test_pushstring },
298 { "buffer", test_buffer },
299 { "exec", test_exec },
300 { NULL, NULL }
301};
302
303static const luaL_Reg more_funcs[] = {
304 { "getupvalues", test_upvalues },
305 { "absindex", test_absindex },
306 { NULL, NULL }
307};
308
309
310int luaopen_testmod (lua_State *L) {
311 int i = 1;
312 luaL_newlib(L, funcs);
313 for (i = 1; i <= NUP; ++i)
314 lua_pushnumber(L, i);
315 luaL_setfuncs(L, more_funcs, NUP);
316 return 1;
317}
318