Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/openzfs/module/lua/lobject.c
48383 views
1
// SPDX-License-Identifier: MIT
2
/*
3
** $Id: lobject.c,v 2.58.1.1 2013/04/12 18:48:47 roberto Exp $
4
** Some generic functions over Lua objects
5
** See Copyright Notice in lua.h
6
*/
7
8
#define lobject_c
9
#define LUA_CORE
10
11
#include <sys/lua/lua.h>
12
13
#include "lctype.h"
14
#include "ldebug.h"
15
#include "ldo.h"
16
#include "lmem.h"
17
#include "lobject.h"
18
#include "lstate.h"
19
#include "lstring.h"
20
#include "lvm.h"
21
22
23
24
LUAI_DDEF const TValue luaO_nilobject_ = {NILCONSTANT};
25
26
27
/*
28
** converts an integer to a "floating point byte", represented as
29
** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if
30
** eeeee != 0 and (xxx) otherwise.
31
*/
32
int luaO_int2fb (unsigned int x) {
33
int e = 0; /* exponent */
34
if (x < 8) return x;
35
while (x >= 0x10) {
36
x = (x+1) >> 1;
37
e++;
38
}
39
return ((e+1) << 3) | (cast_int(x) - 8);
40
}
41
42
43
/* converts back */
44
int luaO_fb2int (int x) {
45
int e = (x >> 3) & 0x1f;
46
if (e == 0) return x;
47
else return ((x & 7) + 8) << (e - 1);
48
}
49
50
51
int luaO_ceillog2 (unsigned int x) {
52
static const lu_byte log_2[256] = {
53
0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
54
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
55
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
56
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
57
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
58
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
59
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
60
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
61
};
62
int l = 0;
63
x--;
64
while (x >= 256) { l += 8; x >>= 8; }
65
return l + log_2[x];
66
}
67
68
69
lua_Number luaO_arith (int op, lua_Number v1, lua_Number v2) {
70
switch (op) {
71
case LUA_OPADD: return luai_numadd(NULL, v1, v2);
72
case LUA_OPSUB: return luai_numsub(NULL, v1, v2);
73
case LUA_OPMUL: return luai_nummul(NULL, v1, v2);
74
case LUA_OPDIV: return luai_numdiv(NULL, v1, v2);
75
case LUA_OPMOD: return luai_nummod(NULL, v1, v2);
76
case LUA_OPPOW: return luai_numpow(NULL, v1, v2);
77
case LUA_OPUNM: return luai_numunm(NULL, v1);
78
default: lua_assert(0); return 0;
79
}
80
}
81
82
83
int luaO_hexavalue (int c) {
84
if (lisdigit(c)) return c - '0';
85
else return ltolower(c) - 'a' + 10;
86
}
87
88
89
#if !defined(lua_strx2number)
90
91
92
93
static int isneg (const char **s) {
94
if (**s == '-') { (*s)++; return 1; }
95
else if (**s == '+') (*s)++;
96
return 0;
97
}
98
99
100
static lua_Number readhexa (const char **s, lua_Number r, int *count) {
101
for (; lisxdigit(cast_uchar(**s)); (*s)++) { /* read integer part */
102
r = (r * cast_num(16.0)) + cast_num(luaO_hexavalue(cast_uchar(**s)));
103
(*count)++;
104
}
105
return r;
106
}
107
108
109
/*
110
** convert an hexadecimal numeric string to a number, following
111
** C99 specification for 'strtod'
112
*/
113
static lua_Number lua_strx2number (const char *s, char **endptr) {
114
lua_Number r = 0.0;
115
int e = 0, i = 0;
116
int neg = 0; /* 1 if number is negative */
117
*endptr = cast(char *, s); /* nothing is valid yet */
118
while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */
119
neg = isneg(&s); /* check signal */
120
if (!(*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))) /* check '0x' */
121
return 0.0; /* invalid format (no '0x') */
122
s += 2; /* skip '0x' */
123
r = readhexa(&s, r, &i); /* read integer part */
124
if (*s == '.') {
125
s++; /* skip dot */
126
r = readhexa(&s, r, &e); /* read fractional part */
127
}
128
if (i == 0 && e == 0)
129
return 0.0; /* invalid format (no digit) */
130
e *= -4; /* each fractional digit divides value by 2^-4 */
131
*endptr = cast(char *, s); /* valid up to here */
132
if (*s == 'p' || *s == 'P') { /* exponent part? */
133
int exp1 = 0;
134
int neg1;
135
s++; /* skip 'p' */
136
neg1 = isneg(&s); /* signal */
137
if (!lisdigit(cast_uchar(*s)))
138
goto ret; /* must have at least one digit */
139
while (lisdigit(cast_uchar(*s))) /* read exponent */
140
exp1 = exp1 * 10 + *(s++) - '0';
141
if (neg1) exp1 = -exp1;
142
e += exp1;
143
}
144
*endptr = cast(char *, s); /* valid up to here */
145
ret:
146
if (neg) r = -r;
147
return ((e >= 0) ? (r * (1ULL << e)) : (r / (1ULL << -e)));
148
}
149
150
#endif
151
152
153
int luaO_str2d (const char *s, size_t len, lua_Number *result) {
154
char *endptr;
155
if (strpbrk(s, "nN")) /* reject 'inf' and 'nan' */
156
return 0;
157
else if (strpbrk(s, "xX")) /* hexa? */
158
*result = lua_strx2number(s, &endptr);
159
else
160
*result = lua_str2number(s, &endptr);
161
if (endptr == s) return 0; /* nothing recognized */
162
while (lisspace(cast_uchar(*endptr))) endptr++;
163
return (endptr == s + len); /* OK if no trailing characters */
164
}
165
166
167
168
static void pushstr (lua_State *L, const char *str, size_t l) {
169
setsvalue2s(L, L->top++, luaS_newlstr(L, str, l));
170
}
171
172
173
/* this function handles only `%d', `%c', %f, %p, and `%s' formats */
174
const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
175
int n = 0;
176
for (;;) {
177
const char *e = strchr(fmt, '%');
178
if (e == NULL) break;
179
luaD_checkstack(L, 2); /* fmt + item */
180
pushstr(L, fmt, e - fmt);
181
switch (*(e+1)) {
182
case 's': {
183
const char *s = va_arg(argp, char *);
184
if (s == NULL) s = "(null)";
185
pushstr(L, s, strlen(s));
186
break;
187
}
188
case 'c': {
189
char buff;
190
buff = cast(char, va_arg(argp, int));
191
pushstr(L, &buff, 1);
192
break;
193
}
194
case 'd': {
195
setnvalue(L->top++, cast_num(va_arg(argp, int)));
196
break;
197
}
198
case 'f': {
199
setnvalue(L->top++, cast_num(va_arg(argp, l_uacNumber)));
200
break;
201
}
202
case 'p': {
203
char buff[4*sizeof(void *) + 8]; /* should be enough space for a `%p' */
204
int l = lcompat_sprintf(buff, sizeof(buff), "%p", va_arg(argp, void *));
205
pushstr(L, buff, l);
206
break;
207
}
208
case '%': {
209
pushstr(L, "%", 1);
210
break;
211
}
212
default: {
213
luaG_runerror(L,
214
"invalid option " LUA_QL("%%%c") " to " LUA_QL("lua_pushfstring"),
215
*(e + 1));
216
}
217
}
218
n += 2;
219
fmt = e+2;
220
}
221
luaD_checkstack(L, 1);
222
pushstr(L, fmt, strlen(fmt));
223
if (n > 0) luaV_concat(L, n + 1);
224
return svalue(L->top - 1);
225
}
226
227
228
const char *luaO_pushfstring (lua_State *L, const char *fmt, ...) {
229
const char *msg;
230
va_list argp;
231
va_start(argp, fmt);
232
msg = luaO_pushvfstring(L, fmt, argp);
233
va_end(argp);
234
return msg;
235
}
236
237
238
/* number of chars of a literal string without the ending \0 */
239
#define LL(x) (sizeof(x)/sizeof(char) - 1)
240
241
#define RETS "..."
242
#define PRE "[string \""
243
#define POS "\"]"
244
245
#define addstr(a,b,l) ( memcpy(a,b,(l) * sizeof(char)), a += (l) )
246
247
void luaO_chunkid (char *out, const char *source, size_t bufflen) {
248
size_t l = strlen(source);
249
if (*source == '=') { /* 'literal' source */
250
if (l <= bufflen) /* small enough? */
251
memcpy(out, source + 1, l * sizeof(char));
252
else { /* truncate it */
253
addstr(out, source + 1, bufflen - 1);
254
*out = '\0';
255
}
256
}
257
else if (*source == '@') { /* file name */
258
if (l <= bufflen) /* small enough? */
259
memcpy(out, source + 1, l * sizeof(char));
260
else { /* add '...' before rest of name */
261
addstr(out, RETS, LL(RETS));
262
bufflen -= LL(RETS);
263
memcpy(out, source + 1 + l - bufflen, bufflen * sizeof(char));
264
}
265
}
266
else { /* string; format as [string "source"] */
267
const char *nl = strchr(source, '\n'); /* find first new line (if any) */
268
addstr(out, PRE, LL(PRE)); /* add prefix */
269
bufflen -= LL(PRE RETS POS) + 1; /* save space for prefix+suffix+'\0' */
270
if (l < bufflen && nl == NULL) { /* small one-line source? */
271
addstr(out, source, l); /* keep it */
272
}
273
else {
274
if (nl != NULL) l = nl - source; /* stop at first newline */
275
if (l > bufflen) l = bufflen;
276
addstr(out, source, l);
277
addstr(out, RETS, LL(RETS));
278
}
279
memcpy(out, POS, (LL(POS) + 1) * sizeof(char));
280
}
281
}
282
283