summaryrefslogtreecommitdiffstats
path: root/src/lib-lua/dlua-compat.c
blob: c676186258434b57c099223834540ac38a1d4f0e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/* Copyright (c) 2017-2018 Dovecot authors, see the included COPYING file */

#include "lib.h"
#include "strnum.h"
#include "dlua-script-private.h"

#if LUA_VERSION_NUM == 502
#  error "Lua 5.2 is not supported.  Use Lua 5.1 or 5.3 instead."
#endif

#ifndef HAVE_LUAL_SETFUNCS
void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup)
{
	luaL_checkstack(L, nup + 1, "too many upvalues");
	for (; l->name != NULL; l++) {
		int i;
		lua_pushstring(L, l->name);
		for (i = 0; i < nup; i++)
			lua_pushvalue(L, -(nup + 1));
		lua_pushcclosure(L, l->func, nup);
		lua_settable(L, -(nup + 3));
	}
	lua_pop(L, nup);
}
#endif

#ifndef HAVE_LUAL_SETMETATABLE
void luaL_setmetatable(lua_State *L, const char *tname)
{
	luaL_checkstack(L, 1, "not enough stack slots");
	luaL_getmetatable(L, tname);
	lua_setmetatable(L, -2);
}
#endif

#ifndef HAVE_LUA_ISINTEGER
#  if LUA_VERSION_NUM >= 503
#    error "Lua 5.3+ should have lua_isinteger()"
#  endif
/*
 * Lua 5.3 added lua_isinteger() which tells us whether or not the input is
 * an integer.  In Lua 5.1 and 5.2, we have to emulate it.
 */
#undef lua_isinteger
int lua_isinteger(lua_State *L, int idx)
{
	int isnum;

	if (lua_type(L, idx) != LUA_TNUMBER)
		return 0;

	(void) lua_tointegerx(L, idx, &isnum);

	return isnum;
}
#endif

#ifndef HAVE_LUA_SETI
void lua_seti(lua_State *L, int index, lua_Integer n)
{
	/* stack: value (top) */
	lua_pushinteger(L, n);
	/* stack: value, n (top) */
	lua_insert(L, -2);
	/* stack: n, value (top) */

	/* adjust relative stack position */
	if (index < 0)
		index--;

	lua_settable(L, index);
}
#endif

#ifndef HAVE_LUA_TOINTEGERX
#  if LUA_VERSION_NUM >= 502
#    error "Lua 5.2+ should have lua_tointegerx()"
#  endif
/*
 * Lua 5.2 added lua_tointegerx() which tells us whether or not the
 * input was an integer. In Lua 5.1, we have to emulate it to the best of
 * our ability.
 */
lua_Integer lua_tointegerx(lua_State *L, int idx, int *isnum_r)
{
	lua_Integer integer;
	lua_Number number;
	const char *str;

	/*
	 * Unfortunately, Lua 5.1 doesn't provide MIN/MAX value macros for
	 * the lua_Integer type, so we hardcode the assumption that it is
	 * the same size as ptrdiff_t.  This matches what Lua does by
	 * default.
	 *
	 * If this compile-time assertion fails, don't forget to change the
	 * PTRDIFF_{MIN,MAX} usage below as well.
	 */
	(void) COMPILE_ERROR_IF_TRUE(sizeof(lua_Integer) != sizeof(ptrdiff_t));

	switch (lua_type(L, idx)) {
	case LUA_TSTRING:
		/* convert using str_to_long() */
		str = lua_tostring(L, idx);

		if (strncasecmp(str, "0x", 2) == 0) {
			/* hex */
			uintmax_t tmp;

			/* skip over leading 0x */
			str += 2;

			if (str_to_uintmax_hex(str, &tmp) < 0)
				break;

			*isnum_r = (tmp <= PTRDIFF_MAX) ? 1 : 0;
			return tmp;
		} else {
			/* try decimal */
			intmax_t tmp;

			if (str_to_intmax(str, &tmp) < 0)
				break;

			*isnum_r = ((tmp >= PTRDIFF_MIN) && (tmp <= PTRDIFF_MAX)) ? 1 : 0;
			return tmp;
		}

		break;
	case LUA_TNUMBER:
		/* use lua helper macro */
		number = lua_tonumber(L, idx);

		/* Lua 5.1-only macro from luaconf.h */
		lua_number2integer(integer, number);

		*isnum_r = (((lua_Number) integer) == number) ? 1 : 0;

		return integer;
	default:
		break;
	}

	/* not an integer */
	*isnum_r = 0;
	return 0;
}
#endif

#if LUA_VERSION_NUM > 501 && LUA_VERSION_NUM < 504
#  undef lua_resume
int lua_resume_compat(lua_State *L, lua_State *from, int nargs, int *nresults)
{
	*nresults = 1;
	return lua_resume(L, from, nargs);
}
#endif