summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--GNUmakefile205
-rw-r--r--config.h.guess32
-rw-r--r--doc/luaossl.pdfbin289975 -> 300041 bytes
-rw-r--r--doc/luaossl.tex162
-rw-r--r--regress/53-csr-extensions.lua6
-rwxr-xr-xregress/82-bn_prepops-null-deref.lua2
-rw-r--r--src/GNUmakefile136
-rw-r--r--src/compat52.h160
-rw-r--r--src/openssl.c866
-rw-r--r--src/openssl.ocsp.basic.lua3
-rw-r--r--src/openssl.ocsp.response.lua3
-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
30 files changed, 7431 insertions, 371 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 6a20f27..81142cb 100644
--- a/doc/luaossl.pdf
+++ b/doc/luaossl.pdf
Binary files differ
diff --git a/doc/luaossl.tex b/doc/luaossl.tex
index 76821a1..7bb85df 100644
--- a/doc/luaossl.tex
+++ b/doc/luaossl.tex
@@ -286,8 +286,13 @@ field & type:default & description\\\hline
286 286
287.exp & number:65537 & RSA or Diffie-Hellman exponent \\ 287.exp & number:65537 & RSA or Diffie-Hellman exponent \\
288 288
289.dhparam & string & PEM encoded string with precomputed DH parameters \\
290
289.curve & string:prime192v1 & for elliptic curve keys, the OpenSSL string identifier of the curve 291.curve & string:prime192v1 & for elliptic curve keys, the OpenSSL string identifier of the curve
290\end{ctabular} 292\end{ctabular}
293
294The DH parameters ``dhparam'' will be generated on the fly, ``bits'' wide. This is a slow process, and especially for larger sizes, you would precompute those; for example: ``openssl dhparam -2 -out dh-2048.pem -outform PEM 2048''. Using the field ``dhparam'' overrides the ``bits'' field.
295
291\subsubsection[\fn{pkey.interpose}]{\fn{pkey.interpose($name$, $function$)}} 296\subsubsection[\fn{pkey.interpose}]{\fn{pkey.interpose($name$, $function$)}}
292 297
293Add or interpose a pkey class method. Returns the previous method, if any. 298Add or interpose a pkey class method. Returns the previous method, if any.
@@ -389,7 +394,19 @@ Binds the X.509 extension OpenSSL object.
389 394
390\subsubsection[\fn{extension.new}]{\fn{extension.new($name$, $value$ [, $data$])}} 395\subsubsection[\fn{extension.new}]{\fn{extension.new($name$, $value$ [, $data$])}}
391 396
392Returns a new X.509 extension. If $value$ is the string ``DER'' or ``critical,DER'', then $data$ is an ASN.1-encoded octet string. Otherwise, $name$ and $value$ are plain text strings in \href{https://www.openssl.org/docs/apps/x509v3_config.html#ARBITRARY_EXTENSIONS}{OpenSSL's arbitrary extension format}; and if specified, $data$ is an OpenSSL configuration string defining any referenced identifiers in $value$. 397Returns a new X.509 extension.
398If $value$ is the string ``DER'' or ``critical,DER'', then $data$ is an ASN.1-encoded octet string.
399Otherwise, $name$ and $value$ are plain text strings in \href{https://www.openssl.org/docs/apps/x509v3_config.html#ARBITRARY_EXTENSIONS}{OpenSSL's arbitrary extension format}; and if specified, $data$ is either an OpenSSL configuration string defining any referenced identifiers in $value$, or a table with members:
400
401\begin{ctabular}{ l | l | p{8cm} }
402field & type:default & description\\\hline
403.db & string:$nil$ & OpenSSL configuration string\\
404.issuer & \module{openssl.x509}:$nil$ & issuer certificate\\
405.subject & \module{openssl.x509}:$nil$ & subject certificate\\
406.request & \module{openssl.x509.csr}:$nil$ & certificate signing request\\
407.crl & \module{openssl.x509.crl}:$nil$ & certificate revocation list\\
408.flags & integer:$0$ & a bitwise combination of flags
409\end{ctabular}
393 410
394\subsubsection[\fn{extension.interpose}]{\fn{extension.interpose($name$, $function$)}} 411\subsubsection[\fn{extension.interpose}]{\fn{extension.interpose($name$, $function$)}}
395 412
@@ -528,7 +545,7 @@ Sets the basic constraints critical flag.
528 545
529\subsubsection[\fn{x509:addExtension}]{\fn{x509:addExtension($ext$)}} 546\subsubsection[\fn{x509:addExtension}]{\fn{x509:addExtension($ext$)}}
530 547
531Adds a copy of the \module{x509.extension} object to the certificate. 548Adds a copy of the \module{x509.extension} object to the certificate.
532 549
533\subsubsection[\fn{x509:getExtension}]{\fn{x509:getExtension($key$)}} 550\subsubsection[\fn{x509:getExtension}]{\fn{x509:getExtension($key$)}}
534 551
@@ -538,6 +555,10 @@ Returns a copy of the \module{x509.extension} object identified by $key$ where $
538 555
539Returns the integer count of the number of extensions. 556Returns the integer count of the number of extensions.
540 557
558\subsubsection[\fn{x509:getOCSP}]{\fn{x509:getOCSP()}}
559
560Returns the OCSP urls for the certificate.
561
541\subsubsection[\fn{x509:isIssuedBy}]{\fn{x509:isIssuedBy($issuer$)}} 562\subsubsection[\fn{x509:isIssuedBy}]{\fn{x509:isIssuedBy($issuer$)}}
542 563
543Returns a boolean according to whether the specified issuer---an \module{openssl.x509.name} object---signed the instance certificate. 564Returns a boolean according to whether the specified issuer---an \module{openssl.x509.name} object---signed the instance certificate.
@@ -554,6 +575,10 @@ Sets the public key component referenced by the \module{openssl.pkey} object $ke
554 575
555Returns the digest of the public key as a binary string. $type$ is an optional string describing the digest type, and defaults to ``sha1''. 576Returns the digest of the public key as a binary string. $type$ is an optional string describing the digest type, and defaults to ``sha1''.
556 577
578\subsubsection[\fn{x509:getSignatureName}]{\fn{x509:getSignatureName()}}
579
580Returns the type of signature used to sign the certificate as a string. e.g. ``RSA-SHA1''
581
557\subsubsection[\fn{x509:sign}]{\fn{x509:sign($key$ [, $type$])}} 582\subsubsection[\fn{x509:sign}]{\fn{x509:sign($key$ [, $type$])}}
558 583
559Signs and updates the instance certificate using the \module{openssl.pkey} $key$. $type$ is an optional string describing the digest type. See \module{pkey:sign}, regarding which types of digests are valid. If $type$ is omitted than a default type is used---``sha1'' for RSA keys, ``dss1'' for DSA keys, and ``ecdsa-with-SHA1'' for EC keys. 584Signs and updates the instance certificate using the \module{openssl.pkey} $key$. $type$ is an optional string describing the digest type. See \module{pkey:sign}, regarding which types of digests are valid. If $type$ is omitted than a default type is used---``sha1'' for RSA keys, ``dss1'' for DSA keys, and ``ecdsa-with-SHA1'' for EC keys.
@@ -674,7 +699,7 @@ Add the certificate identified by $serial$ to the revocation list. $serial$ shou
674 699
675\subsubsection[\fn{crl:addExtension}]{\fn{crl:addExtension($ext$)}} 700\subsubsection[\fn{crl:addExtension}]{\fn{crl:addExtension($ext$)}}
676 701
677Adds a copy of the \module{x509.extension} object to the revocation list. 702Adds a copy of the \module{x509.extension} object to the revocation list.
678 703
679\subsubsection[\fn{crl:getExtension}]{\fn{crl:getExtension($key$)}} 704\subsubsection[\fn{crl:getExtension}]{\fn{crl:getExtension($key$)}}
680 705
@@ -688,6 +713,10 @@ Returns the integer count of the number of extensions.
688 713
689Signs the instance CRL using the \module{openssl.pkey} $key$. 714Signs the instance CRL using the \module{openssl.pkey} $key$.
690 715
716\subsubsection[\fn{crl:verify}]{\fn{crl:verify($publickey$)}}
717
718Verifies the instance CRL using a public key.
719
691\subsubsection[\fn{crl:text}]{\fn{crl:text()}} 720\subsubsection[\fn{crl:text}]{\fn{crl:text()}}
692 721
693Returns a human-readable textual representation of the instance CRL. 722Returns a human-readable textual representation of the instance CRL.
@@ -763,6 +792,10 @@ Add or interpose a store class method. Returns the previous method, if any.
763 792
764Returns a PKCS \#12 binary encoded string. 793Returns a PKCS \#12 binary encoded string.
765 794
795\subsubsection[\fn{pkcs12.parse}]{\fn{pkcs12.parse($bag$[, $passphrase$])}}
796
797Parses a PKCS\#12 bag, presented as a binary string $bag$. The second parameter $passphrase$ is the passphrase required to decrypt the PKCS\#12 bag. The function returns three items; namely the key, certificate and the CA chain, as their respective objects. If an item is absent, it will be substituted with nil.
798
766\end{Module} 799\end{Module}
767 800
768 801
@@ -781,7 +814,7 @@ Returns a new context object. $protocol$ is an optional string identifier select
781\begin{ctabular}{ c | p{14cm} } 814\begin{ctabular}{ c | p{14cm} }
782\multicolumn{2}{c}{$protocol$ identifiers}\\\hline\hline 815\multicolumn{2}{c}{$protocol$ identifiers}\\\hline\hline
783name & \href{https://www.openssl.org/docs/ssl/SSL_CTX_new.html}{description} \\\hline 816name & \href{https://www.openssl.org/docs/ssl/SSL_CTX_new.html}{description} \\\hline
784TLS & Supports TLS 1.0 \emph{and above}. Internally uses \fn{SSLv23\_method} and disables SSLv2 and 817TLS & Supports TLS 1.0 \emph{and above}. Internally uses \fn{SSLv23\_method} and disables SSLv2 and
785SSLv3 using \texttt{SSL\_OP\_NO\_SSLv2} and \texttt{SSL\_OP\_NO\_SSLv3}.\\ 818SSLv3 using \texttt{SSL\_OP\_NO\_SSLv2} and \texttt{SSL\_OP\_NO\_SSLv3}.\\
786 819
787SSL & Supports SSL 3.0 \emph{and above}. Internally uses \fn{SSLv23\_method} and disables SSLv2 using \texttt{SSL\_OP\_NO\_SSLv2}.\\ 820SSL & Supports SSL 3.0 \emph{and above}. Internally uses \fn{SSLv23\_method} and disables SSLv2 using \texttt{SSL\_OP\_NO\_SSLv2}.\\
@@ -853,6 +886,23 @@ Returns the option flags of the context instance as an integer.
853 886
854Clears the option flags of the context instance. 887Clears the option flags of the context instance.
855 888
889\subsubsection[\fn{context:setStore}]{\fn{context:setStore($store$)}}
890
891Associate the \module{openssl.x509.store} object $store$ with $context$. Replaces any existing store.
892
893\subsubsection[\fn{context:getStore}]{\fn{context:getStore()}}
894
895Returns the \module{openssl.x509.store} object associated with $context$.
896
897\subsubsection[\fn{context:setParam}]{\fn{context:setParam($params$)}}
898
899Causes $context$ to inherit the parameters from the \module{openssl.x509.verify\_param} object $params$.
900Only parameters set in $params$ will take effect (others will stay unchanged).
901
902\subsubsection[\fn{context:getParam}]{\fn{context:getParam()}}
903
904Returns an \module{openssl.x509.verify\_param} object containing a copy of $context$'s parameters.
905
856\subsubsection[\fn{context:setVerify}]{\fn{context:setVerify([$mode$][, $depth$])}} 906\subsubsection[\fn{context:setVerify}]{\fn{context:setVerify([$mode$][, $depth$])}}
857 907
858Sets the verification mode flags and maximum validation chain depth. 908Sets the verification mode flags and maximum validation chain depth.
@@ -903,6 +953,26 @@ Sets the advertised ALPN protocols. $table$ is an array of protocol string ident
903 953
904\emph{Only supported since OpenSSL 1.0.2.} 954\emph{Only supported since OpenSSL 1.0.2.}
905 955
956\subsubsection[\fn{context:setAlpnSelect}]{\fn{context:setAlpnSelect($cb$)}}
957
958Sets the callback used to select an ALPN protocol. $cb$ should be a function that takes two arguments: an \module{openssl.ssl} object and a table containing a sequence of ALPN protocol strings; it should return the ALPN protocol string it selected or $nil$ to select none of them.
959
960\emph{Only supported since OpenSSL 1.0.2.}
961
962\subsubsection[\fn{context:setTLSextStatusType}]{\fn{context:setTLSextStatusType($type$)}}
963
964Sets the default TLS extension status for SSL objects derived from this context.
965See \fn{ssl:setTLSextStatusType}
966
967\emph{Only supported since OpenSSL 1.1.0.}
968
969\subsubsection[\fn{context:getTLSextStatusType}]{\fn{context:getTLSextStatusType()}}
970
971Gets the default TLS extension status for SSL objects derived from this context as a string.
972See \fn{ssl:getTLSextStatusType}
973
974\emph{Only supported since OpenSSL 1.1.0.}
975
906\end{Module} 976\end{Module}
907 977
908 978
@@ -917,6 +987,10 @@ A table mapping OpenSSL named constants. Includes all constants provided by \mod
917\subsubsection[\fn{ssl.interpose}]{\fn{ssl.interpose($name$, $function$)}} 987\subsubsection[\fn{ssl.interpose}]{\fn{ssl.interpose($name$, $function$)}}
918Add or interpose an ssl class method. Returns the previous method, if any. 988Add or interpose an ssl class method. Returns the previous method, if any.
919 989
990\subsubsection[\fn{ssl:setContext}]{\fn{ssl:setContext($context$)}}
991
992Replaces the \module{openssl.ssl.context} used by $ssl$ with $context$.
993
920\subsubsection[\fn{ssl:setOptions}]{\fn{ssl:setOptions($flags$)}} 994\subsubsection[\fn{ssl:setOptions}]{\fn{ssl:setOptions($flags$)}}
921 995
922Adds the option flags of the SSL connection instance. See \fn{openssl.ssl.context:setOptions}. 996Adds the option flags of the SSL connection instance. See \fn{openssl.ssl.context:setOptions}.
@@ -929,6 +1003,30 @@ Returns the option flags of the SSL connection instance. See \fn{openssl.ssl.con
929 1003
930Clears the option flags of the SSL connection instance. See \fn{openssl.ssl.context:clearOptions}. 1004Clears the option flags of the SSL connection instance. See \fn{openssl.ssl.context:clearOptions}.
931 1005
1006\subsubsection[\fn{ssl:setVerify}]{\fn{ssl:setVerify([$mode$][, $depth$])}}
1007
1008Sets the verification mode flags and maximum validation chain depth.
1009See \fn{openssl.ssl.context:setVerify}.
1010
1011\subsubsection[\fn{ssl:getVerify}]{\fn{ssl:getVerify()}}
1012
1013Returns two values: the bitwise verification mode flags, and the maximum validation depth.
1014See \fn{openssl.ssl.context:getVerify}.
1015
1016\subsubsection[\fn{ssl:getVerifyResult}]{\fn{ssl:getVerifyResult()}}
1017
1018Returns two values: the integer verification result code and the string representation of that code.
1019
1020\subsubsection[\fn{ssl:setCertificate}]{\fn{ssl:setCertificate($crt$)}}
1021
1022Sets the X.509 certificate \module{openssl.x509} object $crt$ to send during SSL connection instance handshakes.
1023See \fn{openssl.ssl.context:setCertificate}.
1024
1025\subsubsection[\fn{ssl:setPrivateKey}]{\fn{ssl:setPrivateKey($key$)}}
1026
1027Sets the private key \module{openssl.pkey} object $key$ for use during SSL connection instance handshakes.
1028See \fn{openssl.ssl.context:setPrivateKey}.
1029
932\subsubsection[\fn{ssl:getPeerCertificate}]{\fn{ssl:getPeerCertificate()}} 1030\subsubsection[\fn{ssl:getPeerCertificate}]{\fn{ssl:getPeerCertificate()}}
933 1031
934Returns the X.509 peer certificate as an \module{openssl.x509} object. If no peer certificate is available, returns $nil$. 1032Returns the X.509 peer certificate as an \module{openssl.x509} object. If no peer certificate is available, returns $nil$.
@@ -939,7 +1037,7 @@ Similar to :getPeerCertifiate, but returns the entire chain sent by the peer as
939 1037
940\subsubsection[\fn{ssl:getCipherInfo}]{\fn{ssl:getCipherInfo()}} 1038\subsubsection[\fn{ssl:getCipherInfo}]{\fn{ssl:getCipherInfo()}}
941 1039
942Returns a table of information on the current cipher. 1040Returns a table of information on the current cipher.
943 1041
944\begin{tabular}{ c | l } 1042\begin{tabular}{ c | l }
945field & description\\\hline 1043field & description\\\hline
@@ -996,6 +1094,30 @@ Sets the advertised ALPN protocols. $table$ is an array of protocol string ident
996 1094
997\emph{Only supported since OpenSSL 1.0.2.} 1095\emph{Only supported since OpenSSL 1.0.2.}
998 1096
1097\subsubsection[\fn{ssl:setTLSextStatusType}]{\fn{ssl:setTLSextStatusType($type$)}}
1098
1099Sets the TLS extension status.
1100
1101Only the $type$ ``ocsp'' is currently supported, this is used by a client to request that a server sends a stapled OCSP response as part of the TLS handshake.
1102
1103See also: \fn{context:setTLSextStatusType()}
1104
1105\subsubsection[\fn{ssl:getTLSextStatusType}]{\fn{ssl:getTLSextStatusType()}}
1106
1107Gets the TLS extension status. As set by \fn{ssl:setTLSextStatusType} or \fn{context:setTLSextStatusType}.
1108
1109Only the type ``ocsp'' is currently known.
1110
1111\emph{Only supported since OpenSSL 1.1.0.}
1112
1113\subsubsection[\fn{ssl:setTLSextStatusOCSPResp}]{\fn{ssl:setTLSextStatusOCSPResp($or$)}}
1114
1115Sets an \module{openssl.ocsp.response}. Used by a server to staple an OCSP response into a TLS handshake.
1116
1117\subsubsection[\fn{ssl:getTLSextStatusOCSPResp}]{\fn{ssl:getTLSextStatusOCSPResp()}}
1118
1119Returns the \module{openssl.ocsp.response} associated with the ssl object (or $nil$ if one has not been set).
1120
999\end{Module} 1121\end{Module}
1000 1122
1001 1123
@@ -1078,6 +1200,36 @@ Update the cipher with the specified string(s). Returns the final output string
1078\end{Module} 1200\end{Module}
1079 1201
1080 1202
1203\begin{Module}{openssl.ocsp.response}
1204
1205Binds OpenSSL's \texttt{OCSP\_RESPONSE} object.
1206
1207\subsubsection[\fn{response:getBasic}]{\fn{response:getBasic()}}
1208
1209Returns a \module{openssl.ocsp.basic} representation of the object contained within the OCSP response.
1210
1211\subsubsection[\fn{response:tostring}]{\fn{response:tostring()}}
1212
1213Returns a human readable description of the OCSP response as a string.
1214
1215\subsubsection[\fn{response:toPEM}]{\fn{response:toPEM()}}
1216
1217Returns the OCSP response as a PEM encoded string.
1218
1219\end{Module}
1220
1221
1222\begin{Module}{openssl.ocsp.basic}
1223
1224Binds OpenSSL's \texttt{OCSP\_BASICRESP} object.
1225
1226\subsubsection[\fn{basic:verify}]{\fn{basic:verify([$certs$ [, $store$[, $flags$]]])}}
1227
1228Verifies that the OCSP response is signed by a certificate in the \module{openssl.x509.chain} $certs$ or a trusted certificate in \module{openssl.x509.store} $store$.
1229
1230\end{Module}
1231
1232
1081\begin{Module}{openssl.rand} 1233\begin{Module}{openssl.rand}
1082 1234
1083Binds OpenSSL's random number interfaces. 1235Binds OpenSSL's random number interfaces.
diff --git a/regress/53-csr-extensions.lua b/regress/53-csr-extensions.lua
index 38346da..6b7d60c 100644
--- a/regress/53-csr-extensions.lua
+++ b/regress/53-csr-extensions.lua
@@ -131,9 +131,9 @@ do
131 checknames(csr:getSubjectAlt(), expected) 131 checknames(csr:getSubjectAlt(), expected)
132 -- check after a round-trip through PEM 132 -- check after a round-trip through PEM
133 checknames(x509_csr.new(tostring(csr)):getSubjectAlt(), expected) 133 checknames(x509_csr.new(tostring(csr)):getSubjectAlt(), expected)
134end 134end
135 135
136-- adding altnames where none existed 136-- adding altnames where none existed
137do 137do
138 local expected = { 138 local expected = {
139 name = { 139 name = {
@@ -155,7 +155,7 @@ do
155 csr:setSubjectAlt(gn) 155 csr:setSubjectAlt(gn)
156 csr:setPublicKey(key) 156 csr:setPublicKey(key)
157 csr:sign(key) 157 csr:sign(key)
158 158
159 checknames(csr:getSubject(), expected.name) 159 checknames(csr:getSubject(), expected.name)
160 checknames(csr:getSubjectAlt(), expected.altname) 160 checknames(csr:getSubjectAlt(), expected.altname)
161 161
diff --git a/regress/82-bn_prepops-null-deref.lua b/regress/82-bn_prepops-null-deref.lua
index 6a1d617..47757d2 100755
--- a/regress/82-bn_prepops-null-deref.lua
+++ b/regress/82-bn_prepops-null-deref.lua
@@ -14,7 +14,7 @@
14-- bn_prepops(L, &r, &a, NULL, 1); 14-- bn_prepops(L, &r, &a, NULL, 1);
15-- ... 15-- ...
16-- } 16-- }
17-- 17--
18-- Caught by clang static analyzer. This was introduced with a patch adding 18-- Caught by clang static analyzer. This was introduced with a patch adding
19-- the :sqr method. This should have been caught sooner as the :sqr method 19-- the :sqr method. This should have been caught sooner as the :sqr method
20-- couldn't have possibly ever worked--a missing or non-numeric second 20-- couldn't have possibly ever worked--a missing or non-numeric second
diff --git a/src/GNUmakefile b/src/GNUmakefile
index 015a93c..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)/../..)) -DLUA_COMPAT_APIINTCASTS -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,13 +65,13 @@ 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 \
93 $$(DESTDIR)$(3)/openssl/auxlib.lua \ 71 $$(DESTDIR)$(3)/openssl/auxlib.lua \
94 $$(DESTDIR)$(3)/openssl/bignum.lua \ 72 $$(DESTDIR)$(3)/openssl/bignum.lua \
73 $$(DESTDIR)$(3)/openssl/ocsp/basic.lua \
74 $$(DESTDIR)$(3)/openssl/ocsp/response.lua \
95 $$(DESTDIR)$(3)/openssl/pkey.lua \ 75 $$(DESTDIR)$(3)/openssl/pkey.lua \
96 $$(DESTDIR)$(3)/openssl/pubkey.lua \ 76 $$(DESTDIR)$(3)/openssl/pubkey.lua \
97 $$(DESTDIR)$(3)/openssl/x509.lua \ 77 $$(DESTDIR)$(3)/openssl/x509.lua \
@@ -114,42 +94,34 @@ MODS$(1)_$(d) = \
114 94
115.SECONDARY: liblua$(1)-openssl-install openssl$(1)-install 95.SECONDARY: liblua$(1)-openssl-install openssl$(1)-install
116 96
117$$(DESTDIR)$(2)/_openssl.so: $$(d)/$(1)/openssl.so 97liblua$(1)-openssl-install openssl$(1)-install: $$(MODS$(1)_$$(d))
118 $$(MKDIR) -p $$(@D)
119 $$(CP) -fp $$< $$@
120 98
121$$(DESTDIR)$(3)/openssl.lua: $$(d)/openssl.lua 99$$(DESTDIR)$(2)/_openssl.so: $$(d)/$(1)/openssl.so
122 $$(LUAC$(1)_$(d)) -p $$<
123 $$(MKDIR) -p $$(@D) 100 $$(MKDIR) -p $$(@D)
124 $$(CP) -p $$< $$@ 101 $$(CP) -p $$< $$@
125 102
126$$(DESTDIR)$(3)/openssl/%.lua: $$(d)/openssl.%.lua 103$$(DESTDIR)$(3)/%.lua: $$(d)/%.lua
127 $$(LUAC$(1)_$(d)) -p $$< 104 $$(LUAC$(subst .,,$(1))) -p $$<
128 $$(MKDIR) -p $$(@D) 105 $$(MKDIR) -p $$(@D)
129 $$(CP) -p $$< $$@ 106 $$(CP) -p $$< $$@
130 107
131# pubkey.lua used to be symbolic link to pkey.lua, but that caused packaging 108$$(DESTDIR)$(3)/openssl/%.lua: $$(d)/openssl.%.lua
132# headaches. Now it's a stub, but the cp -p in the inference rule will copy 109 $$(LUAC$(subst .,,$(1))) -p $$<
133# to the target of the symbolic link, so we need a special install rule to
134# clean up the mess.
135$$(DESTDIR)$(3)/openssl/pubkey.lua: $$(d)/openssl.pubkey.lua
136 $$(LUAC$(1)_$(d)) -p $$<
137 $$(MKDIR) -p $$(@D) 110 $$(MKDIR) -p $$(@D)
138 $$(RM) -f $$@
139 $$(CP) -p $$< $$@ 111 $$(CP) -p $$< $$@
140 112
141$$(DESTDIR)$(3)/openssl/x509/%.lua: $$(d)/openssl.x509.%.lua 113$$(DESTDIR)$(3)/openssl/ocsp/%.lua: $$(d)/ocsp.%.lua
142 $$(LUAC$(1)_$(d)) -p $$< 114 $$(LUAC$(subst .,,$(1))) -p $$<
143 $$(MKDIR) -p $$(@D) 115 $$(MKDIR) -p $$(@D)
144 $$(CP) -p $$< $$@ 116 $$(CP) -p $$< $$@
145 117
146$$(DESTDIR)$(3)/openssl/ssl/%.lua: $$(d)/openssl.ssl.%.lua 118$$(DESTDIR)$(3)/openssl/x509/%.lua: $$(d)/x509.%.lua
147 $$(LUAC$(1)_$(d)) -p $$< 119 $$(LUAC$(subst .,,$(1))) -p $$<
148 $$(MKDIR) -p $$(@D) 120 $$(MKDIR) -p $$(@D)
149 $$(CP) -p $$< $$@ 121 $$(CP) -p $$< $$@
150 122
151$$(DESTDIR)$(3)/openssl/ssl/%.lua: $$(d)/openssl.ssl.%.lua 123$$(DESTDIR)$(3)/openssl/ssl/%.lua: $$(d)/ssl.%.lua
152 $$(LUAC$(1)_$(d)) -p $$< 124 $$(LUAC$(subst .,,$(1))) -p $$<
153 $$(MKDIR) -p $$(@D) 125 $$(MKDIR) -p $$(@D)
154 $$(CP) -p $$< $$@ 126 $$(CP) -p $$< $$@
155 127
@@ -159,6 +131,7 @@ liblua$(1)-openssl-install openssl$(1)-install: $$(MODS$(1)_$$(d))
159 131
160liblua$(1)-openssl-uninstall openssl$(1)-uninstall: 132liblua$(1)-openssl-uninstall openssl$(1)-uninstall:
161 $$(RM) -f $$(MODS$(1)_$(d)) 133 $$(RM) -f $$(MODS$(1)_$(d))
134 -$$(RMDIR) $$(DESTDIR)$(3)/openssl/ocsp
162 -$$(RMDIR) $$(DESTDIR)$(3)/openssl/x509 135 -$$(RMDIR) $$(DESTDIR)$(3)/openssl/x509
163 -$$(RMDIR) $$(DESTDIR)$(3)/openssl/ssl 136 -$$(RMDIR) $$(DESTDIR)$(3)/openssl/ssl
164 -$$(RMDIR) $$(DESTDIR)$(3)/openssl 137 -$$(RMDIR) $$(DESTDIR)$(3)/openssl
@@ -166,31 +139,24 @@ liblua$(1)-openssl-uninstall openssl$(1)-uninstall:
166endef # INSTALL_$(d) 139endef # INSTALL_$(d)
167 140
168$(eval $(call INSTALL_$(d),5.1,$$(lua51cpath),$$(lua51path))) 141$(eval $(call INSTALL_$(d),5.1,$$(lua51cpath),$$(lua51path)))
169
170$(eval $(call INSTALL_$(d),5.2,$$(lua52cpath),$$(lua52path))) 142$(eval $(call INSTALL_$(d),5.2,$$(lua52cpath),$$(lua52path)))
171
172$(eval $(call INSTALL_$(d),5.3,$$(lua53cpath),$$(lua53path))) 143$(eval $(call INSTALL_$(d),5.3,$$(lua53cpath),$$(lua53path)))
173 144
174ifneq "$(filter $(abspath $(d)/..)/%, $(abspath $(firstword $(MAKEFILE_LIST))))" "" 145ifneq "$(filter $(abspath $(d)/..)/%, $(abspath $(firstword $(MAKEFILE_LIST))))" ""
146
175.SECONDARY: install5.1 install5.2 install5.3 install 147.SECONDARY: install5.1 install5.2 install5.3 install
176 148
177install5.1: liblua5.1-openssl-install 149install5.1: liblua5.1-openssl-install
178
179install5.2: liblua5.2-openssl-install 150install5.2: liblua5.2-openssl-install
180
181install5.3: liblua5.3-openssl-install 151install5.3: liblua5.3-openssl-install
182 152install: $(foreach API,$(strip $(LUA_APIS)),install$(API))
183install: install5.1 install5.2
184 153
185.PHONY: uninstall5.1 uninstall5.2 uninstall5.3 uninstall 154.PHONY: uninstall5.1 uninstall5.2 uninstall5.3 uninstall
186 155
187uninstall5.1: liblua5.1-openssl-uninstall 156uninstall5.1: liblua5.1-openssl-uninstall
188
189uninstall5.2: liblua5.2-openssl-uninstall 157uninstall5.2: liblua5.2-openssl-uninstall
190
191uninstall5.3: liblua5.3-openssl-uninstall 158uninstall5.3: liblua5.3-openssl-uninstall
192 159uninstall: $(foreach API,$(strip $(LUA_APIS)),uninstall$(API))
193uninstall: uninstall5.1 uninstall5.2
194 160
195endif 161endif
196 162
@@ -201,7 +167,7 @@ endif
201.PHONY: $(d)/clean $(d)/clean~ clean clean~ 167.PHONY: $(d)/clean $(d)/clean~ clean clean~
202 168
203$(d)/clean: 169$(d)/clean:
204 $(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
205 171
206$(d)/clean~: $(d)/clean 172$(d)/clean~: $(d)/clean
207 $(RM) -f $(@D)/*~ 173 $(RM) -f $(@D)/*~
@@ -218,27 +184,27 @@ clean~: $(d)/clean~
218 184
219$(d)/help: 185$(d)/help:
220 @echo 186 @echo
221 @echo "ext/ targets:" 187 @echo "src/ targets:"
222 @echo "" 188 @echo ""
223 @echo " all - build all binary targets" 189 @echo " all - build all API targets"
224 @echo "openssl - invokes openssl5.1 and openssl5.2" 190 @echo " all5.1 - build 5.1/openssl.so"
225 @echo "openssl5.1 - build 5.1/openssl.so" 191 @echo " all5.2 - build 5.2/openssl.so"
226 @echo "openssl5.2 - build 5.2/openssl.so" 192 @echo " all5.3 - build 5.3/openssl.so"
227 @echo "openssl5.3 - build 5.3/openssl.so" 193 @echo " install - install all API targets"
228 @echo "install - invokes install5.1 and install5.2" 194 @echo " install5.1 - install openssl Lua 5.1 modules"
229 @echo "install5.1 - install openssl Lua 5.1 modules" 195 @echo " install5.2 - install openssl Lua 5.2 modules"
230 @echo "install5.2 - install openssl Lua 5.2 modules" 196 @echo " install5.3 - install openssl Lua 5.3 modules"
231 @echo "install5.3 - install openssl Lua 5.3 modules" 197 @echo " uninstall - uninstall all API targets"
232 @echo "uninstall - invokes uninstall5.1 and uninstall5.2"
233 @echo "uninstall5.1 - uninstall openssl Lua 5.1 modules" 198 @echo "uninstall5.1 - uninstall openssl Lua 5.1 modules"
234 @echo "uninstall5.2 - uninstall openssl Lua 5.2 modules" 199 @echo "uninstall5.2 - uninstall openssl Lua 5.2 modules"
235 @echo "uninstall5.3 - uninstall openssl Lua 5.3 modules" 200 @echo "uninstall5.3 - uninstall openssl Lua 5.3 modules"
236 @echo " clean - rm binary targets, object files, debugging symbols, etc" 201 @echo " clean - rm binary targets, object files, debugging symbols, etc"
237 @echo " clean~ - clean + rm *~" 202 @echo " clean~ - clean + rm *~"
238 @echo " help - echo this help message" 203 @echo " help - echo this help message"
239 @echo "" 204 @echo ""
240 @echo "Some important Make variables:" 205 @echo "Some important Make variables:"
241 @echo "" 206 @echo ""
207 @echo ' LUA_APIS - default Lua APIs to target ($(LUA_APIS))'
242 @echo " prefix - path to install root ($(value prefix))" 208 @echo " prefix - path to install root ($(value prefix))"
243 @echo ' lua51path - install path for Lua 5.1 modules ($(value lua51path))' 209 @echo ' lua51path - install path for Lua 5.1 modules ($(value lua51path))'
244 @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))'
@@ -247,6 +213,10 @@ $(d)/help:
247 @echo ' lua53path - install path for Lua 5.3 modules ($(value lua53path))' 213 @echo ' lua53path - install path for Lua 5.3 modules ($(value lua53path))'
248 @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))'
249 @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 ""
250 @echo "(NOTE: all the common GNU-style paths are supported, including" 220 @echo "(NOTE: all the common GNU-style paths are supported, including"
251 @echo "prefix, bindir, libdir, datadir, includedir, and DESTDIR.)" 221 @echo "prefix, bindir, libdir, datadir, includedir, and DESTDIR.)"
252 @echo "" 222 @echo ""
diff --git a/src/compat52.h b/src/compat52.h
deleted file mode 100644
index 0057b3c..0000000
--- a/src/compat52.h
+++ /dev/null
@@ -1,160 +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#if LUA_VERSION_NUM < 502
27
28#define LUA_OK 0
29
30
31static void luaL_setmetatable(lua_State *L, const char *tname) {
32 luaL_getmetatable(L, tname);
33 lua_setmetatable(L, -2);
34} /* luaL_setmetatable() */
35
36
37static int lua_absindex(lua_State *L, int idx) {
38 return (idx > 0 || idx <= LUA_REGISTRYINDEX)? idx : lua_gettop(L) + idx + 1;
39} /* lua_absindex() */
40
41
42static void *luaL_testudata(lua_State *L, int arg, const char *tname) {
43 void *p = lua_touserdata(L, arg);
44 int eq;
45
46 if (!p || !lua_getmetatable(L, arg))
47 return 0;
48
49 luaL_getmetatable(L, tname);
50 eq = lua_rawequal(L, -2, -1);
51 lua_pop(L, 2);
52
53 return (eq)? p : 0;
54} /* luaL_testudate() */
55
56
57static void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup) {
58 int i, t = lua_absindex(L, -1 - nup);
59
60 for (; l->name; l++) {
61 for (i = 0; i < nup; i++)
62 lua_pushvalue(L, -nup);
63 lua_pushcclosure(L, l->func, nup);
64 lua_setfield(L, t, l->name);
65 }
66
67 lua_pop(L, nup);
68} /* luaL_setfuncs() */
69
70
71#define luaL_newlibtable(L, l) \
72 lua_createtable(L, 0, (sizeof (l) / sizeof *(l)) - 1)
73
74#define luaL_newlib(L, l) \
75 (luaL_newlibtable((L), (l)), luaL_setfuncs((L), (l), 0))
76
77
78static void luaL_requiref(lua_State *L, const char *modname, lua_CFunction openf, int glb) {
79 lua_pushcfunction(L, openf);
80 lua_pushstring(L, modname);
81 lua_call(L, 1, 1);
82
83 lua_getglobal(L, "package");
84 lua_getfield(L, -1, "loaded");
85 lua_pushvalue(L, -3);
86 lua_setfield(L, -2, modname);
87
88 lua_pop(L, 2);
89
90 if (glb) {
91 lua_pushvalue(L, -1);
92 lua_setglobal(L, modname);
93 }
94} /* luaL_requiref() */
95
96
97#define lua_resume(L, from, nargs) lua_resume((L), (nargs))
98
99
100static void lua_rawgetp(lua_State *L, int index, const void *p) {
101 index = lua_absindex(L, index);
102 lua_pushlightuserdata(L, (void *)p);
103 lua_rawget(L, index);
104} /* lua_rawgetp() */
105
106static void lua_rawsetp(lua_State *L, int index, const void *p) {
107 index = lua_absindex(L, index);
108 lua_pushlightuserdata(L, (void *)p);
109 lua_pushvalue(L, -2);
110 lua_rawset(L, index);
111 lua_pop(L, 1);
112} /* lua_rawsetp() */
113
114
115#ifndef LUA_UNSIGNED
116#define LUA_UNSIGNED unsigned
117#endif
118
119typedef LUA_UNSIGNED lua_Unsigned;
120
121
122static void lua_pushunsigned(lua_State *L, lua_Unsigned n) {
123 lua_pushnumber(L, (lua_Number)n);
124} /* lua_pushunsigned() */
125
126static lua_Unsigned luaL_checkunsigned(lua_State *L, int arg) {
127 return (lua_Unsigned)luaL_checknumber(L, arg);
128} /* luaL_checkunsigned() */
129
130
131static lua_Unsigned luaL_optunsigned(lua_State *L, int arg, lua_Unsigned def) {
132 return (lua_Unsigned)luaL_optnumber(L, arg, (lua_Number)def);
133} /* luaL_optunsigned() */
134
135
136#ifndef LUA_FILEHANDLE /* Not defined by earlier LuaJIT releases */
137#define LUA_FILEHANDLE "FILE*"
138#endif
139
140/*
141 * Lua 5.1 userdata is a simple FILE *, while LuaJIT is a struct with the
142 * first member a FILE *, similar to Lua 5.2.
143 */
144typedef struct luaL_Stream {
145 FILE *f;
146} luaL_Stream;
147
148
149#define lua_rawlen(...) lua_objlen(__VA_ARGS__)
150
151
152#define lua_pushstring(...) lua52_pushstring(__VA_ARGS__)
153
154static const char *lua52_pushstring(lua_State *L, const char *s) {
155 (lua_pushstring)(L, s);
156 return lua_tostring(L, -1);
157} /* lua52_pushstring() */
158
159
160#endif /* LUA_VERSION_NUM < 502 */
diff --git a/src/openssl.c b/src/openssl.c
index 8217deb..a3e5637 100644
--- a/src/openssl.c
+++ b/src/openssl.c
@@ -69,14 +69,13 @@
69#include <openssl/hmac.h> 69#include <openssl/hmac.h>
70#include <openssl/rand.h> 70#include <openssl/rand.h>
71#include <openssl/des.h> 71#include <openssl/des.h>
72#include <openssl/ocsp.h>
72 73
73#include <lua.h> 74#include <lua.h>
74#include <lualib.h> 75#include <lualib.h>
75#include <lauxlib.h> 76#include <lauxlib.h>
76 77
77#if LUA_VERSION_NUM < 502 78#include "../vendor/compat53/c-api/compat-5.3.h"
78#include "compat52.h"
79#endif
80 79
81#define GNUC_2VER(M, m, p) (((M) * 10000) + ((m) * 100) + (p)) 80#define GNUC_2VER(M, m, p) (((M) * 10000) + ((m) * 100) + (p))
82#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)))
@@ -270,6 +269,10 @@
270#define HAVE_SSL_CTX_SET_ALPN_SELECT_CB HAVE_SSL_CTX_SET_ALPN_PROTOS 269#define HAVE_SSL_CTX_SET_ALPN_SELECT_CB HAVE_SSL_CTX_SET_ALPN_PROTOS
271#endif 270#endif
272 271
272#ifndef HAVE_SSL_CTX_SET_TLSEXT_SERVERNAME_CALLBACK
273#define HAVE_SSL_CTX_SET_TLSEXT_SERVERNAME_CALLBACK OPENSSL_PREREQ(1,0,0)
274#endif
275
273#ifndef HAVE_SSL_CTX_SET1_CERT_STORE 276#ifndef HAVE_SSL_CTX_SET1_CERT_STORE
274#define HAVE_SSL_CTX_SET1_CERT_STORE (HAVE_SSL_CTX_set1_cert_store || 0) /* backwards compatible with old macro name */ 277#define HAVE_SSL_CTX_SET1_CERT_STORE (HAVE_SSL_CTX_set1_cert_store || 0) /* backwards compatible with old macro name */
275#endif 278#endif
@@ -282,6 +285,14 @@
282#define HAVE_SSL_CTX_CERT_STORE (!OPENSSL_PREREQ(1,1,0)) 285#define HAVE_SSL_CTX_CERT_STORE (!OPENSSL_PREREQ(1,1,0))
283#endif 286#endif
284 287
288#ifndef HAVE_SSL_CTX_SET_TLSEXT_STATUS_TYPE
289#define HAVE_SSL_CTX_SET_TLSEXT_STATUS_TYPE OPENSSL_PREREQ(1,1,0)
290#endif
291
292#ifndef HAVE_SSL_CTX_GET_TLSEXT_STATUS_TYPE
293#define HAVE_SSL_CTX_GET_TLSEXT_STATUS_TYPE OPENSSL_PREREQ(1,1,0)
294#endif
295
285#ifndef HAVE_SSL_GET0_ALPN_SELECTED 296#ifndef HAVE_SSL_GET0_ALPN_SELECTED
286#define HAVE_SSL_GET0_ALPN_SELECTED HAVE_SSL_CTX_SET_ALPN_PROTOS 297#define HAVE_SSL_GET0_ALPN_SELECTED HAVE_SSL_CTX_SET_ALPN_PROTOS
287#endif 298#endif
@@ -302,6 +313,14 @@
302#define HAVE_SSL_SET1_PARAM OPENSSL_PREREQ(1,0,2) 313#define HAVE_SSL_SET1_PARAM OPENSSL_PREREQ(1,0,2)
303#endif 314#endif
304 315
316#ifndef HAVE_SSL_GET_CLIENT_RANDOM
317#define HAVE_SSL_GET_CLIENT_RANDOM OPENSSL_PREREQ(1,1,0)
318#endif
319
320#ifndef HAVE_SSL_GET_TLSEXT_STATUS_TYPE
321#define HAVE_SSL_GET_TLSEXT_STATUS_TYPE OPENSSL_PREREQ(1,1,0)
322#endif
323
305#ifndef HAVE_SSL_UP_REF 324#ifndef HAVE_SSL_UP_REF
306#define HAVE_SSL_UP_REF OPENSSL_PREREQ(1,1,0) 325#define HAVE_SSL_UP_REF OPENSSL_PREREQ(1,1,0)
307#endif 326#endif
@@ -314,6 +333,10 @@
314#define HAVE_SSLV2_SERVER_METHOD (!OPENSSL_PREREQ(1,1,0) && !defined OPENSSL_NO_SSL2) 333#define HAVE_SSLV2_SERVER_METHOD (!OPENSSL_PREREQ(1,1,0) && !defined OPENSSL_NO_SSL2)
315#endif 334#endif
316 335
336#ifndef HAVE_X509_GET_SIGNATURE_NID
337#define HAVE_X509_GET_SIGNATURE_NID OPENSSL_PREREQ(1,0,2)
338#endif
339
317#ifndef HAVE_X509_STORE_REFERENCES 340#ifndef HAVE_X509_STORE_REFERENCES
318#define HAVE_X509_STORE_REFERENCES (!OPENSSL_PREREQ(1,1,0)) 341#define HAVE_X509_STORE_REFERENCES (!OPENSSL_PREREQ(1,1,0))
319#endif 342#endif
@@ -392,6 +415,8 @@
392#define DIGEST_CLASS "EVP_MD_CTX*" 415#define DIGEST_CLASS "EVP_MD_CTX*"
393#define HMAC_CLASS "HMAC_CTX*" 416#define HMAC_CLASS "HMAC_CTX*"
394#define CIPHER_CLASS "EVP_CIPHER_CTX*" 417#define CIPHER_CLASS "EVP_CIPHER_CTX*"
418#define OCSP_RESPONSE_CLASS "OCSP_RESPONSE*"
419#define OCSP_BASICRESP_CLASS "OCSP_BASICRESP*"
395 420
396 421
397#if __GNUC__ 422#if __GNUC__
@@ -669,6 +694,44 @@ static void *loadfield_udata(lua_State *L, int index, const char *k, const char
669} /* loadfield_udata() */ 694} /* loadfield_udata() */
670 695
671 696
697/* Forward declaration */
698static SSL *ssl_push(lua_State *, SSL *);
699
700/* push an ssl object into lua in a way that is safe from OOM
701 * Lua 5.1 does not support normally returning values from lua_cpcall
702 * to return a value, we instead return it via an error object
703 */
704static int ssl_pushsafe_helper(lua_State *L) {
705 ssl_push(L, lua_touserdata(L, 1));
706#if LUA_VERSION_NUM <= 501
707 return lua_error(L);
708#else
709 return 1;
710#endif
711}
712
713static int ssl_pushsafe(lua_State *L, SSL *ssl) {
714 int status;
715#if LUA_VERSION_NUM <= 501
716 status = lua_cpcall(L, ssl_pushsafe_helper, ssl);
717 if (status == LUA_ERRRUN)
718 status = LUA_OK;
719 else if (status == LUA_OK)
720 /* this should be impossible */
721 status = LUA_ERRRUN;
722 else
723 lua_pop(L, 1);
724#else
725 lua_pushcfunction(L, ssl_pushsafe_helper);
726 lua_pushlightuserdata(L, ssl);
727 status = lua_pcall(L, 1, 1, 0);
728 if (status != LUA_OK)
729 lua_pop(L, 1);
730#endif
731 return status;
732}
733
734
672/* 735/*
673 * Auxiliary C routines 736 * Auxiliary C routines
674 * 737 *
@@ -920,7 +983,7 @@ static void auxL_pushinteger(lua_State *L, auxL_Integer i) {
920 } 983 }
921} /* auxL_pushinteger() */ 984} /* auxL_pushinteger() */
922 985
923NOTUSED static void auxL_pushunsigned(lua_State *L, auxL_Unsigned i) { 986static void auxL_pushunsigned(lua_State *L, auxL_Unsigned i) {
924 if (i <= lua_IntegerMax) { 987 if (i <= lua_IntegerMax) {
925 lua_pushinteger(L, i); 988 lua_pushinteger(L, i);
926 } else if (i == (auxL_Unsigned)(lua_Number)i) { 989 } else if (i == (auxL_Unsigned)(lua_Number)i) {
@@ -1571,6 +1634,18 @@ static void compat_RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d) {
1571} /* compat_RSA_set0_key() */ 1634} /* compat_RSA_set0_key() */
1572#endif 1635#endif
1573 1636
1637#if !HAVE_SSL_GET_CLIENT_RANDOM
1638#define SSL_get_client_random(...) compat_SSL_get_client_random(__VA_ARGS__)
1639static size_t compat_SSL_get_client_random(const SSL *ssl, unsigned char *out, size_t outlen) {
1640 if (outlen == 0)
1641 return sizeof(ssl->s3->client_random);
1642 if (outlen > sizeof(ssl->s3->client_random))
1643 outlen = sizeof(ssl->s3->client_random);
1644 memcpy(out, ssl->s3->client_random, outlen);
1645 return outlen;
1646}
1647#endif
1648
1574#if !HAVE_SSL_CLIENT_VERSION 1649#if !HAVE_SSL_CLIENT_VERSION
1575#define SSL_client_version(...) compat_SSL_client_version(__VA_ARGS__) 1650#define SSL_client_version(...) compat_SSL_client_version(__VA_ARGS__)
1576 1651
@@ -1627,6 +1702,10 @@ static int compat_SSL_CTX_set1_param(SSL_CTX *ctx, X509_VERIFY_PARAM *vpm) {
1627#define X509_get0_ext(crt, i) X509_get_ext((crt), (i)) 1702#define X509_get0_ext(crt, i) X509_get_ext((crt), (i))
1628#endif 1703#endif
1629 1704
1705#if !HAVE_X509_GET_SIGNATURE_NID
1706#define X509_get_signature_nid(crt) OBJ_obj2nid((crt)->sig_alg->algorithm)
1707#endif
1708
1630#if !HAVE_X509_CRL_GET0_EXT 1709#if !HAVE_X509_CRL_GET0_EXT
1631#define X509_CRL_get0_ext(crt, i) X509_CRL_get_ext((crt), (i)) 1710#define X509_CRL_get0_ext(crt, i) X509_CRL_get_ext((crt), (i))
1632#endif 1711#endif
@@ -1914,6 +1993,7 @@ struct ex_data {
1914 1993
1915enum { 1994enum {
1916 EX_SSL_CTX_ALPN_SELECT_CB, 1995 EX_SSL_CTX_ALPN_SELECT_CB,
1996 EX_SSL_CTX_TLSEXT_SERVERNAME_CB,
1917}; 1997};
1918 1998
1919static struct ex_type { 1999static struct ex_type {
@@ -1923,6 +2003,7 @@ static struct ex_type {
1923 int (*set_ex_data)(); 2003 int (*set_ex_data)();
1924} ex_type[] = { 2004} ex_type[] = {
1925 [EX_SSL_CTX_ALPN_SELECT_CB] = { CRYPTO_EX_INDEX_SSL_CTX, -1, &SSL_CTX_get_ex_data, &SSL_CTX_set_ex_data }, 2005 [EX_SSL_CTX_ALPN_SELECT_CB] = { CRYPTO_EX_INDEX_SSL_CTX, -1, &SSL_CTX_get_ex_data, &SSL_CTX_set_ex_data },
2006 [EX_SSL_CTX_TLSEXT_SERVERNAME_CB] = { CRYPTO_EX_INDEX_SSL_CTX, -1, &SSL_CTX_get_ex_data, &SSL_CTX_set_ex_data },
1926}; 2007};
1927 2008
1928#if OPENSSL_PREREQ(1,1,0) 2009#if OPENSSL_PREREQ(1,1,0)
@@ -3074,6 +3155,7 @@ static int pk_new(lua_State *L) {
3074 unsigned exp = 65537; 3155 unsigned exp = 65537;
3075 int curve = NID_X9_62_prime192v1; 3156 int curve = NID_X9_62_prime192v1;
3076 const char *id; 3157 const char *id;
3158 const char *dhparam = NULL;
3077 lua_Number n; 3159 lua_Number n;
3078 3160
3079 if (!lua_istable(L, 1)) 3161 if (!lua_istable(L, 1))
@@ -3115,6 +3197,9 @@ static int pk_new(lua_State *L) {
3115 luaL_argerror(L, 1, lua_pushfstring(L, "%s: invalid curve", id)); 3197 luaL_argerror(L, 1, lua_pushfstring(L, "%s: invalid curve", id));
3116 } 3198 }
3117 3199
3200 /* dhparam field can contain a PEM encoded string. */
3201 loadfield(L, 1, "dhparam", LUA_TSTRING, &dhparam);
3202
3118creat: 3203creat:
3119 if (!(*ud = EVP_PKEY_new())) 3204 if (!(*ud = EVP_PKEY_new()))
3120 return auxL_error(L, auxL_EOPENSSL, "pkey.new"); 3205 return auxL_error(L, auxL_EOPENSSL, "pkey.new");
@@ -3152,9 +3237,23 @@ creat:
3152 case EVP_PKEY_DH: { 3237 case EVP_PKEY_DH: {
3153 DH *dh; 3238 DH *dh;
3154 3239
3155 if (!(dh = DH_generate_parameters(bits, exp, 0, 0))) 3240 /* DH Parameter Generation can take a long time, therefore we look
3241 * at the "dhparam" field, provided by the user.
3242 * The "dhparam" field takes precedence over "bits"
3243 */
3244 if (dhparam) {
3245 BIO *bio = BIO_new_mem_buf((void*)dhparam, strlen(dhparam));
3246 if (!bio)
3247 return auxL_error(L, auxL_EOPENSSL, "pkey.new");
3248
3249 dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
3250 BIO_free(bio);
3251 if (!dh)
3252 return auxL_error(L, auxL_EOPENSSL, "pkey.new");
3253 } else if (!(dh = DH_generate_parameters(bits, exp, 0, 0)))
3156 return auxL_error(L, auxL_EOPENSSL, "pkey.new"); 3254 return auxL_error(L, auxL_EOPENSSL, "pkey.new");
3157 3255
3256
3158 if (!DH_generate_key(dh)) { 3257 if (!DH_generate_key(dh)) {
3159 DH_free(dh); 3258 DH_free(dh);
3160 return auxL_error(L, auxL_EOPENSSL, "pkey.new"); 3259 return auxL_error(L, auxL_EOPENSSL, "pkey.new");
@@ -3420,7 +3519,7 @@ static int pk_decrypt(lua_State *L) {
3420 if (lua_istable(L, 3)) { 3519 if (lua_istable(L, 3)) {
3421 if (base_type == EVP_PKEY_RSA) { 3520 if (base_type == EVP_PKEY_RSA) {
3422 lua_getfield(L, 3, "rsaPadding"); 3521 lua_getfield(L, 3, "rsaPadding");
3423 rsaPadding = luaL_optint(L, -1, rsaPadding); 3522 rsaPadding = luaL_optinteger(L, -1, rsaPadding);
3424 lua_pop(L, 1); 3523 lua_pop(L, 1);
3425 } 3524 }
3426 } 3525 }
@@ -3479,7 +3578,7 @@ static int pk_encrypt(lua_State *L) {
3479 if (lua_istable(L, 3)) { 3578 if (lua_istable(L, 3)) {
3480 if (base_type == EVP_PKEY_RSA) { 3579 if (base_type == EVP_PKEY_RSA) {
3481 lua_getfield(L, 3, "rsaPadding"); 3580 lua_getfield(L, 3, "rsaPadding");
3482 rsaPadding = luaL_optint(L, -1, rsaPadding); 3581 rsaPadding = luaL_optinteger(L, -1, rsaPadding);
3483 lua_pop(L, 1); 3582 lua_pop(L, 1);
3484 } 3583 }
3485 } 3584 }
@@ -4401,7 +4500,7 @@ static int ecg_new(lua_State *L) {
4401 return 1; 4500 return 1;
4402 } 4501 }
4403 case LUA_TNUMBER: { 4502 case LUA_TNUMBER: {
4404 int nid = luaL_checkint(L, 2); 4503 int nid = luaL_checkinteger(L, 2);
4405 4504
4406 if (!ecg_push_by_nid(L, nid)) 4505 if (!ecg_push_by_nid(L, nid))
4407 goto sslerr; 4506 goto sslerr;
@@ -4970,6 +5069,25 @@ static _Bool xe_new_isder(const char *value, _Bool *crit) {
4970 return 0; 5069 return 0;
4971} /* xs_new_isder() */ 5070} /* xs_new_isder() */
4972 5071
5072static CONF* loadconf(lua_State *L, int idx) {
5073 CONF *conf;
5074 size_t len;
5075 const char *cdata = luaL_checklstring(L, idx, &len);
5076 BIO *bio = getbio(L);
5077 if (BIO_write(bio, cdata, len) < 0)
5078 return NULL;
5079
5080 if (!(conf = NCONF_new(NULL)))
5081 return NULL;
5082
5083 if (!NCONF_load_bio(conf, bio, NULL)) {
5084 NCONF_free(conf);
5085 return NULL;
5086 }
5087
5088 return conf;
5089}
5090
4973static int xe_new(lua_State *L) { 5091static int xe_new(lua_State *L) {
4974 const char *name = luaL_checkstring(L, 1); 5092 const char *name = luaL_checkstring(L, 1);
4975 const char *value = luaL_checkstring(L, 2); 5093 const char *value = luaL_checkstring(L, 2);
@@ -4978,42 +5096,87 @@ static int xe_new(lua_State *L) {
4978 CONF *conf = NULL; 5096 CONF *conf = NULL;
4979 X509V3_CTX cbuf = { 0 }, *ctx = NULL; 5097 X509V3_CTX cbuf = { 0 }, *ctx = NULL;
4980 X509_EXTENSION **ud; 5098 X509_EXTENSION **ud;
5099 _Bool crit;
4981 5100
4982 lua_settop(L, 3); 5101 lua_settop(L, 3);
4983 ud = prepsimple(L, X509_EXT_CLASS); 5102 ud = prepsimple(L, X509_EXT_CLASS);
4984 5103
4985 if (!lua_isnil(L, 3)) { 5104 if (xe_new_isder(value, &crit)) {
4986 size_t len; 5105 size_t len;
4987 const char *cdata = luaL_checklstring(L, 3, &len); 5106 const char *cdata = lua_tolstring(L, 3, &len);
4988 _Bool crit; 5107 if (!(obj = OBJ_txt2obj(name, 0)))
5108 goto error;
5109 if (!(oct = ASN1_STRING_new()))
5110 goto error;
5111 if (!ASN1_STRING_set(oct, cdata, len))
5112 goto error;
5113 if (!(*ud = X509_EXTENSION_create_by_OBJ(NULL, obj, crit, oct)))
5114 goto error;
4989 5115
4990 if (xe_new_isder(value, &crit)) { 5116 ASN1_OBJECT_free(obj);
4991 if (!(obj = OBJ_txt2obj(name, 0))) 5117 ASN1_STRING_free(oct);
4992 goto error; 5118
4993 if (!(oct = ASN1_STRING_new())) 5119 return 1;
4994 goto error; 5120 }
4995 if (!ASN1_STRING_set(oct, cdata, len)) 5121
4996 goto error; 5122 switch (lua_type(L, 3)) {
4997 if (!(*ud = X509_EXTENSION_create_by_OBJ(NULL, obj, crit, oct))) 5123 case LUA_TNONE:
5124 case LUA_TNIL:
5125 break;
5126 case LUA_TSTRING: {
5127 if (!(conf = loadconf(L, 3)))
5128 goto error;
5129
5130 ctx = &cbuf;
5131 X509V3_set_nconf(ctx, conf);
5132 break;
5133 }
5134 case LUA_TTABLE: {
5135 X509 *issuer = NULL;
5136 X509 *subject = NULL;
5137 X509_REQ *request = NULL;
5138 X509_CRL *crl = NULL;
5139 int flags = 0;
5140
5141 ctx = &cbuf;
5142
5143 if (lua_getfield(L, 3, "db") != LUA_TNIL) {
5144 if (!(conf = loadconf(L, -1)))
4998 goto error; 5145 goto error;
5146 X509V3_set_nconf(ctx, conf);
5147 }
5148 lua_pop(L, 1);
4999 5149
5000 ASN1_OBJECT_free(obj); 5150 if (lua_getfield(L, 3, "issuer") != LUA_TNIL) {
5001 ASN1_STRING_free(oct); 5151 issuer = checksimple(L, -1, X509_CERT_CLASS);
5152 }
5153 lua_pop(L, 1);
5002 5154
5003 return 1; 5155 if (lua_getfield(L, 3, "subject") != LUA_TNIL) {
5156 subject = checksimple(L, -1, X509_CERT_CLASS);
5004 } 5157 }
5158 lua_pop(L, 1);
5005 5159
5006 BIO *bio = getbio(L); 5160 if (lua_getfield(L, 3, "request") != LUA_TNIL) {
5007 if (BIO_puts(bio, cdata) < 0) 5161 request = checksimple(L, -1, X509_CSR_CLASS);
5008 goto error; 5162 }
5163 lua_pop(L, 1);
5009 5164
5010 if (!(conf = NCONF_new(NULL))) 5165 if (lua_getfield(L, 3, "crl") != LUA_TNIL) {
5011 goto error; 5166 crl = checksimple(L, -1, X509_CRL_CLASS);
5012 if (!NCONF_load_bio(conf, bio, NULL)) 5167 }
5013 goto error; 5168 lua_pop(L, 1);
5014 5169
5015 ctx = &cbuf; 5170 if (lua_getfield(L, 3, "flags") != LUA_TNIL) {
5016 X509V3_set_nconf(ctx, conf); 5171 flags = luaL_checkinteger(L, -1);
5172 }
5173 lua_pop(L, 1);
5174
5175 X509V3_set_ctx(ctx, issuer, subject, request, crl, flags);
5176 break;
5177 }
5178 default:
5179 return luaL_argerror(L, 3, "invalid extra parameter (expected string, table or nil)");
5017 } 5180 }
5018 5181
5019 /* 5182 /*
@@ -5257,7 +5420,7 @@ static int xc_getVersion(lua_State *L) {
5257 5420
5258static int xc_setVersion(lua_State *L) { 5421static int xc_setVersion(lua_State *L) {
5259 X509 *crt = checksimple(L, 1, X509_CERT_CLASS); 5422 X509 *crt = checksimple(L, 1, X509_CERT_CLASS);
5260 int version = luaL_checkint(L, 2); 5423 int version = luaL_checkinteger(L, 2);
5261 5424
5262 if (!X509_set_version(crt, version - 1)) 5425 if (!X509_set_version(crt, version - 1))
5263 return luaL_error(L, "x509.cert:setVersion: %d: invalid version", version); 5426 return luaL_error(L, "x509.cert:setVersion: %d: invalid version", version);
@@ -5804,11 +5967,11 @@ static int xc_setBasicConstraint(lua_State *L) {
5804 lua_pop(L, 1); 5967 lua_pop(L, 1);
5805 5968
5806 lua_getfield(L, 2, "pathLen"); 5969 lua_getfield(L, 2, "pathLen");
5807 pathLen = luaL_optint(L, -1, pathLen); 5970 pathLen = luaL_optinteger(L, -1, pathLen);
5808 lua_pop(L, 1); 5971 lua_pop(L, 1);
5809 5972
5810 lua_getfield(L, 2, "pathLenConstraint"); 5973 lua_getfield(L, 2, "pathLenConstraint");
5811 pathLen = luaL_optint(L, -1, pathLen); 5974 pathLen = luaL_optinteger(L, -1, pathLen);
5812 lua_pop(L, 1); 5975 lua_pop(L, 1);
5813 5976
5814 if (!(bs = BASIC_CONSTRAINTS_new())) 5977 if (!(bs = BASIC_CONSTRAINTS_new()))
@@ -5825,7 +5988,7 @@ static int xc_setBasicConstraint(lua_State *L) {
5825 case 1: 5988 case 1:
5826 /* FALL THROUGH */ 5989 /* FALL THROUGH */
5827 case 2: 5990 case 2:
5828 pathLen = luaL_checkint(L, 3); 5991 pathLen = luaL_checkinteger(L, 3);
5829 5992
5830 break; 5993 break;
5831 } 5994 }
@@ -5947,6 +6110,40 @@ static int xc_getExtensionCount(lua_State *L) {
5947} /* xc_getExtensionCount() */ 6110} /* xc_getExtensionCount() */
5948 6111
5949 6112
6113static int sk_openssl_string__gc(lua_State *L) {
6114 STACK_OF(OPENSSL_STRING) **res = lua_touserdata(L, 1);
6115
6116 if (*res) {
6117 sk_OPENSSL_STRING_free(*res);
6118 *res = NULL;
6119 }
6120
6121 return 0;
6122} /* sk_openssl_string__gc() */
6123
6124
6125static int xc_getOCSP(lua_State *L) {
6126 X509 *crt = checksimple(L, 1, X509_CERT_CLASS);
6127 STACK_OF(OPENSSL_STRING) **res = prepsimple(L, NULL, &sk_openssl_string__gc);
6128 int num, i;
6129
6130 *res = X509_get1_ocsp(crt);
6131 if (!*res)
6132 return 0;
6133
6134 num = sk_OPENSSL_STRING_num(*res);
6135 luaL_checkstack(L, num, "too many authorityInfoAccess");
6136 for (i = 0; i < num; i++) {
6137 lua_pushstring(L, sk_OPENSSL_STRING_value(*res, i));
6138 }
6139
6140 sk_OPENSSL_STRING_free(*res);
6141 *res = NULL;
6142
6143 return num;
6144} /* xc_getOCSP */
6145
6146
5950static int xc_isIssuedBy(lua_State *L) { 6147static int xc_isIssuedBy(lua_State *L) {
5951 X509 *crt = checksimple(L, 1, X509_CERT_CLASS); 6148 X509 *crt = checksimple(L, 1, X509_CERT_CLASS);
5952 X509 *issuer = checksimple(L, 2, X509_CERT_CLASS); 6149 X509 *issuer = checksimple(L, 2, X509_CERT_CLASS);
@@ -6029,23 +6226,17 @@ static int xc_getPublicKeyDigest(lua_State *L) {
6029} /* xc_getPublicKeyDigest() */ 6226} /* xc_getPublicKeyDigest() */
6030 6227
6031 6228
6032#if 0
6033/*
6034 * TODO: X509_get_signature_type always seems to return NID_undef. Are we
6035 * using it wrong or is it broken?
6036 */
6037static int xc_getSignatureName(lua_State *L) { 6229static int xc_getSignatureName(lua_State *L) {
6038 X509 *crt = checksimple(L, 1, X509_CERT_CLASS); 6230 X509 *crt = checksimple(L, 1, X509_CERT_CLASS);
6039 int nid; 6231 int nid;
6040 6232
6041 if (NID_undef == (nid = X509_get_signature_type(crt))) 6233 if (NID_undef == (nid = X509_get_signature_nid(crt)))
6042 return 0; 6234 return 0;
6043 6235
6044 auxL_pushnid(L, nid); 6236 auxL_pushnid(L, nid);
6045 6237
6046 return 1; 6238 return 1;
6047} /* xc_getSignatureName() */ 6239} /* xc_getSignatureName() */
6048#endif
6049 6240
6050 6241
6051static int xc_sign(lua_State *L) { 6242static int xc_sign(lua_State *L) {
@@ -6188,13 +6379,12 @@ static const auxL_Reg xc_methods[] = {
6188 { "addExtension", &xc_addExtension }, 6379 { "addExtension", &xc_addExtension },
6189 { "getExtension", &xc_getExtension }, 6380 { "getExtension", &xc_getExtension },
6190 { "getExtensionCount", &xc_getExtensionCount }, 6381 { "getExtensionCount", &xc_getExtensionCount },
6382 { "getOCSP", &xc_getOCSP },
6191 { "isIssuedBy", &xc_isIssuedBy }, 6383 { "isIssuedBy", &xc_isIssuedBy },
6192 { "getPublicKey", &xc_getPublicKey }, 6384 { "getPublicKey", &xc_getPublicKey },
6193 { "setPublicKey", &xc_setPublicKey }, 6385 { "setPublicKey", &xc_setPublicKey },
6194 { "getPublicKeyDigest", &xc_getPublicKeyDigest }, 6386 { "getPublicKeyDigest", &xc_getPublicKeyDigest },
6195#if 0
6196 { "getSignatureName", &xc_getSignatureName }, 6387 { "getSignatureName", &xc_getSignatureName },
6197#endif
6198 { "sign", &xc_sign }, 6388 { "sign", &xc_sign },
6199 { "text", &xc_text }, 6389 { "text", &xc_text },
6200 { "tostring", &xc__tostring }, 6390 { "tostring", &xc__tostring },
@@ -6286,7 +6476,7 @@ static int xr_getVersion(lua_State *L) {
6286 6476
6287static int xr_setVersion(lua_State *L) { 6477static int xr_setVersion(lua_State *L) {
6288 X509_REQ *csr = checksimple(L, 1, X509_CSR_CLASS); 6478 X509_REQ *csr = checksimple(L, 1, X509_CSR_CLASS);
6289 int version = luaL_checkint(L, 2); 6479 int version = luaL_checkinteger(L, 2);
6290 6480
6291 if (!X509_REQ_set_version(csr, version - 1)) 6481 if (!X509_REQ_set_version(csr, version - 1))
6292 return luaL_error(L, "x509.csr:setVersion: %d: invalid version", version); 6482 return luaL_error(L, "x509.csr:setVersion: %d: invalid version", version);
@@ -6591,7 +6781,7 @@ static int xx_getVersion(lua_State *L) {
6591 6781
6592static int xx_setVersion(lua_State *L) { 6782static int xx_setVersion(lua_State *L) {
6593 X509_CRL *crl = checksimple(L, 1, X509_CRL_CLASS); 6783 X509_CRL *crl = checksimple(L, 1, X509_CRL_CLASS);
6594 int version = luaL_checkint(L, 2); 6784 int version = luaL_checkinteger(L, 2);
6595 6785
6596 if (!X509_CRL_set_version(crl, version - 1)) 6786 if (!X509_CRL_set_version(crl, version - 1))
6597 return luaL_error(L, "x509.crl:setVersion: %d: invalid version", version); 6787 return luaL_error(L, "x509.crl:setVersion: %d: invalid version", version);
@@ -6642,7 +6832,7 @@ static int xx_getNextUpdate(lua_State *L) {
6642 updateby = timeutc(time); 6832 updateby = timeutc(time);
6643 6833
6644 if (isfinite(updateby)) 6834 if (isfinite(updateby))
6645 lua_pushnumber(L, 1); 6835 lua_pushnumber(L, updateby);
6646 else 6836 else
6647 lua_pushnil(L); 6837 lua_pushnil(L);
6648 6838
@@ -6832,6 +7022,19 @@ static int xx_sign(lua_State *L) {
6832} /* xx_sign() */ 7022} /* xx_sign() */
6833 7023
6834 7024
7025static int xx_verify(lua_State *L) {
7026 X509_CRL *crl = checksimple(L, 1, X509_CRL_CLASS);
7027 EVP_PKEY *key = checksimple(L, 2, PKEY_CLASS);
7028
7029 if (!X509_CRL_verify(crl, key))
7030 return auxL_error(L, auxL_EOPENSSL, "x509.crl:verify");
7031
7032 lua_pushboolean(L, 1);
7033
7034 return 1;
7035} /* xx_verify() */
7036
7037
6835static int xx_text(lua_State *L) { 7038static int xx_text(lua_State *L) {
6836 X509_CRL *crl = checksimple(L, 1, X509_CRL_CLASS); 7039 X509_CRL *crl = checksimple(L, 1, X509_CRL_CLASS);
6837 7040
@@ -6901,6 +7104,7 @@ static const auxL_Reg xx_methods[] = {
6901 { "getExtension", &xx_getExtension }, 7104 { "getExtension", &xx_getExtension },
6902 { "getExtensionCount", &xx_getExtensionCount }, 7105 { "getExtensionCount", &xx_getExtensionCount },
6903 { "sign", &xx_sign }, 7106 { "sign", &xx_sign },
7107 { "verify", &xx_verify },
6904 { "text", &xx_text }, 7108 { "text", &xx_text },
6905 { "tostring", &xx__tostring }, 7109 { "tostring", &xx__tostring },
6906 { NULL, NULL }, 7110 { NULL, NULL },
@@ -7180,7 +7384,7 @@ static int xs_verify(lua_State *L) {
7180 X509 *crt = checksimple(L, 2, X509_CERT_CLASS); 7384 X509 *crt = checksimple(L, 2, X509_CERT_CLASS);
7181 STACK_OF(X509) *chain = NULL, **proof; 7385 STACK_OF(X509) *chain = NULL, **proof;
7182 X509_STORE_CTX *ctx = NULL; 7386 X509_STORE_CTX *ctx = NULL;
7183 int nr = 0, ok, why; 7387 int ok, why;
7184 7388
7185 /* pre-allocate space for a successful return */ 7389 /* pre-allocate space for a successful return */
7186 lua_settop(L, 3); 7390 lua_settop(L, 3);
@@ -7215,27 +7419,24 @@ static int xs_verify(lua_State *L) {
7215 case 1: /* verified */ 7419 case 1: /* verified */
7216 if (!(*proof = X509_STORE_CTX_get1_chain(ctx))) 7420 if (!(*proof = X509_STORE_CTX_get1_chain(ctx)))
7217 goto eossl; 7421 goto eossl;
7422 X509_STORE_CTX_free(ctx);
7218 7423
7219 lua_pushboolean(L, 1); 7424 lua_pushboolean(L, 1);
7220 lua_pushvalue(L, -2); 7425 lua_pushvalue(L, -2);
7221 nr = 2;
7222 7426
7223 break; 7427 return 2;
7224 case 0: /* not verified */ 7428 case 0: /* not verified */
7225 why = X509_STORE_CTX_get_error(ctx); 7429 why = X509_STORE_CTX_get_error(ctx);
7430 X509_STORE_CTX_free(ctx);
7226 7431
7227 lua_pushboolean(L, 0); 7432 lua_pushboolean(L, 0);
7228 lua_pushstring(L, X509_verify_cert_error_string(why)); 7433 lua_pushstring(L, X509_verify_cert_error_string(why));
7229 nr = 2;
7230 7434
7231 break; 7435 return 2;
7232 default: 7436 default:
7233 goto eossl; 7437 goto eossl;
7234 } 7438 }
7235 7439
7236 X509_STORE_CTX_free(ctx);
7237
7238 return nr;
7239eossl: 7440eossl:
7240 if (ctx) 7441 if (ctx)
7241 X509_STORE_CTX_free(ctx); 7442 X509_STORE_CTX_free(ctx);
@@ -7428,6 +7629,57 @@ static int p12_interpose(lua_State *L) {
7428} /* p12_interpose() */ 7629} /* p12_interpose() */
7429 7630
7430 7631
7632static int p12_parse(lua_State *L) {
7633 /* parse a p12 binary string and return the parts */
7634 PKCS12 *p12;
7635
7636 /* gather input parameters */
7637 size_t len;
7638 const char *blob = luaL_checklstring(L, 1, &len);
7639 const char *passphrase = luaL_optstring(L, 2, NULL);
7640
7641 /* prepare return values */
7642 EVP_PKEY **ud_pkey = prepsimple(L, PKEY_CLASS);
7643 X509 **ud_cert = prepsimple(L, X509_CERT_CLASS);
7644 STACK_OF(X509) **ud_chain = prepsimple(L, X509_CHAIN_CLASS);
7645 /* Note: *ud_chain must be initialised to NULL, which prepsimple does. */
7646
7647 /* read PKCS#12 data into OpenSSL memory buffer */
7648 BIO *bio = BIO_new_mem_buf((void*)blob, len);
7649 if (!bio)
7650 return auxL_error(L, auxL_EOPENSSL, "pkcs12.parse");
7651 p12 = d2i_PKCS12_bio(bio, NULL);
7652 BIO_free(bio);
7653 if (!p12)
7654 return auxL_error(L, auxL_EOPENSSL, "pkcs12.parse");
7655
7656 /* the p12 pointer holds the data we're interested in */
7657 int rc = PKCS12_parse(p12, passphrase, ud_pkey, ud_cert, ud_chain);
7658 PKCS12_free(p12);
7659 if (!rc)
7660 auxL_error(L, auxL_EOPENSSL, "pkcs12.parse");
7661
7662 /* replace the return values by nil if the ud pointers are NULL */
7663 if (*ud_pkey == NULL) {
7664 lua_pushnil(L);
7665 lua_replace(L, -4);
7666 }
7667
7668 if (*ud_cert == NULL) {
7669 lua_pushnil(L);
7670 lua_replace(L, -3);
7671 }
7672
7673 /* other certificates (a chain, STACK_OF(X509) *) */
7674 if (*ud_chain == NULL) {
7675 lua_pop(L, 1);
7676 lua_pushnil(L);
7677 }
7678
7679 return 3;
7680} /* p12_parse() */
7681
7682
7431static int p12__tostring(lua_State *L) { 7683static int p12__tostring(lua_State *L) {
7432 PKCS12 *p12 = checksimple(L, 1, PKCS12_CLASS); 7684 PKCS12 *p12 = checksimple(L, 1, PKCS12_CLASS);
7433 BIO *bio = getbio(L); 7685 BIO *bio = getbio(L);
@@ -7471,6 +7723,7 @@ static const auxL_Reg p12_metatable[] = {
7471static const auxL_Reg p12_globals[] = { 7723static const auxL_Reg p12_globals[] = {
7472 { "new", &p12_new }, 7724 { "new", &p12_new },
7473 { "interpose", &p12_interpose }, 7725 { "interpose", &p12_interpose },
7726 { "parse", &p12_parse },
7474 { NULL, NULL }, 7727 { NULL, NULL },
7475}; 7728};
7476 7729
@@ -7690,8 +7943,8 @@ static int sx_getParam(lua_State *L) {
7690 7943
7691static int sx_setVerify(lua_State *L) { 7944static int sx_setVerify(lua_State *L) {
7692 SSL_CTX *ctx = checksimple(L, 1, SSL_CTX_CLASS); 7945 SSL_CTX *ctx = checksimple(L, 1, SSL_CTX_CLASS);
7693 int mode = luaL_optint(L, 2, -1); 7946 int mode = luaL_optinteger(L, 2, -1);
7694 int depth = luaL_optint(L, 3, -1); 7947 int depth = luaL_optinteger(L, 3, -1);
7695 7948
7696 if (mode != -1) 7949 if (mode != -1)
7697 SSL_CTX_set_verify(ctx, mode, 0); 7950 SSL_CTX_set_verify(ctx, mode, 0);
@@ -7855,9 +8108,8 @@ static int sx_setAlpnProtos(lua_State *L) {
7855} /* sx_setAlpnProtos() */ 8108} /* sx_setAlpnProtos() */
7856#endif 8109#endif
7857 8110
7858#if HAVE_SSL_CTX_SET_ALPN_SELECT_CB
7859static SSL *ssl_push(lua_State *, SSL *);
7860 8111
8112#if HAVE_SSL_CTX_SET_ALPN_SELECT_CB
7861static int sx_setAlpnSelect_cb(SSL *ssl, const unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *_ctx) { 8113static int sx_setAlpnSelect_cb(SSL *ssl, const unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *_ctx) {
7862 SSL_CTX *ctx = _ctx; 8114 SSL_CTX *ctx = _ctx;
7863 lua_State *L = NULL; 8115 lua_State *L = NULL;
@@ -7875,12 +8127,12 @@ static int sx_setAlpnSelect_cb(SSL *ssl, const unsigned char **out, unsigned cha
7875 8127
7876 otop = lua_gettop(L) - n; 8128 otop = lua_gettop(L) - n;
7877 8129
7878 /* TODO: Install temporary panic handler to catch OOM errors */
7879
7880 /* pass SSL object as 1st argument */ 8130 /* pass SSL object as 1st argument */
7881 ssl_push(L, ssl); 8131 if (ssl_pushsafe(L, ssl))
8132 goto fatal;
7882 lua_insert(L, otop + 3); 8133 lua_insert(L, otop + 3);
7883 8134
8135 /* TODO: Install temporary panic handler to catch OOM errors */
7884 /* pass table of protocol names as 2nd argument */ 8136 /* pass table of protocol names as 2nd argument */
7885 pushprotos(L, in, inlen); 8137 pushprotos(L, in, inlen);
7886 lua_insert(L, otop + 4); 8138 lua_insert(L, otop + 4);
@@ -7952,6 +8204,116 @@ static int sx_setAlpnSelect(lua_State *L) {
7952#endif 8204#endif
7953 8205
7954 8206
8207#if HAVE_SSL_CTX_SET_TLSEXT_SERVERNAME_CALLBACK
8208static int sx_setHostNameCallback_cb(SSL *ssl, int *ad, void *_ctx) {
8209 SSL_CTX *ctx = _ctx;
8210 lua_State *L = NULL;
8211 size_t n;
8212 int otop, status, ret = SSL_TLSEXT_ERR_ALERT_FATAL;
8213
8214 *ad = SSL_AD_INTERNAL_ERROR;
8215
8216 /* expect at least one value: closure */
8217 if ((n = ex_getdata(&L, EX_SSL_CTX_TLSEXT_SERVERNAME_CB, ctx)) < 1)
8218 return SSL_TLSEXT_ERR_ALERT_FATAL;
8219
8220 otop = lua_gettop(L) - n;
8221
8222 /* pass SSL object as 1st argument */
8223 if (ssl_pushsafe(L, ssl))
8224 goto done;
8225
8226 lua_insert(L, otop + 2);
8227
8228 if (LUA_OK != (status = lua_pcall(L, 1 + (n - 1), 2, 0)))
8229 goto done;
8230
8231 /* callback should return a boolean for OK/NOACK
8232 * or nil + an integer for a controlled error
8233 * everything else will be a fatal internal error
8234 */
8235 if (lua_isboolean(L, -2)) {
8236 ret = lua_toboolean(L, -2) ? SSL_TLSEXT_ERR_OK : SSL_TLSEXT_ERR_NOACK;
8237 } else {
8238 ret = SSL_TLSEXT_ERR_ALERT_FATAL;
8239 if (lua_isnil(L, -2) && lua_isinteger(L, -1))
8240 *ad = lua_tointeger(L, -1);
8241 }
8242
8243done:
8244 lua_settop(L, otop);
8245
8246 return ret;
8247} /* sx_setHostNameCallback_cb() */
8248
8249
8250static int sx_setHostNameCallback(lua_State *L) {
8251 SSL_CTX *ctx = checksimple(L, 1, SSL_CTX_CLASS);
8252 int error;
8253
8254 luaL_checktype(L, 2, LUA_TFUNCTION);
8255
8256 if ((error = ex_setdata(L, EX_SSL_CTX_TLSEXT_SERVERNAME_CB, ctx, lua_gettop(L) - 1))) {
8257 if (error > 0) {
8258 return luaL_error(L, "unable to set hostname selection callback: %s", aux_strerror(error));
8259 } else if (error == auxL_EOPENSSL && !ERR_peek_error()) {
8260 return luaL_error(L, "unable to set hostname selection callback: Unknown internal error");
8261 } else {
8262 return auxL_error(L, error, "ssl.context:setHostNameCallback");
8263 }
8264 }
8265 SSL_CTX_set_tlsext_servername_callback(ctx, sx_setHostNameCallback_cb);
8266 SSL_CTX_set_tlsext_servername_arg(ctx, ctx);
8267
8268 lua_pushboolean(L, 1);
8269
8270 return 1;
8271} /* sx_setHostNameCallback() */
8272#endif
8273
8274
8275int TLSEXT_STATUSTYPEs[] = { TLSEXT_STATUSTYPE_ocsp };
8276const char *TLSEXT_STATUSTYPEs_names[] = { "ocsp", NULL };
8277#define checkTLSEXT_STATUSTYPE(L, idx) \
8278 (TLSEXT_STATUSTYPEs[luaL_checkoption((L), (idx), NULL, TLSEXT_STATUSTYPEs_names)])
8279
8280
8281#if HAVE_SSL_CTX_SET_TLSEXT_STATUS_TYPE
8282static int sx_setTLSextStatusType(lua_State *L) {
8283 SSL_CTX *ctx = checksimple(L, 1, SSL_CTX_CLASS);
8284 int type = checkTLSEXT_STATUSTYPE(L, 2);
8285
8286 if(!SSL_CTX_set_tlsext_status_type(ctx, type))
8287 return auxL_error(L, auxL_EOPENSSL, "ssl.context:setTLSextStatusType");
8288
8289 lua_pushboolean(L, 1);
8290
8291 return 1;
8292} /* sx_setTLSextStatusType() */
8293#endif
8294
8295
8296#if HAVE_SSL_CTX_GET_TLSEXT_STATUS_TYPE
8297static int sx_getTLSextStatusType(lua_State *L) {
8298 SSL_CTX *ctx = checksimple(L, 1, SSL_CLASS);
8299
8300 int type = SSL_CTX_get_tlsext_status_type(ctx);
8301 switch(type) {
8302 case -1:
8303 lua_pushnil(L);
8304 break;
8305 case TLSEXT_STATUSTYPE_ocsp:
8306 lua_pushliteral(L, "ocsp");
8307 break;
8308 default:
8309 luaL_error(L, "unknown TLS extension %d", type);
8310 }
8311
8312 return 1;
8313} /* sx_getTLSextStatusType() */
8314#endif
8315
8316
7955static int sx__gc(lua_State *L) { 8317static int sx__gc(lua_State *L) {
7956 SSL_CTX **ud = luaL_checkudata(L, 1, SSL_CTX_CLASS); 8318 SSL_CTX **ud = luaL_checkudata(L, 1, SSL_CTX_CLASS);
7957 8319
@@ -7987,6 +8349,15 @@ static const auxL_Reg sx_methods[] = {
7987#if HAVE_SSL_CTX_SET_ALPN_SELECT_CB 8349#if HAVE_SSL_CTX_SET_ALPN_SELECT_CB
7988 { "setAlpnSelect", &sx_setAlpnSelect }, 8350 { "setAlpnSelect", &sx_setAlpnSelect },
7989#endif 8351#endif
8352#if HAVE_SSL_CTX_SET_TLSEXT_SERVERNAME_CALLBACK
8353 { "setHostNameCallback", &sx_setHostNameCallback },
8354#endif
8355#if HAVE_SSL_CTX_SET_TLSEXT_STATUS_TYPE
8356 { "setTLSextStatusType", &sx_setTLSextStatusType },
8357#endif
8358#if HAVE_SSL_CTX_GET_TLSEXT_STATUS_TYPE
8359 { "getTLSextStatusType", &sx_getTLSextStatusType },
8360#endif
7990 { NULL, NULL }, 8361 { NULL, NULL },
7991}; 8362};
7992 8363
@@ -8098,6 +8469,18 @@ static int ssl_interpose(lua_State *L) {
8098} /* ssl_interpose() */ 8469} /* ssl_interpose() */
8099 8470
8100 8471
8472static int ssl_setContext(lua_State *L) {
8473 SSL *ssl = checksimple(L, 1, SSL_CLASS);
8474 SSL_CTX *ctx = checksimple(L, 2, SSL_CTX_CLASS);
8475
8476 if (!SSL_set_SSL_CTX(ssl, ctx))
8477 return auxL_error(L, auxL_EOPENSSL, "ssl.setContext");
8478
8479 lua_pushboolean(L, 1);
8480
8481 return 1;
8482} /* ssl_setContext() */
8483
8101static int ssl_setOptions(lua_State *L) { 8484static int ssl_setOptions(lua_State *L) {
8102 SSL *ssl = checksimple(L, 1, SSL_CLASS); 8485 SSL *ssl = checksimple(L, 1, SSL_CLASS);
8103 auxL_Integer options = auxL_checkinteger(L, 2); 8486 auxL_Integer options = auxL_checkinteger(L, 2);
@@ -8159,6 +8542,33 @@ static int ssl_getParam(lua_State *L) {
8159} /* ssl_getParam() */ 8542} /* ssl_getParam() */
8160 8543
8161 8544
8545static int ssl_setVerify(lua_State *L) {
8546 SSL *ssl = checksimple(L, 1, SSL_CLASS);
8547 int mode = luaL_optinteger(L, 2, -1);
8548 int depth = luaL_optinteger(L, 3, -1);
8549
8550 if (mode != -1)
8551 SSL_set_verify(ssl, mode, 0);
8552
8553 if (depth != -1)
8554 SSL_set_verify_depth(ssl, depth);
8555
8556 lua_pushboolean(L, 1);
8557
8558 return 1;
8559} /* ssl_setVerify() */
8560
8561
8562static int ssl_getVerify(lua_State *L) {
8563 SSL *ssl = checksimple(L, 1, SSL_CLASS);
8564
8565 lua_pushinteger(L, SSL_get_verify_mode(ssl));
8566 lua_pushinteger(L, SSL_get_verify_depth(ssl));
8567
8568 return 2;
8569} /* ssl_getVerify() */
8570
8571
8162static int ssl_getVerifyResult(lua_State *L) { 8572static int ssl_getVerifyResult(lua_State *L) {
8163 SSL *ssl = checksimple(L, 1, SSL_CLASS); 8573 SSL *ssl = checksimple(L, 1, SSL_CLASS);
8164 long res = SSL_get_verify_result(ssl); 8574 long res = SSL_get_verify_result(ssl);
@@ -8168,6 +8578,44 @@ static int ssl_getVerifyResult(lua_State *L) {
8168} /* ssl_getVerifyResult() */ 8578} /* ssl_getVerifyResult() */
8169 8579
8170 8580
8581static int ssl_setCertificate(lua_State *L) {
8582 SSL *ssl = checksimple(L, 1, SSL_CLASS);
8583 X509 *crt = X509_dup(checksimple(L, 2, X509_CERT_CLASS));
8584 int ok;
8585
8586 ok = SSL_use_certificate(ssl, crt);
8587 X509_free(crt);
8588
8589 if (!ok)
8590 return auxL_error(L, auxL_EOPENSSL, "ssl:setCertificate");
8591
8592 lua_pushboolean(L, 1);
8593
8594 return 1;
8595} /* ssl_setCertificate() */
8596
8597
8598static int ssl_setPrivateKey(lua_State *L) {
8599 SSL *ssl = checksimple(L, 1, SSL_CLASS);
8600 EVP_PKEY *key = checksimple(L, 2, PKEY_CLASS);
8601 /*
8602 * NOTE: No easy way to dup the key, but a shared reference should
8603 * be okay as keys are less mutable than certificates.
8604 *
8605 * FIXME: SSL_use_PrivateKey will return true even if the
8606 * EVP_PKEY object has no private key. Instead, we'll just get a
8607 * segfault during the SSL handshake. We need to check that a
8608 * private key is actually defined in the object.
8609 */
8610 if (!SSL_use_PrivateKey(ssl, key))
8611 return auxL_error(L, auxL_EOPENSSL, "ssl:setPrivateKey");
8612
8613 lua_pushboolean(L, 1);
8614
8615 return 1;
8616} /* ssl_setPrivateKey() */
8617
8618
8171static int ssl_getPeerCertificate(lua_State *L) { 8619static int ssl_getPeerCertificate(lua_State *L) {
8172 SSL *ssl = checksimple(L, 1, SSL_CLASS); 8620 SSL *ssl = checksimple(L, 1, SSL_CLASS);
8173 X509 **x509 = prepsimple(L, X509_CERT_CLASS); 8621 X509 **x509 = prepsimple(L, X509_CERT_CLASS);
@@ -8284,6 +8732,31 @@ static int ssl_getVersion(lua_State *L) {
8284} /* ssl_getVersion() */ 8732} /* ssl_getVersion() */
8285 8733
8286 8734
8735static int ssl_getClientRandom(lua_State *L) {
8736 SSL *ssl = checksimple(L, 1, SSL_CLASS);
8737 luaL_Buffer B;
8738 size_t len;
8739 unsigned char *out;
8740
8741 len = SSL_get_client_random(ssl, NULL, 0);
8742#if LUA_VERSION_NUM < 502
8743 if (LUAL_BUFFERSIZE < len)
8744 luaL_error(L, "ssl:getClientRandom: LUAL_BUFFERSIZE(%d) < SSL_get_client_random(ssl, NULL, 0)", (int)LUAL_BUFFERSIZE, (int)len);
8745 luaL_buffinit(L, &B);
8746 out = (unsigned char*)luaL_prepbuffer(&B);
8747 len = SSL_get_client_random(ssl, out, len);
8748 luaL_addsize(&B, len);
8749 luaL_pushresult(&B);
8750#else
8751 out = (unsigned char*)luaL_buffinitsize(L, &B, len);
8752 len = SSL_get_client_random(ssl, out, len);
8753 luaL_pushresultsize(&B, len);
8754#endif
8755
8756 return 1;
8757} /* ssl_getClientRandom() */
8758
8759
8287static int ssl_getClientVersion(lua_State *L) { 8760static int ssl_getClientVersion(lua_State *L) {
8288 SSL *ssl = checksimple(L, 1, SSL_CLASS); 8761 SSL *ssl = checksimple(L, 1, SSL_CLASS);
8289 int format = luaL_checkoption(L, 2, "d", (const char *[]){ "d", ".", "f", NULL }); 8762 int format = luaL_checkoption(L, 2, "d", (const char *[]){ "d", ".", "f", NULL });
@@ -8354,6 +8827,87 @@ static int ssl_setAlpnProtos(lua_State *L) {
8354#endif 8827#endif
8355 8828
8356 8829
8830static int ssl_setTLSextStatusType(lua_State *L) {
8831 SSL *ssl = checksimple(L, 1, SSL_CLASS);
8832 int type = checkTLSEXT_STATUSTYPE(L, 2);
8833
8834 if(!SSL_set_tlsext_status_type(ssl, type))
8835 return auxL_error(L, auxL_EOPENSSL, "ssl:setTLSextStatusType");
8836
8837 lua_pushboolean(L, 1);
8838
8839 return 1;
8840} /* ssl_setTLSextStatusType() */
8841
8842
8843#if HAVE_SSL_GET_TLSEXT_STATUS_TYPE
8844static int ssl_getTLSextStatusType(lua_State *L) {
8845 SSL *ssl = checksimple(L, 1, SSL_CLASS);
8846
8847 int type = SSL_get_tlsext_status_type(ssl);
8848 switch(type) {
8849 case -1:
8850 lua_pushnil(L);
8851 break;
8852 case TLSEXT_STATUSTYPE_ocsp:
8853 lua_pushliteral(L, "ocsp");
8854 break;
8855 default:
8856 luaL_error(L, "unknown TLS extension %d", type);
8857 }
8858
8859 return 1;
8860} /* ssl_getTLSextStatusType() */
8861#endif
8862
8863
8864static int ssl_setTLSextStatusOCSPResp(lua_State *L) {
8865 SSL *ssl = checksimple(L, 1, SSL_CLASS);
8866 OCSP_RESPONSE *or = testsimple(L, 2, OCSP_RESPONSE_CLASS);
8867
8868 unsigned char *resp = NULL;
8869 long resp_len;
8870
8871 if (or) {
8872 resp_len = i2d_OCSP_RESPONSE(or, &resp);
8873 if (resp_len <= 0)
8874 return auxL_error(L, auxL_EOPENSSL, "ssl:setTLSextStatusOCSPResp");
8875 } else {
8876 resp_len = 0;
8877 }
8878
8879 if (!SSL_set_tlsext_status_ocsp_resp(ssl, resp, resp_len))
8880 return auxL_error(L, auxL_EOPENSSL, "ssl:setTLSextStatusOCSPResp");
8881
8882 lua_pushboolean(L, 1);
8883
8884 return 1;
8885} /* ssl_setTLSextStatusOCSPResp() */
8886
8887
8888static int ssl_getTLSextStatusOCSPResp(lua_State *L) {
8889 SSL *ssl = checksimple(L, 1, SSL_CLASS);
8890
8891 OCSP_RESPONSE **ud = prepsimple(L, OCSP_RESPONSE_CLASS);
8892 const unsigned char *resp;
8893 long resp_len;
8894
8895 resp_len = SSL_get_tlsext_status_ocsp_resp(ssl, &resp);
8896 if (resp == NULL) {
8897 lua_pushnil(L);
8898 return 1;
8899 }
8900 if (resp_len == -1)
8901 return auxL_error(L, auxL_EOPENSSL, "ssl:getTLSextStatusOCSPResp");
8902
8903 *ud = d2i_OCSP_RESPONSE(NULL, &resp, resp_len);
8904 if(*ud == NULL)
8905 return auxL_error(L, auxL_EOPENSSL, "ssl:getTLSextStatusOCSPResp");
8906
8907 return 1;
8908} /* ssl_getTLSextStatusOCSPResp() */
8909
8910
8357static int ssl__gc(lua_State *L) { 8911static int ssl__gc(lua_State *L) {
8358 SSL **ud = luaL_checkudata(L, 1, SSL_CLASS); 8912 SSL **ud = luaL_checkudata(L, 1, SSL_CLASS);
8359 8913
@@ -8367,12 +8921,17 @@ static int ssl__gc(lua_State *L) {
8367 8921
8368 8922
8369static const auxL_Reg ssl_methods[] = { 8923static const auxL_Reg ssl_methods[] = {
8924 { "setContext", &ssl_setContext },
8370 { "setOptions", &ssl_setOptions }, 8925 { "setOptions", &ssl_setOptions },
8371 { "getOptions", &ssl_getOptions }, 8926 { "getOptions", &ssl_getOptions },
8372 { "clearOptions", &ssl_clearOptions }, 8927 { "clearOptions", &ssl_clearOptions },
8373 { "setParam", &ssl_setParam }, 8928 { "setParam", &ssl_setParam },
8374 { "getParam", &ssl_getParam }, 8929 { "getParam", &ssl_getParam },
8930 { "setVerify", &ssl_setVerify },
8931 { "getVerify", &ssl_getVerify },
8375 { "getVerifyResult", &ssl_getVerifyResult }, 8932 { "getVerifyResult", &ssl_getVerifyResult },
8933 { "setCertificate", &ssl_setCertificate },
8934 { "setPrivateKey", &ssl_setPrivateKey },
8376 { "getPeerCertificate", &ssl_getPeerCertificate }, 8935 { "getPeerCertificate", &ssl_getPeerCertificate },
8377 { "getPeerChain", &ssl_getPeerChain }, 8936 { "getPeerChain", &ssl_getPeerChain },
8378 { "getCipherInfo", &ssl_getCipherInfo }, 8937 { "getCipherInfo", &ssl_getCipherInfo },
@@ -8382,6 +8941,7 @@ static const auxL_Reg ssl_methods[] = {
8382 { "getHostName", &ssl_getHostName }, 8941 { "getHostName", &ssl_getHostName },
8383 { "setHostName", &ssl_setHostName }, 8942 { "setHostName", &ssl_setHostName },
8384 { "getVersion", &ssl_getVersion }, 8943 { "getVersion", &ssl_getVersion },
8944 { "getClientRandom", &ssl_getClientRandom },
8385 { "getClientVersion", &ssl_getClientVersion }, 8945 { "getClientVersion", &ssl_getClientVersion },
8386#if HAVE_SSL_GET0_ALPN_SELECTED 8946#if HAVE_SSL_GET0_ALPN_SELECTED
8387 { "getAlpnSelected", &ssl_getAlpnSelected }, 8947 { "getAlpnSelected", &ssl_getAlpnSelected },
@@ -8389,6 +8949,12 @@ static const auxL_Reg ssl_methods[] = {
8389#if HAVE_SSL_SET_ALPN_PROTOS 8949#if HAVE_SSL_SET_ALPN_PROTOS
8390 { "setAlpnProtos", &ssl_setAlpnProtos }, 8950 { "setAlpnProtos", &ssl_setAlpnProtos },
8391#endif 8951#endif
8952 { "setTLSextStatusType", &ssl_setTLSextStatusType },
8953#if HAVE_SSL_GET_TLSEXT_STATUS_TYPE
8954 { "getTLSextStatusType", &ssl_getTLSextStatusType },
8955#endif
8956 { "setTLSextStatusOCSPResp", &ssl_setTLSextStatusOCSPResp },
8957 { "getTLSextStatusOCSPResp", &ssl_getTLSextStatusOCSPResp },
8392 { NULL, NULL }, 8958 { NULL, NULL },
8393}; 8959};
8394 8960
@@ -9126,6 +9692,166 @@ int luaopen__openssl_cipher(lua_State *L) {
9126 9692
9127 9693
9128/* 9694/*
9695 * OCSP_RESPONSE - openssl.ocsp.response
9696 *
9697 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
9698
9699static int or_tostring(lua_State *L) {
9700 OCSP_RESPONSE *resp = checksimple(L, 1, OCSP_RESPONSE_CLASS);
9701 BIO *bio = getbio(L);
9702 size_t len;
9703 char *bytes;
9704
9705 if (!OCSP_RESPONSE_print(bio, resp, 0))
9706 return auxL_error(L, auxL_EOPENSSL, "OCSP_RESPONSE:tostring");
9707
9708 len = BIO_get_mem_data(bio, &bytes);
9709 lua_pushlstring(L, bytes, len);
9710
9711 return 1;
9712} /* or__tostring() */
9713
9714
9715static int or_toPEM(lua_State *L) {
9716 OCSP_RESPONSE *resp = checksimple(L, 1, OCSP_RESPONSE_CLASS);
9717 BIO *bio = getbio(L);
9718 size_t len;
9719 char *bytes;
9720
9721 if (!PEM_write_bio_OCSP_RESPONSE(bio, resp))
9722 return auxL_error(L, auxL_EOPENSSL, "OCSP_RESPONSE:toPEM");
9723
9724 len = BIO_get_mem_data(bio, &bytes);
9725 lua_pushlstring(L, bytes, len);
9726
9727 return 1;
9728} /* or_toPEM() */
9729
9730
9731static int or_getBasic(lua_State *L) {
9732 OCSP_RESPONSE *resp = checksimple(L, 1, OCSP_RESPONSE_CLASS);
9733
9734 OCSP_BASICRESP **basic = prepsimple(L, OCSP_BASICRESP_CLASS);
9735
9736 *basic = OCSP_response_get1_basic(resp);
9737 if (!*basic)
9738 return auxL_error(L, auxL_EOPENSSL, "OCSP_RESPONSE:getBasic");
9739
9740 return 1;
9741} /* or_getBasic() */
9742
9743
9744static int or__gc(lua_State *L) {
9745 OCSP_RESPONSE **ud = luaL_checkudata(L, 1, OCSP_RESPONSE_CLASS);
9746
9747 if (*ud) {
9748 OCSP_RESPONSE_free(*ud);
9749 *ud = NULL;
9750 }
9751
9752 return 0;
9753} /* or__gc() */
9754
9755static const auxL_Reg or_methods[] = {
9756 { "tostring", &or_tostring },
9757 { "toPEM", &or_toPEM },
9758 { "getBasic", &or_getBasic },
9759 { NULL, NULL },
9760};
9761
9762static const auxL_Reg or_metatable[] = {
9763 { "__tostring", &or_tostring },
9764 { "__gc", &or__gc },
9765 { NULL, NULL },
9766};
9767
9768static const auxL_Reg or_globals[] = {
9769 { NULL, NULL },
9770};
9771
9772int luaopen__openssl_ocsp_response(lua_State *L) {
9773 initall(L);
9774
9775 auxL_newlib(L, or_globals, 0);
9776
9777 return 1;
9778} /* luaopen__openssl_ocsp_response() */
9779
9780
9781/*
9782 * OCSP_BASICRESP - openssl.ocsp.basic
9783 *
9784 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
9785
9786static int ob_verify(lua_State *L) {
9787 OCSP_BASICRESP *basic = checksimple(L, 1, OCSP_BASICRESP_CLASS);
9788 STACK_OF(X509) *certs = testsimple(L, 2, X509_CHAIN_CLASS);
9789 X509_STORE *store = testsimple(L, 3, X509_STORE_CLASS);
9790 unsigned long flags = luaL_optinteger(L, 4, 0);
9791
9792 int res = OCSP_basic_verify(basic, certs, store, flags);
9793 if (res == -1)
9794 return auxL_error(L, auxL_EOPENSSL, "OCSP_BASICRESP:verify");
9795
9796 lua_pushboolean(L, res);
9797 if (res) {
9798 return 1;
9799 } else {
9800 auxL_pusherror(L, auxL_EOPENSSL, NULL);
9801 return 2;
9802 }
9803} /* ob_verify() */
9804
9805
9806static int ob__gc(lua_State *L) {
9807 OCSP_BASICRESP **ud = luaL_checkudata(L, 1, OCSP_BASICRESP_CLASS);
9808
9809 if (*ud) {
9810 OCSP_BASICRESP_free(*ud);
9811 *ud = NULL;
9812 }
9813
9814 return 0;
9815} /* or__gc() */
9816
9817
9818static const auxL_Reg ob_methods[] = {
9819 { "verify", &ob_verify },
9820 { NULL, NULL },
9821};
9822
9823static const auxL_Reg ob_metatable[] = {
9824 { "__gc", &ob__gc },
9825 { NULL, NULL },
9826};
9827
9828static const auxL_Reg ob_globals[] = {
9829 { NULL, NULL },
9830};
9831
9832static const auxL_IntegerReg ob_verify_flags[] = {
9833 { "NOSIGS", OCSP_NOSIGS},
9834 { "NOVERIFY", OCSP_NOVERIFY},
9835 { "NOCHAIN", OCSP_NOCHAIN},
9836 { "NOCHECKS", OCSP_NOCHECKS},
9837 { "NOEXPLICIT", OCSP_NOEXPLICIT},
9838 { "TRUSTOTHER", OCSP_TRUSTOTHER},
9839 { "NOINTERN", OCSP_NOINTERN},
9840 { "TRUSTOTHER", OCSP_TRUSTOTHER},
9841 { NULL, 0 },
9842};
9843
9844int luaopen__openssl_ocsp_basic(lua_State *L) {
9845 initall(L);
9846
9847 auxL_newlib(L, ob_globals, 0);
9848 auxL_setintegers(L, ob_verify_flags);
9849
9850 return 1;
9851} /* luaopen__openssl_ocsp_basic() */
9852
9853
9854/*
9129 * Rand - openssl.rand 9855 * Rand - openssl.rand
9130 * 9856 *
9131 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 9857 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
@@ -9322,7 +10048,7 @@ static int rand_add(lua_State *L) {
9322 10048
9323 10049
9324static int rand_bytes(lua_State *L) { 10050static int rand_bytes(lua_State *L) {
9325 int size = luaL_checkint(L, 1); 10051 int size = luaL_checkinteger(L, 1);
9326 luaL_Buffer B; 10052 luaL_Buffer B;
9327 int count = 0, n; 10053 int count = 0, n;
9328 10054
@@ -9438,11 +10164,7 @@ static int rand_uniform(lua_State *L) {
9438 } else { 10164 } else {
9439 unsigned long long N, m; 10165 unsigned long long N, m;
9440 10166
9441 if (sizeof (lua_Unsigned) >= sizeof r) { 10167 N = auxL_checkunsigned(L, 1);
9442 N = luaL_checkunsigned(L, 1);
9443 } else {
9444 N = luaL_checknumber(L, 1);
9445 }
9446 10168
9447 luaL_argcheck(L, N > 1, 1, lua_pushfstring(L, "[0, %d): interval is empty", (int)N)); 10169 luaL_argcheck(L, N > 1, 1, lua_pushfstring(L, "[0, %d): interval is empty", (int)N));
9448 10170
@@ -9455,11 +10177,7 @@ static int rand_uniform(lua_State *L) {
9455 r = r % N; 10177 r = r % N;
9456 } 10178 }
9457 10179
9458 if (sizeof (lua_Unsigned) >= sizeof r) { 10180 auxL_pushunsigned(L, r);
9459 lua_pushunsigned(L, r);
9460 } else {
9461 lua_pushnumber(L, r);
9462 }
9463 10181
9464 return 1; 10182 return 1;
9465} /* rand_uniform() */ 10183} /* rand_uniform() */
@@ -9690,5 +10408,7 @@ static void initall(lua_State *L) {
9690 auxL_addclass(L, DIGEST_CLASS, md_methods, md_metatable, 0); 10408 auxL_addclass(L, DIGEST_CLASS, md_methods, md_metatable, 0);
9691 auxL_addclass(L, HMAC_CLASS, hmac_methods, hmac_metatable, 0); 10409 auxL_addclass(L, HMAC_CLASS, hmac_methods, hmac_metatable, 0);
9692 auxL_addclass(L, CIPHER_CLASS, cipher_methods, cipher_metatable, 0); 10410 auxL_addclass(L, CIPHER_CLASS, cipher_methods, cipher_metatable, 0);
10411 auxL_addclass(L, OCSP_RESPONSE_CLASS, or_methods, or_metatable, 0);
10412 auxL_addclass(L, OCSP_BASICRESP_CLASS, ob_methods, ob_metatable, 0);
9693} /* initall() */ 10413} /* initall() */
9694 10414
diff --git a/src/openssl.ocsp.basic.lua b/src/openssl.ocsp.basic.lua
new file mode 100644
index 0000000..355faf7
--- /dev/null
+++ b/src/openssl.ocsp.basic.lua
@@ -0,0 +1,3 @@
1local ob = require "_openssl.ocsp.basic"
2
3return ob
diff --git a/src/openssl.ocsp.response.lua b/src/openssl.ocsp.response.lua
new file mode 100644
index 0000000..2226096
--- /dev/null
+++ b/src/openssl.ocsp.response.lua
@@ -0,0 +1,3 @@
1local ocsp_response = require "_openssl.ocsp.response"
2
3return ocsp_response
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