1*088332b5SXin Li /*
2*088332b5SXin Li ** $Id: lstrlib.c $
3*088332b5SXin Li ** Standard library for string operations and pattern-matching
4*088332b5SXin Li ** See Copyright Notice in lua.h
5*088332b5SXin Li */
6*088332b5SXin Li
7*088332b5SXin Li #define lstrlib_c
8*088332b5SXin Li #define LUA_LIB
9*088332b5SXin Li
10*088332b5SXin Li #include "lprefix.h"
11*088332b5SXin Li
12*088332b5SXin Li
13*088332b5SXin Li #include <ctype.h>
14*088332b5SXin Li #include <float.h>
15*088332b5SXin Li #include <limits.h>
16*088332b5SXin Li #include <locale.h>
17*088332b5SXin Li #include <math.h>
18*088332b5SXin Li #include <stddef.h>
19*088332b5SXin Li #include <stdio.h>
20*088332b5SXin Li #include <stdlib.h>
21*088332b5SXin Li #include <string.h>
22*088332b5SXin Li
23*088332b5SXin Li #include "lua.h"
24*088332b5SXin Li
25*088332b5SXin Li #include "lauxlib.h"
26*088332b5SXin Li #include "lualib.h"
27*088332b5SXin Li
28*088332b5SXin Li
29*088332b5SXin Li /*
30*088332b5SXin Li ** maximum number of captures that a pattern can do during
31*088332b5SXin Li ** pattern-matching. This limit is arbitrary, but must fit in
32*088332b5SXin Li ** an unsigned char.
33*088332b5SXin Li */
34*088332b5SXin Li #if !defined(LUA_MAXCAPTURES)
35*088332b5SXin Li #define LUA_MAXCAPTURES 32
36*088332b5SXin Li #endif
37*088332b5SXin Li
38*088332b5SXin Li
39*088332b5SXin Li /* macro to 'unsign' a character */
40*088332b5SXin Li #define uchar(c) ((unsigned char)(c))
41*088332b5SXin Li
42*088332b5SXin Li
43*088332b5SXin Li /*
44*088332b5SXin Li ** Some sizes are better limited to fit in 'int', but must also fit in
45*088332b5SXin Li ** 'size_t'. (We assume that 'lua_Integer' cannot be smaller than 'int'.)
46*088332b5SXin Li */
47*088332b5SXin Li #define MAX_SIZET ((size_t)(~(size_t)0))
48*088332b5SXin Li
49*088332b5SXin Li #define MAXSIZE \
50*088332b5SXin Li (sizeof(size_t) < sizeof(int) ? MAX_SIZET : (size_t)(INT_MAX))
51*088332b5SXin Li
52*088332b5SXin Li
53*088332b5SXin Li
54*088332b5SXin Li
str_len(lua_State * L)55*088332b5SXin Li static int str_len (lua_State *L) {
56*088332b5SXin Li size_t l;
57*088332b5SXin Li luaL_checklstring(L, 1, &l);
58*088332b5SXin Li lua_pushinteger(L, (lua_Integer)l);
59*088332b5SXin Li return 1;
60*088332b5SXin Li }
61*088332b5SXin Li
62*088332b5SXin Li
63*088332b5SXin Li /*
64*088332b5SXin Li ** translate a relative initial string position
65*088332b5SXin Li ** (negative means back from end): clip result to [1, inf).
66*088332b5SXin Li ** The length of any string in Lua must fit in a lua_Integer,
67*088332b5SXin Li ** so there are no overflows in the casts.
68*088332b5SXin Li ** The inverted comparison avoids a possible overflow
69*088332b5SXin Li ** computing '-pos'.
70*088332b5SXin Li */
posrelatI(lua_Integer pos,size_t len)71*088332b5SXin Li static size_t posrelatI (lua_Integer pos, size_t len) {
72*088332b5SXin Li if (pos > 0)
73*088332b5SXin Li return (size_t)pos;
74*088332b5SXin Li else if (pos == 0)
75*088332b5SXin Li return 1;
76*088332b5SXin Li else if (pos < -(lua_Integer)len) /* inverted comparison */
77*088332b5SXin Li return 1; /* clip to 1 */
78*088332b5SXin Li else return len + (size_t)pos + 1;
79*088332b5SXin Li }
80*088332b5SXin Li
81*088332b5SXin Li
82*088332b5SXin Li /*
83*088332b5SXin Li ** Gets an optional ending string position from argument 'arg',
84*088332b5SXin Li ** with default value 'def'.
85*088332b5SXin Li ** Negative means back from end: clip result to [0, len]
86*088332b5SXin Li */
getendpos(lua_State * L,int arg,lua_Integer def,size_t len)87*088332b5SXin Li static size_t getendpos (lua_State *L, int arg, lua_Integer def,
88*088332b5SXin Li size_t len) {
89*088332b5SXin Li lua_Integer pos = luaL_optinteger(L, arg, def);
90*088332b5SXin Li if (pos > (lua_Integer)len)
91*088332b5SXin Li return len;
92*088332b5SXin Li else if (pos >= 0)
93*088332b5SXin Li return (size_t)pos;
94*088332b5SXin Li else if (pos < -(lua_Integer)len)
95*088332b5SXin Li return 0;
96*088332b5SXin Li else return len + (size_t)pos + 1;
97*088332b5SXin Li }
98*088332b5SXin Li
99*088332b5SXin Li
str_sub(lua_State * L)100*088332b5SXin Li static int str_sub (lua_State *L) {
101*088332b5SXin Li size_t l;
102*088332b5SXin Li const char *s = luaL_checklstring(L, 1, &l);
103*088332b5SXin Li size_t start = posrelatI(luaL_checkinteger(L, 2), l);
104*088332b5SXin Li size_t end = getendpos(L, 3, -1, l);
105*088332b5SXin Li if (start <= end)
106*088332b5SXin Li lua_pushlstring(L, s + start - 1, (end - start) + 1);
107*088332b5SXin Li else lua_pushliteral(L, "");
108*088332b5SXin Li return 1;
109*088332b5SXin Li }
110*088332b5SXin Li
111*088332b5SXin Li
str_reverse(lua_State * L)112*088332b5SXin Li static int str_reverse (lua_State *L) {
113*088332b5SXin Li size_t l, i;
114*088332b5SXin Li luaL_Buffer b;
115*088332b5SXin Li const char *s = luaL_checklstring(L, 1, &l);
116*088332b5SXin Li char *p = luaL_buffinitsize(L, &b, l);
117*088332b5SXin Li for (i = 0; i < l; i++)
118*088332b5SXin Li p[i] = s[l - i - 1];
119*088332b5SXin Li luaL_pushresultsize(&b, l);
120*088332b5SXin Li return 1;
121*088332b5SXin Li }
122*088332b5SXin Li
123*088332b5SXin Li
str_lower(lua_State * L)124*088332b5SXin Li static int str_lower (lua_State *L) {
125*088332b5SXin Li size_t l;
126*088332b5SXin Li size_t i;
127*088332b5SXin Li luaL_Buffer b;
128*088332b5SXin Li const char *s = luaL_checklstring(L, 1, &l);
129*088332b5SXin Li char *p = luaL_buffinitsize(L, &b, l);
130*088332b5SXin Li for (i=0; i<l; i++)
131*088332b5SXin Li p[i] = tolower(uchar(s[i]));
132*088332b5SXin Li luaL_pushresultsize(&b, l);
133*088332b5SXin Li return 1;
134*088332b5SXin Li }
135*088332b5SXin Li
136*088332b5SXin Li
str_upper(lua_State * L)137*088332b5SXin Li static int str_upper (lua_State *L) {
138*088332b5SXin Li size_t l;
139*088332b5SXin Li size_t i;
140*088332b5SXin Li luaL_Buffer b;
141*088332b5SXin Li const char *s = luaL_checklstring(L, 1, &l);
142*088332b5SXin Li char *p = luaL_buffinitsize(L, &b, l);
143*088332b5SXin Li for (i=0; i<l; i++)
144*088332b5SXin Li p[i] = toupper(uchar(s[i]));
145*088332b5SXin Li luaL_pushresultsize(&b, l);
146*088332b5SXin Li return 1;
147*088332b5SXin Li }
148*088332b5SXin Li
149*088332b5SXin Li
str_rep(lua_State * L)150*088332b5SXin Li static int str_rep (lua_State *L) {
151*088332b5SXin Li size_t l, lsep;
152*088332b5SXin Li const char *s = luaL_checklstring(L, 1, &l);
153*088332b5SXin Li lua_Integer n = luaL_checkinteger(L, 2);
154*088332b5SXin Li const char *sep = luaL_optlstring(L, 3, "", &lsep);
155*088332b5SXin Li if (n <= 0) lua_pushliteral(L, "");
156*088332b5SXin Li else if (l + lsep < l || l + lsep > MAXSIZE / n) /* may overflow? */
157*088332b5SXin Li return luaL_error(L, "resulting string too large");
158*088332b5SXin Li else {
159*088332b5SXin Li size_t totallen = (size_t)n * l + (size_t)(n - 1) * lsep;
160*088332b5SXin Li luaL_Buffer b;
161*088332b5SXin Li char *p = luaL_buffinitsize(L, &b, totallen);
162*088332b5SXin Li while (n-- > 1) { /* first n-1 copies (followed by separator) */
163*088332b5SXin Li memcpy(p, s, l * sizeof(char)); p += l;
164*088332b5SXin Li if (lsep > 0) { /* empty 'memcpy' is not that cheap */
165*088332b5SXin Li memcpy(p, sep, lsep * sizeof(char));
166*088332b5SXin Li p += lsep;
167*088332b5SXin Li }
168*088332b5SXin Li }
169*088332b5SXin Li memcpy(p, s, l * sizeof(char)); /* last copy (not followed by separator) */
170*088332b5SXin Li luaL_pushresultsize(&b, totallen);
171*088332b5SXin Li }
172*088332b5SXin Li return 1;
173*088332b5SXin Li }
174*088332b5SXin Li
175*088332b5SXin Li
str_byte(lua_State * L)176*088332b5SXin Li static int str_byte (lua_State *L) {
177*088332b5SXin Li size_t l;
178*088332b5SXin Li const char *s = luaL_checklstring(L, 1, &l);
179*088332b5SXin Li lua_Integer pi = luaL_optinteger(L, 2, 1);
180*088332b5SXin Li size_t posi = posrelatI(pi, l);
181*088332b5SXin Li size_t pose = getendpos(L, 3, pi, l);
182*088332b5SXin Li int n, i;
183*088332b5SXin Li if (posi > pose) return 0; /* empty interval; return no values */
184*088332b5SXin Li if (pose - posi >= (size_t)INT_MAX) /* arithmetic overflow? */
185*088332b5SXin Li return luaL_error(L, "string slice too long");
186*088332b5SXin Li n = (int)(pose - posi) + 1;
187*088332b5SXin Li luaL_checkstack(L, n, "string slice too long");
188*088332b5SXin Li for (i=0; i<n; i++)
189*088332b5SXin Li lua_pushinteger(L, uchar(s[posi+i-1]));
190*088332b5SXin Li return n;
191*088332b5SXin Li }
192*088332b5SXin Li
193*088332b5SXin Li
str_char(lua_State * L)194*088332b5SXin Li static int str_char (lua_State *L) {
195*088332b5SXin Li int n = lua_gettop(L); /* number of arguments */
196*088332b5SXin Li int i;
197*088332b5SXin Li luaL_Buffer b;
198*088332b5SXin Li char *p = luaL_buffinitsize(L, &b, n);
199*088332b5SXin Li for (i=1; i<=n; i++) {
200*088332b5SXin Li lua_Unsigned c = (lua_Unsigned)luaL_checkinteger(L, i);
201*088332b5SXin Li luaL_argcheck(L, c <= (lua_Unsigned)UCHAR_MAX, i, "value out of range");
202*088332b5SXin Li p[i - 1] = uchar(c);
203*088332b5SXin Li }
204*088332b5SXin Li luaL_pushresultsize(&b, n);
205*088332b5SXin Li return 1;
206*088332b5SXin Li }
207*088332b5SXin Li
208*088332b5SXin Li
209*088332b5SXin Li /*
210*088332b5SXin Li ** Buffer to store the result of 'string.dump'. It must be initialized
211*088332b5SXin Li ** after the call to 'lua_dump', to ensure that the function is on the
212*088332b5SXin Li ** top of the stack when 'lua_dump' is called. ('luaL_buffinit' might
213*088332b5SXin Li ** push stuff.)
214*088332b5SXin Li */
215*088332b5SXin Li struct str_Writer {
216*088332b5SXin Li int init; /* true iff buffer has been initialized */
217*088332b5SXin Li luaL_Buffer B;
218*088332b5SXin Li };
219*088332b5SXin Li
220*088332b5SXin Li
writer(lua_State * L,const void * b,size_t size,void * ud)221*088332b5SXin Li static int writer (lua_State *L, const void *b, size_t size, void *ud) {
222*088332b5SXin Li struct str_Writer *state = (struct str_Writer *)ud;
223*088332b5SXin Li if (!state->init) {
224*088332b5SXin Li state->init = 1;
225*088332b5SXin Li luaL_buffinit(L, &state->B);
226*088332b5SXin Li }
227*088332b5SXin Li luaL_addlstring(&state->B, (const char *)b, size);
228*088332b5SXin Li return 0;
229*088332b5SXin Li }
230*088332b5SXin Li
231*088332b5SXin Li
str_dump(lua_State * L)232*088332b5SXin Li static int str_dump (lua_State *L) {
233*088332b5SXin Li struct str_Writer state;
234*088332b5SXin Li int strip = lua_toboolean(L, 2);
235*088332b5SXin Li luaL_checktype(L, 1, LUA_TFUNCTION);
236*088332b5SXin Li lua_settop(L, 1); /* ensure function is on the top of the stack */
237*088332b5SXin Li state.init = 0;
238*088332b5SXin Li if (lua_dump(L, writer, &state, strip) != 0)
239*088332b5SXin Li return luaL_error(L, "unable to dump given function");
240*088332b5SXin Li luaL_pushresult(&state.B);
241*088332b5SXin Li return 1;
242*088332b5SXin Li }
243*088332b5SXin Li
244*088332b5SXin Li
245*088332b5SXin Li
246*088332b5SXin Li /*
247*088332b5SXin Li ** {======================================================
248*088332b5SXin Li ** METAMETHODS
249*088332b5SXin Li ** =======================================================
250*088332b5SXin Li */
251*088332b5SXin Li
252*088332b5SXin Li #if defined(LUA_NOCVTS2N) /* { */
253*088332b5SXin Li
254*088332b5SXin Li /* no coercion from strings to numbers */
255*088332b5SXin Li
256*088332b5SXin Li static const luaL_Reg stringmetamethods[] = {
257*088332b5SXin Li {"__index", NULL}, /* placeholder */
258*088332b5SXin Li {NULL, NULL}
259*088332b5SXin Li };
260*088332b5SXin Li
261*088332b5SXin Li #else /* }{ */
262*088332b5SXin Li
tonum(lua_State * L,int arg)263*088332b5SXin Li static int tonum (lua_State *L, int arg) {
264*088332b5SXin Li if (lua_type(L, arg) == LUA_TNUMBER) { /* already a number? */
265*088332b5SXin Li lua_pushvalue(L, arg);
266*088332b5SXin Li return 1;
267*088332b5SXin Li }
268*088332b5SXin Li else { /* check whether it is a numerical string */
269*088332b5SXin Li size_t len;
270*088332b5SXin Li const char *s = lua_tolstring(L, arg, &len);
271*088332b5SXin Li return (s != NULL && lua_stringtonumber(L, s) == len + 1);
272*088332b5SXin Li }
273*088332b5SXin Li }
274*088332b5SXin Li
275*088332b5SXin Li
trymt(lua_State * L,const char * mtname)276*088332b5SXin Li static void trymt (lua_State *L, const char *mtname) {
277*088332b5SXin Li lua_settop(L, 2); /* back to the original arguments */
278*088332b5SXin Li if (lua_type(L, 2) == LUA_TSTRING || !luaL_getmetafield(L, 2, mtname))
279*088332b5SXin Li luaL_error(L, "attempt to %s a '%s' with a '%s'", mtname + 2,
280*088332b5SXin Li luaL_typename(L, -2), luaL_typename(L, -1));
281*088332b5SXin Li lua_insert(L, -3); /* put metamethod before arguments */
282*088332b5SXin Li lua_call(L, 2, 1); /* call metamethod */
283*088332b5SXin Li }
284*088332b5SXin Li
285*088332b5SXin Li
arith(lua_State * L,int op,const char * mtname)286*088332b5SXin Li static int arith (lua_State *L, int op, const char *mtname) {
287*088332b5SXin Li if (tonum(L, 1) && tonum(L, 2))
288*088332b5SXin Li lua_arith(L, op); /* result will be on the top */
289*088332b5SXin Li else
290*088332b5SXin Li trymt(L, mtname);
291*088332b5SXin Li return 1;
292*088332b5SXin Li }
293*088332b5SXin Li
294*088332b5SXin Li
arith_add(lua_State * L)295*088332b5SXin Li static int arith_add (lua_State *L) {
296*088332b5SXin Li return arith(L, LUA_OPADD, "__add");
297*088332b5SXin Li }
298*088332b5SXin Li
arith_sub(lua_State * L)299*088332b5SXin Li static int arith_sub (lua_State *L) {
300*088332b5SXin Li return arith(L, LUA_OPSUB, "__sub");
301*088332b5SXin Li }
302*088332b5SXin Li
arith_mul(lua_State * L)303*088332b5SXin Li static int arith_mul (lua_State *L) {
304*088332b5SXin Li return arith(L, LUA_OPMUL, "__mul");
305*088332b5SXin Li }
306*088332b5SXin Li
arith_mod(lua_State * L)307*088332b5SXin Li static int arith_mod (lua_State *L) {
308*088332b5SXin Li return arith(L, LUA_OPMOD, "__mod");
309*088332b5SXin Li }
310*088332b5SXin Li
arith_pow(lua_State * L)311*088332b5SXin Li static int arith_pow (lua_State *L) {
312*088332b5SXin Li return arith(L, LUA_OPPOW, "__pow");
313*088332b5SXin Li }
314*088332b5SXin Li
arith_div(lua_State * L)315*088332b5SXin Li static int arith_div (lua_State *L) {
316*088332b5SXin Li return arith(L, LUA_OPDIV, "__div");
317*088332b5SXin Li }
318*088332b5SXin Li
arith_idiv(lua_State * L)319*088332b5SXin Li static int arith_idiv (lua_State *L) {
320*088332b5SXin Li return arith(L, LUA_OPIDIV, "__idiv");
321*088332b5SXin Li }
322*088332b5SXin Li
arith_unm(lua_State * L)323*088332b5SXin Li static int arith_unm (lua_State *L) {
324*088332b5SXin Li return arith(L, LUA_OPUNM, "__unm");
325*088332b5SXin Li }
326*088332b5SXin Li
327*088332b5SXin Li
328*088332b5SXin Li static const luaL_Reg stringmetamethods[] = {
329*088332b5SXin Li {"__add", arith_add},
330*088332b5SXin Li {"__sub", arith_sub},
331*088332b5SXin Li {"__mul", arith_mul},
332*088332b5SXin Li {"__mod", arith_mod},
333*088332b5SXin Li {"__pow", arith_pow},
334*088332b5SXin Li {"__div", arith_div},
335*088332b5SXin Li {"__idiv", arith_idiv},
336*088332b5SXin Li {"__unm", arith_unm},
337*088332b5SXin Li {"__index", NULL}, /* placeholder */
338*088332b5SXin Li {NULL, NULL}
339*088332b5SXin Li };
340*088332b5SXin Li
341*088332b5SXin Li #endif /* } */
342*088332b5SXin Li
343*088332b5SXin Li /* }====================================================== */
344*088332b5SXin Li
345*088332b5SXin Li /*
346*088332b5SXin Li ** {======================================================
347*088332b5SXin Li ** PATTERN MATCHING
348*088332b5SXin Li ** =======================================================
349*088332b5SXin Li */
350*088332b5SXin Li
351*088332b5SXin Li
352*088332b5SXin Li #define CAP_UNFINISHED (-1)
353*088332b5SXin Li #define CAP_POSITION (-2)
354*088332b5SXin Li
355*088332b5SXin Li
356*088332b5SXin Li typedef struct MatchState {
357*088332b5SXin Li const char *src_init; /* init of source string */
358*088332b5SXin Li const char *src_end; /* end ('\0') of source string */
359*088332b5SXin Li const char *p_end; /* end ('\0') of pattern */
360*088332b5SXin Li lua_State *L;
361*088332b5SXin Li int matchdepth; /* control for recursive depth (to avoid C stack overflow) */
362*088332b5SXin Li unsigned char level; /* total number of captures (finished or unfinished) */
363*088332b5SXin Li struct {
364*088332b5SXin Li const char *init;
365*088332b5SXin Li ptrdiff_t len;
366*088332b5SXin Li } capture[LUA_MAXCAPTURES];
367*088332b5SXin Li } MatchState;
368*088332b5SXin Li
369*088332b5SXin Li
370*088332b5SXin Li /* recursive function */
371*088332b5SXin Li static const char *match (MatchState *ms, const char *s, const char *p);
372*088332b5SXin Li
373*088332b5SXin Li
374*088332b5SXin Li /* maximum recursion depth for 'match' */
375*088332b5SXin Li #if !defined(MAXCCALLS)
376*088332b5SXin Li #define MAXCCALLS 200
377*088332b5SXin Li #endif
378*088332b5SXin Li
379*088332b5SXin Li
380*088332b5SXin Li #define L_ESC '%'
381*088332b5SXin Li #define SPECIALS "^$*+?.([%-"
382*088332b5SXin Li
383*088332b5SXin Li
check_capture(MatchState * ms,int l)384*088332b5SXin Li static int check_capture (MatchState *ms, int l) {
385*088332b5SXin Li l -= '1';
386*088332b5SXin Li if (l < 0 || l >= ms->level || ms->capture[l].len == CAP_UNFINISHED)
387*088332b5SXin Li return luaL_error(ms->L, "invalid capture index %%%d", l + 1);
388*088332b5SXin Li return l;
389*088332b5SXin Li }
390*088332b5SXin Li
391*088332b5SXin Li
capture_to_close(MatchState * ms)392*088332b5SXin Li static int capture_to_close (MatchState *ms) {
393*088332b5SXin Li int level = ms->level;
394*088332b5SXin Li for (level--; level>=0; level--)
395*088332b5SXin Li if (ms->capture[level].len == CAP_UNFINISHED) return level;
396*088332b5SXin Li return luaL_error(ms->L, "invalid pattern capture");
397*088332b5SXin Li }
398*088332b5SXin Li
399*088332b5SXin Li
classend(MatchState * ms,const char * p)400*088332b5SXin Li static const char *classend (MatchState *ms, const char *p) {
401*088332b5SXin Li switch (*p++) {
402*088332b5SXin Li case L_ESC: {
403*088332b5SXin Li if (p == ms->p_end)
404*088332b5SXin Li luaL_error(ms->L, "malformed pattern (ends with '%%')");
405*088332b5SXin Li return p+1;
406*088332b5SXin Li }
407*088332b5SXin Li case '[': {
408*088332b5SXin Li if (*p == '^') p++;
409*088332b5SXin Li do { /* look for a ']' */
410*088332b5SXin Li if (p == ms->p_end)
411*088332b5SXin Li luaL_error(ms->L, "malformed pattern (missing ']')");
412*088332b5SXin Li if (*(p++) == L_ESC && p < ms->p_end)
413*088332b5SXin Li p++; /* skip escapes (e.g. '%]') */
414*088332b5SXin Li } while (*p != ']');
415*088332b5SXin Li return p+1;
416*088332b5SXin Li }
417*088332b5SXin Li default: {
418*088332b5SXin Li return p;
419*088332b5SXin Li }
420*088332b5SXin Li }
421*088332b5SXin Li }
422*088332b5SXin Li
423*088332b5SXin Li
match_class(int c,int cl)424*088332b5SXin Li static int match_class (int c, int cl) {
425*088332b5SXin Li int res;
426*088332b5SXin Li switch (tolower(cl)) {
427*088332b5SXin Li case 'a' : res = isalpha(c); break;
428*088332b5SXin Li case 'c' : res = iscntrl(c); break;
429*088332b5SXin Li case 'd' : res = isdigit(c); break;
430*088332b5SXin Li case 'g' : res = isgraph(c); break;
431*088332b5SXin Li case 'l' : res = islower(c); break;
432*088332b5SXin Li case 'p' : res = ispunct(c); break;
433*088332b5SXin Li case 's' : res = isspace(c); break;
434*088332b5SXin Li case 'u' : res = isupper(c); break;
435*088332b5SXin Li case 'w' : res = isalnum(c); break;
436*088332b5SXin Li case 'x' : res = isxdigit(c); break;
437*088332b5SXin Li case 'z' : res = (c == 0); break; /* deprecated option */
438*088332b5SXin Li default: return (cl == c);
439*088332b5SXin Li }
440*088332b5SXin Li return (islower(cl) ? res : !res);
441*088332b5SXin Li }
442*088332b5SXin Li
443*088332b5SXin Li
matchbracketclass(int c,const char * p,const char * ec)444*088332b5SXin Li static int matchbracketclass (int c, const char *p, const char *ec) {
445*088332b5SXin Li int sig = 1;
446*088332b5SXin Li if (*(p+1) == '^') {
447*088332b5SXin Li sig = 0;
448*088332b5SXin Li p++; /* skip the '^' */
449*088332b5SXin Li }
450*088332b5SXin Li while (++p < ec) {
451*088332b5SXin Li if (*p == L_ESC) {
452*088332b5SXin Li p++;
453*088332b5SXin Li if (match_class(c, uchar(*p)))
454*088332b5SXin Li return sig;
455*088332b5SXin Li }
456*088332b5SXin Li else if ((*(p+1) == '-') && (p+2 < ec)) {
457*088332b5SXin Li p+=2;
458*088332b5SXin Li if (uchar(*(p-2)) <= c && c <= uchar(*p))
459*088332b5SXin Li return sig;
460*088332b5SXin Li }
461*088332b5SXin Li else if (uchar(*p) == c) return sig;
462*088332b5SXin Li }
463*088332b5SXin Li return !sig;
464*088332b5SXin Li }
465*088332b5SXin Li
466*088332b5SXin Li
singlematch(MatchState * ms,const char * s,const char * p,const char * ep)467*088332b5SXin Li static int singlematch (MatchState *ms, const char *s, const char *p,
468*088332b5SXin Li const char *ep) {
469*088332b5SXin Li if (s >= ms->src_end)
470*088332b5SXin Li return 0;
471*088332b5SXin Li else {
472*088332b5SXin Li int c = uchar(*s);
473*088332b5SXin Li switch (*p) {
474*088332b5SXin Li case '.': return 1; /* matches any char */
475*088332b5SXin Li case L_ESC: return match_class(c, uchar(*(p+1)));
476*088332b5SXin Li case '[': return matchbracketclass(c, p, ep-1);
477*088332b5SXin Li default: return (uchar(*p) == c);
478*088332b5SXin Li }
479*088332b5SXin Li }
480*088332b5SXin Li }
481*088332b5SXin Li
482*088332b5SXin Li
matchbalance(MatchState * ms,const char * s,const char * p)483*088332b5SXin Li static const char *matchbalance (MatchState *ms, const char *s,
484*088332b5SXin Li const char *p) {
485*088332b5SXin Li if (p >= ms->p_end - 1)
486*088332b5SXin Li luaL_error(ms->L, "malformed pattern (missing arguments to '%%b')");
487*088332b5SXin Li if (*s != *p) return NULL;
488*088332b5SXin Li else {
489*088332b5SXin Li int b = *p;
490*088332b5SXin Li int e = *(p+1);
491*088332b5SXin Li int cont = 1;
492*088332b5SXin Li while (++s < ms->src_end) {
493*088332b5SXin Li if (*s == e) {
494*088332b5SXin Li if (--cont == 0) return s+1;
495*088332b5SXin Li }
496*088332b5SXin Li else if (*s == b) cont++;
497*088332b5SXin Li }
498*088332b5SXin Li }
499*088332b5SXin Li return NULL; /* string ends out of balance */
500*088332b5SXin Li }
501*088332b5SXin Li
502*088332b5SXin Li
max_expand(MatchState * ms,const char * s,const char * p,const char * ep)503*088332b5SXin Li static const char *max_expand (MatchState *ms, const char *s,
504*088332b5SXin Li const char *p, const char *ep) {
505*088332b5SXin Li ptrdiff_t i = 0; /* counts maximum expand for item */
506*088332b5SXin Li while (singlematch(ms, s + i, p, ep))
507*088332b5SXin Li i++;
508*088332b5SXin Li /* keeps trying to match with the maximum repetitions */
509*088332b5SXin Li while (i>=0) {
510*088332b5SXin Li const char *res = match(ms, (s+i), ep+1);
511*088332b5SXin Li if (res) return res;
512*088332b5SXin Li i--; /* else didn't match; reduce 1 repetition to try again */
513*088332b5SXin Li }
514*088332b5SXin Li return NULL;
515*088332b5SXin Li }
516*088332b5SXin Li
517*088332b5SXin Li
min_expand(MatchState * ms,const char * s,const char * p,const char * ep)518*088332b5SXin Li static const char *min_expand (MatchState *ms, const char *s,
519*088332b5SXin Li const char *p, const char *ep) {
520*088332b5SXin Li for (;;) {
521*088332b5SXin Li const char *res = match(ms, s, ep+1);
522*088332b5SXin Li if (res != NULL)
523*088332b5SXin Li return res;
524*088332b5SXin Li else if (singlematch(ms, s, p, ep))
525*088332b5SXin Li s++; /* try with one more repetition */
526*088332b5SXin Li else return NULL;
527*088332b5SXin Li }
528*088332b5SXin Li }
529*088332b5SXin Li
530*088332b5SXin Li
start_capture(MatchState * ms,const char * s,const char * p,int what)531*088332b5SXin Li static const char *start_capture (MatchState *ms, const char *s,
532*088332b5SXin Li const char *p, int what) {
533*088332b5SXin Li const char *res;
534*088332b5SXin Li int level = ms->level;
535*088332b5SXin Li if (level >= LUA_MAXCAPTURES) luaL_error(ms->L, "too many captures");
536*088332b5SXin Li ms->capture[level].init = s;
537*088332b5SXin Li ms->capture[level].len = what;
538*088332b5SXin Li ms->level = level+1;
539*088332b5SXin Li if ((res=match(ms, s, p)) == NULL) /* match failed? */
540*088332b5SXin Li ms->level--; /* undo capture */
541*088332b5SXin Li return res;
542*088332b5SXin Li }
543*088332b5SXin Li
544*088332b5SXin Li
end_capture(MatchState * ms,const char * s,const char * p)545*088332b5SXin Li static const char *end_capture (MatchState *ms, const char *s,
546*088332b5SXin Li const char *p) {
547*088332b5SXin Li int l = capture_to_close(ms);
548*088332b5SXin Li const char *res;
549*088332b5SXin Li ms->capture[l].len = s - ms->capture[l].init; /* close capture */
550*088332b5SXin Li if ((res = match(ms, s, p)) == NULL) /* match failed? */
551*088332b5SXin Li ms->capture[l].len = CAP_UNFINISHED; /* undo capture */
552*088332b5SXin Li return res;
553*088332b5SXin Li }
554*088332b5SXin Li
555*088332b5SXin Li
match_capture(MatchState * ms,const char * s,int l)556*088332b5SXin Li static const char *match_capture (MatchState *ms, const char *s, int l) {
557*088332b5SXin Li size_t len;
558*088332b5SXin Li l = check_capture(ms, l);
559*088332b5SXin Li len = ms->capture[l].len;
560*088332b5SXin Li if ((size_t)(ms->src_end-s) >= len &&
561*088332b5SXin Li memcmp(ms->capture[l].init, s, len) == 0)
562*088332b5SXin Li return s+len;
563*088332b5SXin Li else return NULL;
564*088332b5SXin Li }
565*088332b5SXin Li
566*088332b5SXin Li
match(MatchState * ms,const char * s,const char * p)567*088332b5SXin Li static const char *match (MatchState *ms, const char *s, const char *p) {
568*088332b5SXin Li if (ms->matchdepth-- == 0)
569*088332b5SXin Li luaL_error(ms->L, "pattern too complex");
570*088332b5SXin Li init: /* using goto's to optimize tail recursion */
571*088332b5SXin Li if (p != ms->p_end) { /* end of pattern? */
572*088332b5SXin Li switch (*p) {
573*088332b5SXin Li case '(': { /* start capture */
574*088332b5SXin Li if (*(p + 1) == ')') /* position capture? */
575*088332b5SXin Li s = start_capture(ms, s, p + 2, CAP_POSITION);
576*088332b5SXin Li else
577*088332b5SXin Li s = start_capture(ms, s, p + 1, CAP_UNFINISHED);
578*088332b5SXin Li break;
579*088332b5SXin Li }
580*088332b5SXin Li case ')': { /* end capture */
581*088332b5SXin Li s = end_capture(ms, s, p + 1);
582*088332b5SXin Li break;
583*088332b5SXin Li }
584*088332b5SXin Li case '$': {
585*088332b5SXin Li if ((p + 1) != ms->p_end) /* is the '$' the last char in pattern? */
586*088332b5SXin Li goto dflt; /* no; go to default */
587*088332b5SXin Li s = (s == ms->src_end) ? s : NULL; /* check end of string */
588*088332b5SXin Li break;
589*088332b5SXin Li }
590*088332b5SXin Li case L_ESC: { /* escaped sequences not in the format class[*+?-]? */
591*088332b5SXin Li switch (*(p + 1)) {
592*088332b5SXin Li case 'b': { /* balanced string? */
593*088332b5SXin Li s = matchbalance(ms, s, p + 2);
594*088332b5SXin Li if (s != NULL) {
595*088332b5SXin Li p += 4; goto init; /* return match(ms, s, p + 4); */
596*088332b5SXin Li } /* else fail (s == NULL) */
597*088332b5SXin Li break;
598*088332b5SXin Li }
599*088332b5SXin Li case 'f': { /* frontier? */
600*088332b5SXin Li const char *ep; char previous;
601*088332b5SXin Li p += 2;
602*088332b5SXin Li if (*p != '[')
603*088332b5SXin Li luaL_error(ms->L, "missing '[' after '%%f' in pattern");
604*088332b5SXin Li ep = classend(ms, p); /* points to what is next */
605*088332b5SXin Li previous = (s == ms->src_init) ? '\0' : *(s - 1);
606*088332b5SXin Li if (!matchbracketclass(uchar(previous), p, ep - 1) &&
607*088332b5SXin Li matchbracketclass(uchar(*s), p, ep - 1)) {
608*088332b5SXin Li p = ep; goto init; /* return match(ms, s, ep); */
609*088332b5SXin Li }
610*088332b5SXin Li s = NULL; /* match failed */
611*088332b5SXin Li break;
612*088332b5SXin Li }
613*088332b5SXin Li case '0': case '1': case '2': case '3':
614*088332b5SXin Li case '4': case '5': case '6': case '7':
615*088332b5SXin Li case '8': case '9': { /* capture results (%0-%9)? */
616*088332b5SXin Li s = match_capture(ms, s, uchar(*(p + 1)));
617*088332b5SXin Li if (s != NULL) {
618*088332b5SXin Li p += 2; goto init; /* return match(ms, s, p + 2) */
619*088332b5SXin Li }
620*088332b5SXin Li break;
621*088332b5SXin Li }
622*088332b5SXin Li default: goto dflt;
623*088332b5SXin Li }
624*088332b5SXin Li break;
625*088332b5SXin Li }
626*088332b5SXin Li default: dflt: { /* pattern class plus optional suffix */
627*088332b5SXin Li const char *ep = classend(ms, p); /* points to optional suffix */
628*088332b5SXin Li /* does not match at least once? */
629*088332b5SXin Li if (!singlematch(ms, s, p, ep)) {
630*088332b5SXin Li if (*ep == '*' || *ep == '?' || *ep == '-') { /* accept empty? */
631*088332b5SXin Li p = ep + 1; goto init; /* return match(ms, s, ep + 1); */
632*088332b5SXin Li }
633*088332b5SXin Li else /* '+' or no suffix */
634*088332b5SXin Li s = NULL; /* fail */
635*088332b5SXin Li }
636*088332b5SXin Li else { /* matched once */
637*088332b5SXin Li switch (*ep) { /* handle optional suffix */
638*088332b5SXin Li case '?': { /* optional */
639*088332b5SXin Li const char *res;
640*088332b5SXin Li if ((res = match(ms, s + 1, ep + 1)) != NULL)
641*088332b5SXin Li s = res;
642*088332b5SXin Li else {
643*088332b5SXin Li p = ep + 1; goto init; /* else return match(ms, s, ep + 1); */
644*088332b5SXin Li }
645*088332b5SXin Li break;
646*088332b5SXin Li }
647*088332b5SXin Li case '+': /* 1 or more repetitions */
648*088332b5SXin Li s++; /* 1 match already done */
649*088332b5SXin Li /* FALLTHROUGH */
650*088332b5SXin Li case '*': /* 0 or more repetitions */
651*088332b5SXin Li s = max_expand(ms, s, p, ep);
652*088332b5SXin Li break;
653*088332b5SXin Li case '-': /* 0 or more repetitions (minimum) */
654*088332b5SXin Li s = min_expand(ms, s, p, ep);
655*088332b5SXin Li break;
656*088332b5SXin Li default: /* no suffix */
657*088332b5SXin Li s++; p = ep; goto init; /* return match(ms, s + 1, ep); */
658*088332b5SXin Li }
659*088332b5SXin Li }
660*088332b5SXin Li break;
661*088332b5SXin Li }
662*088332b5SXin Li }
663*088332b5SXin Li }
664*088332b5SXin Li ms->matchdepth++;
665*088332b5SXin Li return s;
666*088332b5SXin Li }
667*088332b5SXin Li
668*088332b5SXin Li
669*088332b5SXin Li
lmemfind(const char * s1,size_t l1,const char * s2,size_t l2)670*088332b5SXin Li static const char *lmemfind (const char *s1, size_t l1,
671*088332b5SXin Li const char *s2, size_t l2) {
672*088332b5SXin Li if (l2 == 0) return s1; /* empty strings are everywhere */
673*088332b5SXin Li else if (l2 > l1) return NULL; /* avoids a negative 'l1' */
674*088332b5SXin Li else {
675*088332b5SXin Li const char *init; /* to search for a '*s2' inside 's1' */
676*088332b5SXin Li l2--; /* 1st char will be checked by 'memchr' */
677*088332b5SXin Li l1 = l1-l2; /* 's2' cannot be found after that */
678*088332b5SXin Li while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) {
679*088332b5SXin Li init++; /* 1st char is already checked */
680*088332b5SXin Li if (memcmp(init, s2+1, l2) == 0)
681*088332b5SXin Li return init-1;
682*088332b5SXin Li else { /* correct 'l1' and 's1' to try again */
683*088332b5SXin Li l1 -= init-s1;
684*088332b5SXin Li s1 = init;
685*088332b5SXin Li }
686*088332b5SXin Li }
687*088332b5SXin Li return NULL; /* not found */
688*088332b5SXin Li }
689*088332b5SXin Li }
690*088332b5SXin Li
691*088332b5SXin Li
692*088332b5SXin Li /*
693*088332b5SXin Li ** get information about the i-th capture. If there are no captures
694*088332b5SXin Li ** and 'i==0', return information about the whole match, which
695*088332b5SXin Li ** is the range 's'..'e'. If the capture is a string, return
696*088332b5SXin Li ** its length and put its address in '*cap'. If it is an integer
697*088332b5SXin Li ** (a position), push it on the stack and return CAP_POSITION.
698*088332b5SXin Li */
get_onecapture(MatchState * ms,int i,const char * s,const char * e,const char ** cap)699*088332b5SXin Li static size_t get_onecapture (MatchState *ms, int i, const char *s,
700*088332b5SXin Li const char *e, const char **cap) {
701*088332b5SXin Li if (i >= ms->level) {
702*088332b5SXin Li if (i != 0)
703*088332b5SXin Li luaL_error(ms->L, "invalid capture index %%%d", i + 1);
704*088332b5SXin Li *cap = s;
705*088332b5SXin Li return e - s;
706*088332b5SXin Li }
707*088332b5SXin Li else {
708*088332b5SXin Li ptrdiff_t capl = ms->capture[i].len;
709*088332b5SXin Li *cap = ms->capture[i].init;
710*088332b5SXin Li if (capl == CAP_UNFINISHED)
711*088332b5SXin Li luaL_error(ms->L, "unfinished capture");
712*088332b5SXin Li else if (capl == CAP_POSITION)
713*088332b5SXin Li lua_pushinteger(ms->L, (ms->capture[i].init - ms->src_init) + 1);
714*088332b5SXin Li return capl;
715*088332b5SXin Li }
716*088332b5SXin Li }
717*088332b5SXin Li
718*088332b5SXin Li
719*088332b5SXin Li /*
720*088332b5SXin Li ** Push the i-th capture on the stack.
721*088332b5SXin Li */
push_onecapture(MatchState * ms,int i,const char * s,const char * e)722*088332b5SXin Li static void push_onecapture (MatchState *ms, int i, const char *s,
723*088332b5SXin Li const char *e) {
724*088332b5SXin Li const char *cap;
725*088332b5SXin Li ptrdiff_t l = get_onecapture(ms, i, s, e, &cap);
726*088332b5SXin Li if (l != CAP_POSITION)
727*088332b5SXin Li lua_pushlstring(ms->L, cap, l);
728*088332b5SXin Li /* else position was already pushed */
729*088332b5SXin Li }
730*088332b5SXin Li
731*088332b5SXin Li
push_captures(MatchState * ms,const char * s,const char * e)732*088332b5SXin Li static int push_captures (MatchState *ms, const char *s, const char *e) {
733*088332b5SXin Li int i;
734*088332b5SXin Li int nlevels = (ms->level == 0 && s) ? 1 : ms->level;
735*088332b5SXin Li luaL_checkstack(ms->L, nlevels, "too many captures");
736*088332b5SXin Li for (i = 0; i < nlevels; i++)
737*088332b5SXin Li push_onecapture(ms, i, s, e);
738*088332b5SXin Li return nlevels; /* number of strings pushed */
739*088332b5SXin Li }
740*088332b5SXin Li
741*088332b5SXin Li
742*088332b5SXin Li /* check whether pattern has no special characters */
nospecials(const char * p,size_t l)743*088332b5SXin Li static int nospecials (const char *p, size_t l) {
744*088332b5SXin Li size_t upto = 0;
745*088332b5SXin Li do {
746*088332b5SXin Li if (strpbrk(p + upto, SPECIALS))
747*088332b5SXin Li return 0; /* pattern has a special character */
748*088332b5SXin Li upto += strlen(p + upto) + 1; /* may have more after \0 */
749*088332b5SXin Li } while (upto <= l);
750*088332b5SXin Li return 1; /* no special chars found */
751*088332b5SXin Li }
752*088332b5SXin Li
753*088332b5SXin Li
prepstate(MatchState * ms,lua_State * L,const char * s,size_t ls,const char * p,size_t lp)754*088332b5SXin Li static void prepstate (MatchState *ms, lua_State *L,
755*088332b5SXin Li const char *s, size_t ls, const char *p, size_t lp) {
756*088332b5SXin Li ms->L = L;
757*088332b5SXin Li ms->matchdepth = MAXCCALLS;
758*088332b5SXin Li ms->src_init = s;
759*088332b5SXin Li ms->src_end = s + ls;
760*088332b5SXin Li ms->p_end = p + lp;
761*088332b5SXin Li }
762*088332b5SXin Li
763*088332b5SXin Li
reprepstate(MatchState * ms)764*088332b5SXin Li static void reprepstate (MatchState *ms) {
765*088332b5SXin Li ms->level = 0;
766*088332b5SXin Li lua_assert(ms->matchdepth == MAXCCALLS);
767*088332b5SXin Li }
768*088332b5SXin Li
769*088332b5SXin Li
str_find_aux(lua_State * L,int find)770*088332b5SXin Li static int str_find_aux (lua_State *L, int find) {
771*088332b5SXin Li size_t ls, lp;
772*088332b5SXin Li const char *s = luaL_checklstring(L, 1, &ls);
773*088332b5SXin Li const char *p = luaL_checklstring(L, 2, &lp);
774*088332b5SXin Li size_t init = posrelatI(luaL_optinteger(L, 3, 1), ls) - 1;
775*088332b5SXin Li if (init > ls) { /* start after string's end? */
776*088332b5SXin Li luaL_pushfail(L); /* cannot find anything */
777*088332b5SXin Li return 1;
778*088332b5SXin Li }
779*088332b5SXin Li /* explicit request or no special characters? */
780*088332b5SXin Li if (find && (lua_toboolean(L, 4) || nospecials(p, lp))) {
781*088332b5SXin Li /* do a plain search */
782*088332b5SXin Li const char *s2 = lmemfind(s + init, ls - init, p, lp);
783*088332b5SXin Li if (s2) {
784*088332b5SXin Li lua_pushinteger(L, (s2 - s) + 1);
785*088332b5SXin Li lua_pushinteger(L, (s2 - s) + lp);
786*088332b5SXin Li return 2;
787*088332b5SXin Li }
788*088332b5SXin Li }
789*088332b5SXin Li else {
790*088332b5SXin Li MatchState ms;
791*088332b5SXin Li const char *s1 = s + init;
792*088332b5SXin Li int anchor = (*p == '^');
793*088332b5SXin Li if (anchor) {
794*088332b5SXin Li p++; lp--; /* skip anchor character */
795*088332b5SXin Li }
796*088332b5SXin Li prepstate(&ms, L, s, ls, p, lp);
797*088332b5SXin Li do {
798*088332b5SXin Li const char *res;
799*088332b5SXin Li reprepstate(&ms);
800*088332b5SXin Li if ((res=match(&ms, s1, p)) != NULL) {
801*088332b5SXin Li if (find) {
802*088332b5SXin Li lua_pushinteger(L, (s1 - s) + 1); /* start */
803*088332b5SXin Li lua_pushinteger(L, res - s); /* end */
804*088332b5SXin Li return push_captures(&ms, NULL, 0) + 2;
805*088332b5SXin Li }
806*088332b5SXin Li else
807*088332b5SXin Li return push_captures(&ms, s1, res);
808*088332b5SXin Li }
809*088332b5SXin Li } while (s1++ < ms.src_end && !anchor);
810*088332b5SXin Li }
811*088332b5SXin Li luaL_pushfail(L); /* not found */
812*088332b5SXin Li return 1;
813*088332b5SXin Li }
814*088332b5SXin Li
815*088332b5SXin Li
str_find(lua_State * L)816*088332b5SXin Li static int str_find (lua_State *L) {
817*088332b5SXin Li return str_find_aux(L, 1);
818*088332b5SXin Li }
819*088332b5SXin Li
820*088332b5SXin Li
str_match(lua_State * L)821*088332b5SXin Li static int str_match (lua_State *L) {
822*088332b5SXin Li return str_find_aux(L, 0);
823*088332b5SXin Li }
824*088332b5SXin Li
825*088332b5SXin Li
826*088332b5SXin Li /* state for 'gmatch' */
827*088332b5SXin Li typedef struct GMatchState {
828*088332b5SXin Li const char *src; /* current position */
829*088332b5SXin Li const char *p; /* pattern */
830*088332b5SXin Li const char *lastmatch; /* end of last match */
831*088332b5SXin Li MatchState ms; /* match state */
832*088332b5SXin Li } GMatchState;
833*088332b5SXin Li
834*088332b5SXin Li
gmatch_aux(lua_State * L)835*088332b5SXin Li static int gmatch_aux (lua_State *L) {
836*088332b5SXin Li GMatchState *gm = (GMatchState *)lua_touserdata(L, lua_upvalueindex(3));
837*088332b5SXin Li const char *src;
838*088332b5SXin Li gm->ms.L = L;
839*088332b5SXin Li for (src = gm->src; src <= gm->ms.src_end; src++) {
840*088332b5SXin Li const char *e;
841*088332b5SXin Li reprepstate(&gm->ms);
842*088332b5SXin Li if ((e = match(&gm->ms, src, gm->p)) != NULL && e != gm->lastmatch) {
843*088332b5SXin Li gm->src = gm->lastmatch = e;
844*088332b5SXin Li return push_captures(&gm->ms, src, e);
845*088332b5SXin Li }
846*088332b5SXin Li }
847*088332b5SXin Li return 0; /* not found */
848*088332b5SXin Li }
849*088332b5SXin Li
850*088332b5SXin Li
gmatch(lua_State * L)851*088332b5SXin Li static int gmatch (lua_State *L) {
852*088332b5SXin Li size_t ls, lp;
853*088332b5SXin Li const char *s = luaL_checklstring(L, 1, &ls);
854*088332b5SXin Li const char *p = luaL_checklstring(L, 2, &lp);
855*088332b5SXin Li size_t init = posrelatI(luaL_optinteger(L, 3, 1), ls) - 1;
856*088332b5SXin Li GMatchState *gm;
857*088332b5SXin Li lua_settop(L, 2); /* keep strings on closure to avoid being collected */
858*088332b5SXin Li gm = (GMatchState *)lua_newuserdatauv(L, sizeof(GMatchState), 0);
859*088332b5SXin Li if (init > ls) /* start after string's end? */
860*088332b5SXin Li init = ls + 1; /* avoid overflows in 's + init' */
861*088332b5SXin Li prepstate(&gm->ms, L, s, ls, p, lp);
862*088332b5SXin Li gm->src = s + init; gm->p = p; gm->lastmatch = NULL;
863*088332b5SXin Li lua_pushcclosure(L, gmatch_aux, 3);
864*088332b5SXin Li return 1;
865*088332b5SXin Li }
866*088332b5SXin Li
867*088332b5SXin Li
add_s(MatchState * ms,luaL_Buffer * b,const char * s,const char * e)868*088332b5SXin Li static void add_s (MatchState *ms, luaL_Buffer *b, const char *s,
869*088332b5SXin Li const char *e) {
870*088332b5SXin Li size_t l;
871*088332b5SXin Li lua_State *L = ms->L;
872*088332b5SXin Li const char *news = lua_tolstring(L, 3, &l);
873*088332b5SXin Li const char *p;
874*088332b5SXin Li while ((p = (char *)memchr(news, L_ESC, l)) != NULL) {
875*088332b5SXin Li luaL_addlstring(b, news, p - news);
876*088332b5SXin Li p++; /* skip ESC */
877*088332b5SXin Li if (*p == L_ESC) /* '%%' */
878*088332b5SXin Li luaL_addchar(b, *p);
879*088332b5SXin Li else if (*p == '0') /* '%0' */
880*088332b5SXin Li luaL_addlstring(b, s, e - s);
881*088332b5SXin Li else if (isdigit(uchar(*p))) { /* '%n' */
882*088332b5SXin Li const char *cap;
883*088332b5SXin Li ptrdiff_t resl = get_onecapture(ms, *p - '1', s, e, &cap);
884*088332b5SXin Li if (resl == CAP_POSITION)
885*088332b5SXin Li luaL_addvalue(b); /* add position to accumulated result */
886*088332b5SXin Li else
887*088332b5SXin Li luaL_addlstring(b, cap, resl);
888*088332b5SXin Li }
889*088332b5SXin Li else
890*088332b5SXin Li luaL_error(L, "invalid use of '%c' in replacement string", L_ESC);
891*088332b5SXin Li l -= p + 1 - news;
892*088332b5SXin Li news = p + 1;
893*088332b5SXin Li }
894*088332b5SXin Li luaL_addlstring(b, news, l);
895*088332b5SXin Li }
896*088332b5SXin Li
897*088332b5SXin Li
898*088332b5SXin Li /*
899*088332b5SXin Li ** Add the replacement value to the string buffer 'b'.
900*088332b5SXin Li ** Return true if the original string was changed. (Function calls and
901*088332b5SXin Li ** table indexing resulting in nil or false do not change the subject.)
902*088332b5SXin Li */
add_value(MatchState * ms,luaL_Buffer * b,const char * s,const char * e,int tr)903*088332b5SXin Li static int add_value (MatchState *ms, luaL_Buffer *b, const char *s,
904*088332b5SXin Li const char *e, int tr) {
905*088332b5SXin Li lua_State *L = ms->L;
906*088332b5SXin Li switch (tr) {
907*088332b5SXin Li case LUA_TFUNCTION: { /* call the function */
908*088332b5SXin Li int n;
909*088332b5SXin Li lua_pushvalue(L, 3); /* push the function */
910*088332b5SXin Li n = push_captures(ms, s, e); /* all captures as arguments */
911*088332b5SXin Li lua_call(L, n, 1); /* call it */
912*088332b5SXin Li break;
913*088332b5SXin Li }
914*088332b5SXin Li case LUA_TTABLE: { /* index the table */
915*088332b5SXin Li push_onecapture(ms, 0, s, e); /* first capture is the index */
916*088332b5SXin Li lua_gettable(L, 3);
917*088332b5SXin Li break;
918*088332b5SXin Li }
919*088332b5SXin Li default: { /* LUA_TNUMBER or LUA_TSTRING */
920*088332b5SXin Li add_s(ms, b, s, e); /* add value to the buffer */
921*088332b5SXin Li return 1; /* something changed */
922*088332b5SXin Li }
923*088332b5SXin Li }
924*088332b5SXin Li if (!lua_toboolean(L, -1)) { /* nil or false? */
925*088332b5SXin Li lua_pop(L, 1); /* remove value */
926*088332b5SXin Li luaL_addlstring(b, s, e - s); /* keep original text */
927*088332b5SXin Li return 0; /* no changes */
928*088332b5SXin Li }
929*088332b5SXin Li else if (!lua_isstring(L, -1))
930*088332b5SXin Li return luaL_error(L, "invalid replacement value (a %s)",
931*088332b5SXin Li luaL_typename(L, -1));
932*088332b5SXin Li else {
933*088332b5SXin Li luaL_addvalue(b); /* add result to accumulator */
934*088332b5SXin Li return 1; /* something changed */
935*088332b5SXin Li }
936*088332b5SXin Li }
937*088332b5SXin Li
938*088332b5SXin Li
str_gsub(lua_State * L)939*088332b5SXin Li static int str_gsub (lua_State *L) {
940*088332b5SXin Li size_t srcl, lp;
941*088332b5SXin Li const char *src = luaL_checklstring(L, 1, &srcl); /* subject */
942*088332b5SXin Li const char *p = luaL_checklstring(L, 2, &lp); /* pattern */
943*088332b5SXin Li const char *lastmatch = NULL; /* end of last match */
944*088332b5SXin Li int tr = lua_type(L, 3); /* replacement type */
945*088332b5SXin Li lua_Integer max_s = luaL_optinteger(L, 4, srcl + 1); /* max replacements */
946*088332b5SXin Li int anchor = (*p == '^');
947*088332b5SXin Li lua_Integer n = 0; /* replacement count */
948*088332b5SXin Li int changed = 0; /* change flag */
949*088332b5SXin Li MatchState ms;
950*088332b5SXin Li luaL_Buffer b;
951*088332b5SXin Li luaL_argexpected(L, tr == LUA_TNUMBER || tr == LUA_TSTRING ||
952*088332b5SXin Li tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3,
953*088332b5SXin Li "string/function/table");
954*088332b5SXin Li luaL_buffinit(L, &b);
955*088332b5SXin Li if (anchor) {
956*088332b5SXin Li p++; lp--; /* skip anchor character */
957*088332b5SXin Li }
958*088332b5SXin Li prepstate(&ms, L, src, srcl, p, lp);
959*088332b5SXin Li while (n < max_s) {
960*088332b5SXin Li const char *e;
961*088332b5SXin Li reprepstate(&ms); /* (re)prepare state for new match */
962*088332b5SXin Li if ((e = match(&ms, src, p)) != NULL && e != lastmatch) { /* match? */
963*088332b5SXin Li n++;
964*088332b5SXin Li changed = add_value(&ms, &b, src, e, tr) | changed;
965*088332b5SXin Li src = lastmatch = e;
966*088332b5SXin Li }
967*088332b5SXin Li else if (src < ms.src_end) /* otherwise, skip one character */
968*088332b5SXin Li luaL_addchar(&b, *src++);
969*088332b5SXin Li else break; /* end of subject */
970*088332b5SXin Li if (anchor) break;
971*088332b5SXin Li }
972*088332b5SXin Li if (!changed) /* no changes? */
973*088332b5SXin Li lua_pushvalue(L, 1); /* return original string */
974*088332b5SXin Li else { /* something changed */
975*088332b5SXin Li luaL_addlstring(&b, src, ms.src_end-src);
976*088332b5SXin Li luaL_pushresult(&b); /* create and return new string */
977*088332b5SXin Li }
978*088332b5SXin Li lua_pushinteger(L, n); /* number of substitutions */
979*088332b5SXin Li return 2;
980*088332b5SXin Li }
981*088332b5SXin Li
982*088332b5SXin Li /* }====================================================== */
983*088332b5SXin Li
984*088332b5SXin Li
985*088332b5SXin Li
986*088332b5SXin Li /*
987*088332b5SXin Li ** {======================================================
988*088332b5SXin Li ** STRING FORMAT
989*088332b5SXin Li ** =======================================================
990*088332b5SXin Li */
991*088332b5SXin Li
992*088332b5SXin Li #if !defined(lua_number2strx) /* { */
993*088332b5SXin Li
994*088332b5SXin Li /*
995*088332b5SXin Li ** Hexadecimal floating-point formatter
996*088332b5SXin Li */
997*088332b5SXin Li
998*088332b5SXin Li #define SIZELENMOD (sizeof(LUA_NUMBER_FRMLEN)/sizeof(char))
999*088332b5SXin Li
1000*088332b5SXin Li
1001*088332b5SXin Li /*
1002*088332b5SXin Li ** Number of bits that goes into the first digit. It can be any value
1003*088332b5SXin Li ** between 1 and 4; the following definition tries to align the number
1004*088332b5SXin Li ** to nibble boundaries by making what is left after that first digit a
1005*088332b5SXin Li ** multiple of 4.
1006*088332b5SXin Li */
1007*088332b5SXin Li #define L_NBFD ((l_floatatt(MANT_DIG) - 1)%4 + 1)
1008*088332b5SXin Li
1009*088332b5SXin Li
1010*088332b5SXin Li /*
1011*088332b5SXin Li ** Add integer part of 'x' to buffer and return new 'x'
1012*088332b5SXin Li */
adddigit(char * buff,int n,lua_Number x)1013*088332b5SXin Li static lua_Number adddigit (char *buff, int n, lua_Number x) {
1014*088332b5SXin Li lua_Number dd = l_mathop(floor)(x); /* get integer part from 'x' */
1015*088332b5SXin Li int d = (int)dd;
1016*088332b5SXin Li buff[n] = (d < 10 ? d + '0' : d - 10 + 'a'); /* add to buffer */
1017*088332b5SXin Li return x - dd; /* return what is left */
1018*088332b5SXin Li }
1019*088332b5SXin Li
1020*088332b5SXin Li
num2straux(char * buff,int sz,lua_Number x)1021*088332b5SXin Li static int num2straux (char *buff, int sz, lua_Number x) {
1022*088332b5SXin Li /* if 'inf' or 'NaN', format it like '%g' */
1023*088332b5SXin Li if (x != x || x == (lua_Number)HUGE_VAL || x == -(lua_Number)HUGE_VAL)
1024*088332b5SXin Li return l_sprintf(buff, sz, LUA_NUMBER_FMT, (LUAI_UACNUMBER)x);
1025*088332b5SXin Li else if (x == 0) { /* can be -0... */
1026*088332b5SXin Li /* create "0" or "-0" followed by exponent */
1027*088332b5SXin Li return l_sprintf(buff, sz, LUA_NUMBER_FMT "x0p+0", (LUAI_UACNUMBER)x);
1028*088332b5SXin Li }
1029*088332b5SXin Li else {
1030*088332b5SXin Li int e;
1031*088332b5SXin Li lua_Number m = l_mathop(frexp)(x, &e); /* 'x' fraction and exponent */
1032*088332b5SXin Li int n = 0; /* character count */
1033*088332b5SXin Li if (m < 0) { /* is number negative? */
1034*088332b5SXin Li buff[n++] = '-'; /* add sign */
1035*088332b5SXin Li m = -m; /* make it positive */
1036*088332b5SXin Li }
1037*088332b5SXin Li buff[n++] = '0'; buff[n++] = 'x'; /* add "0x" */
1038*088332b5SXin Li m = adddigit(buff, n++, m * (1 << L_NBFD)); /* add first digit */
1039*088332b5SXin Li e -= L_NBFD; /* this digit goes before the radix point */
1040*088332b5SXin Li if (m > 0) { /* more digits? */
1041*088332b5SXin Li buff[n++] = lua_getlocaledecpoint(); /* add radix point */
1042*088332b5SXin Li do { /* add as many digits as needed */
1043*088332b5SXin Li m = adddigit(buff, n++, m * 16);
1044*088332b5SXin Li } while (m > 0);
1045*088332b5SXin Li }
1046*088332b5SXin Li n += l_sprintf(buff + n, sz - n, "p%+d", e); /* add exponent */
1047*088332b5SXin Li lua_assert(n < sz);
1048*088332b5SXin Li return n;
1049*088332b5SXin Li }
1050*088332b5SXin Li }
1051*088332b5SXin Li
1052*088332b5SXin Li
lua_number2strx(lua_State * L,char * buff,int sz,const char * fmt,lua_Number x)1053*088332b5SXin Li static int lua_number2strx (lua_State *L, char *buff, int sz,
1054*088332b5SXin Li const char *fmt, lua_Number x) {
1055*088332b5SXin Li int n = num2straux(buff, sz, x);
1056*088332b5SXin Li if (fmt[SIZELENMOD] == 'A') {
1057*088332b5SXin Li int i;
1058*088332b5SXin Li for (i = 0; i < n; i++)
1059*088332b5SXin Li buff[i] = toupper(uchar(buff[i]));
1060*088332b5SXin Li }
1061*088332b5SXin Li else if (fmt[SIZELENMOD] != 'a')
1062*088332b5SXin Li return luaL_error(L, "modifiers for format '%%a'/'%%A' not implemented");
1063*088332b5SXin Li return n;
1064*088332b5SXin Li }
1065*088332b5SXin Li
1066*088332b5SXin Li #endif /* } */
1067*088332b5SXin Li
1068*088332b5SXin Li
1069*088332b5SXin Li /*
1070*088332b5SXin Li ** Maximum size for items formatted with '%f'. This size is produced
1071*088332b5SXin Li ** by format('%.99f', -maxfloat), and is equal to 99 + 3 ('-', '.',
1072*088332b5SXin Li ** and '\0') + number of decimal digits to represent maxfloat (which
1073*088332b5SXin Li ** is maximum exponent + 1). (99+3+1, adding some extra, 110)
1074*088332b5SXin Li */
1075*088332b5SXin Li #define MAX_ITEMF (110 + l_floatatt(MAX_10_EXP))
1076*088332b5SXin Li
1077*088332b5SXin Li
1078*088332b5SXin Li /*
1079*088332b5SXin Li ** All formats except '%f' do not need that large limit. The other
1080*088332b5SXin Li ** float formats use exponents, so that they fit in the 99 limit for
1081*088332b5SXin Li ** significant digits; 's' for large strings and 'q' add items directly
1082*088332b5SXin Li ** to the buffer; all integer formats also fit in the 99 limit. The
1083*088332b5SXin Li ** worst case are floats: they may need 99 significant digits, plus
1084*088332b5SXin Li ** '0x', '-', '.', 'e+XXXX', and '\0'. Adding some extra, 120.
1085*088332b5SXin Li */
1086*088332b5SXin Li #define MAX_ITEM 120
1087*088332b5SXin Li
1088*088332b5SXin Li
1089*088332b5SXin Li /* valid flags in a format specification */
1090*088332b5SXin Li #if !defined(L_FMTFLAGS)
1091*088332b5SXin Li #define L_FMTFLAGS "-+ #0"
1092*088332b5SXin Li #endif
1093*088332b5SXin Li
1094*088332b5SXin Li
1095*088332b5SXin Li /*
1096*088332b5SXin Li ** maximum size of each format specification (such as "%-099.99d")
1097*088332b5SXin Li */
1098*088332b5SXin Li #define MAX_FORMAT 32
1099*088332b5SXin Li
1100*088332b5SXin Li
addquoted(luaL_Buffer * b,const char * s,size_t len)1101*088332b5SXin Li static void addquoted (luaL_Buffer *b, const char *s, size_t len) {
1102*088332b5SXin Li luaL_addchar(b, '"');
1103*088332b5SXin Li while (len--) {
1104*088332b5SXin Li if (*s == '"' || *s == '\\' || *s == '\n') {
1105*088332b5SXin Li luaL_addchar(b, '\\');
1106*088332b5SXin Li luaL_addchar(b, *s);
1107*088332b5SXin Li }
1108*088332b5SXin Li else if (iscntrl(uchar(*s))) {
1109*088332b5SXin Li char buff[10];
1110*088332b5SXin Li if (!isdigit(uchar(*(s+1))))
1111*088332b5SXin Li l_sprintf(buff, sizeof(buff), "\\%d", (int)uchar(*s));
1112*088332b5SXin Li else
1113*088332b5SXin Li l_sprintf(buff, sizeof(buff), "\\%03d", (int)uchar(*s));
1114*088332b5SXin Li luaL_addstring(b, buff);
1115*088332b5SXin Li }
1116*088332b5SXin Li else
1117*088332b5SXin Li luaL_addchar(b, *s);
1118*088332b5SXin Li s++;
1119*088332b5SXin Li }
1120*088332b5SXin Li luaL_addchar(b, '"');
1121*088332b5SXin Li }
1122*088332b5SXin Li
1123*088332b5SXin Li
1124*088332b5SXin Li /*
1125*088332b5SXin Li ** Serialize a floating-point number in such a way that it can be
1126*088332b5SXin Li ** scanned back by Lua. Use hexadecimal format for "common" numbers
1127*088332b5SXin Li ** (to preserve precision); inf, -inf, and NaN are handled separately.
1128*088332b5SXin Li ** (NaN cannot be expressed as a numeral, so we write '(0/0)' for it.)
1129*088332b5SXin Li */
quotefloat(lua_State * L,char * buff,lua_Number n)1130*088332b5SXin Li static int quotefloat (lua_State *L, char *buff, lua_Number n) {
1131*088332b5SXin Li const char *s; /* for the fixed representations */
1132*088332b5SXin Li if (n == (lua_Number)HUGE_VAL) /* inf? */
1133*088332b5SXin Li s = "1e9999";
1134*088332b5SXin Li else if (n == -(lua_Number)HUGE_VAL) /* -inf? */
1135*088332b5SXin Li s = "-1e9999";
1136*088332b5SXin Li else if (n != n) /* NaN? */
1137*088332b5SXin Li s = "(0/0)";
1138*088332b5SXin Li else { /* format number as hexadecimal */
1139*088332b5SXin Li int nb = lua_number2strx(L, buff, MAX_ITEM,
1140*088332b5SXin Li "%" LUA_NUMBER_FRMLEN "a", n);
1141*088332b5SXin Li /* ensures that 'buff' string uses a dot as the radix character */
1142*088332b5SXin Li if (memchr(buff, '.', nb) == NULL) { /* no dot? */
1143*088332b5SXin Li char point = lua_getlocaledecpoint(); /* try locale point */
1144*088332b5SXin Li char *ppoint = (char *)memchr(buff, point, nb);
1145*088332b5SXin Li if (ppoint) *ppoint = '.'; /* change it to a dot */
1146*088332b5SXin Li }
1147*088332b5SXin Li return nb;
1148*088332b5SXin Li }
1149*088332b5SXin Li /* for the fixed representations */
1150*088332b5SXin Li return l_sprintf(buff, MAX_ITEM, "%s", s);
1151*088332b5SXin Li }
1152*088332b5SXin Li
1153*088332b5SXin Li
addliteral(lua_State * L,luaL_Buffer * b,int arg)1154*088332b5SXin Li static void addliteral (lua_State *L, luaL_Buffer *b, int arg) {
1155*088332b5SXin Li switch (lua_type(L, arg)) {
1156*088332b5SXin Li case LUA_TSTRING: {
1157*088332b5SXin Li size_t len;
1158*088332b5SXin Li const char *s = lua_tolstring(L, arg, &len);
1159*088332b5SXin Li addquoted(b, s, len);
1160*088332b5SXin Li break;
1161*088332b5SXin Li }
1162*088332b5SXin Li case LUA_TNUMBER: {
1163*088332b5SXin Li char *buff = luaL_prepbuffsize(b, MAX_ITEM);
1164*088332b5SXin Li int nb;
1165*088332b5SXin Li if (!lua_isinteger(L, arg)) /* float? */
1166*088332b5SXin Li nb = quotefloat(L, buff, lua_tonumber(L, arg));
1167*088332b5SXin Li else { /* integers */
1168*088332b5SXin Li lua_Integer n = lua_tointeger(L, arg);
1169*088332b5SXin Li const char *format = (n == LUA_MININTEGER) /* corner case? */
1170*088332b5SXin Li ? "0x%" LUA_INTEGER_FRMLEN "x" /* use hex */
1171*088332b5SXin Li : LUA_INTEGER_FMT; /* else use default format */
1172*088332b5SXin Li nb = l_sprintf(buff, MAX_ITEM, format, (LUAI_UACINT)n);
1173*088332b5SXin Li }
1174*088332b5SXin Li luaL_addsize(b, nb);
1175*088332b5SXin Li break;
1176*088332b5SXin Li }
1177*088332b5SXin Li case LUA_TNIL: case LUA_TBOOLEAN: {
1178*088332b5SXin Li luaL_tolstring(L, arg, NULL);
1179*088332b5SXin Li luaL_addvalue(b);
1180*088332b5SXin Li break;
1181*088332b5SXin Li }
1182*088332b5SXin Li default: {
1183*088332b5SXin Li luaL_argerror(L, arg, "value has no literal form");
1184*088332b5SXin Li }
1185*088332b5SXin Li }
1186*088332b5SXin Li }
1187*088332b5SXin Li
1188*088332b5SXin Li
scanformat(lua_State * L,const char * strfrmt,char * form)1189*088332b5SXin Li static const char *scanformat (lua_State *L, const char *strfrmt, char *form) {
1190*088332b5SXin Li const char *p = strfrmt;
1191*088332b5SXin Li while (*p != '\0' && strchr(L_FMTFLAGS, *p) != NULL) p++; /* skip flags */
1192*088332b5SXin Li if ((size_t)(p - strfrmt) >= sizeof(L_FMTFLAGS)/sizeof(char))
1193*088332b5SXin Li luaL_error(L, "invalid format (repeated flags)");
1194*088332b5SXin Li if (isdigit(uchar(*p))) p++; /* skip width */
1195*088332b5SXin Li if (isdigit(uchar(*p))) p++; /* (2 digits at most) */
1196*088332b5SXin Li if (*p == '.') {
1197*088332b5SXin Li p++;
1198*088332b5SXin Li if (isdigit(uchar(*p))) p++; /* skip precision */
1199*088332b5SXin Li if (isdigit(uchar(*p))) p++; /* (2 digits at most) */
1200*088332b5SXin Li }
1201*088332b5SXin Li if (isdigit(uchar(*p)))
1202*088332b5SXin Li luaL_error(L, "invalid format (width or precision too long)");
1203*088332b5SXin Li *(form++) = '%';
1204*088332b5SXin Li memcpy(form, strfrmt, ((p - strfrmt) + 1) * sizeof(char));
1205*088332b5SXin Li form += (p - strfrmt) + 1;
1206*088332b5SXin Li *form = '\0';
1207*088332b5SXin Li return p;
1208*088332b5SXin Li }
1209*088332b5SXin Li
1210*088332b5SXin Li
1211*088332b5SXin Li /*
1212*088332b5SXin Li ** add length modifier into formats
1213*088332b5SXin Li */
addlenmod(char * form,const char * lenmod)1214*088332b5SXin Li static void addlenmod (char *form, const char *lenmod) {
1215*088332b5SXin Li size_t l = strlen(form);
1216*088332b5SXin Li size_t lm = strlen(lenmod);
1217*088332b5SXin Li char spec = form[l - 1];
1218*088332b5SXin Li strcpy(form + l - 1, lenmod);
1219*088332b5SXin Li form[l + lm - 1] = spec;
1220*088332b5SXin Li form[l + lm] = '\0';
1221*088332b5SXin Li }
1222*088332b5SXin Li
1223*088332b5SXin Li
str_format(lua_State * L)1224*088332b5SXin Li static int str_format (lua_State *L) {
1225*088332b5SXin Li int top = lua_gettop(L);
1226*088332b5SXin Li int arg = 1;
1227*088332b5SXin Li size_t sfl;
1228*088332b5SXin Li const char *strfrmt = luaL_checklstring(L, arg, &sfl);
1229*088332b5SXin Li const char *strfrmt_end = strfrmt+sfl;
1230*088332b5SXin Li luaL_Buffer b;
1231*088332b5SXin Li luaL_buffinit(L, &b);
1232*088332b5SXin Li while (strfrmt < strfrmt_end) {
1233*088332b5SXin Li if (*strfrmt != L_ESC)
1234*088332b5SXin Li luaL_addchar(&b, *strfrmt++);
1235*088332b5SXin Li else if (*++strfrmt == L_ESC)
1236*088332b5SXin Li luaL_addchar(&b, *strfrmt++); /* %% */
1237*088332b5SXin Li else { /* format item */
1238*088332b5SXin Li char form[MAX_FORMAT]; /* to store the format ('%...') */
1239*088332b5SXin Li int maxitem = MAX_ITEM;
1240*088332b5SXin Li char *buff = luaL_prepbuffsize(&b, maxitem); /* to put formatted item */
1241*088332b5SXin Li int nb = 0; /* number of bytes in added item */
1242*088332b5SXin Li if (++arg > top)
1243*088332b5SXin Li return luaL_argerror(L, arg, "no value");
1244*088332b5SXin Li strfrmt = scanformat(L, strfrmt, form);
1245*088332b5SXin Li switch (*strfrmt++) {
1246*088332b5SXin Li case 'c': {
1247*088332b5SXin Li nb = l_sprintf(buff, maxitem, form, (int)luaL_checkinteger(L, arg));
1248*088332b5SXin Li break;
1249*088332b5SXin Li }
1250*088332b5SXin Li case 'd': case 'i':
1251*088332b5SXin Li case 'o': case 'u': case 'x': case 'X': {
1252*088332b5SXin Li lua_Integer n = luaL_checkinteger(L, arg);
1253*088332b5SXin Li addlenmod(form, LUA_INTEGER_FRMLEN);
1254*088332b5SXin Li nb = l_sprintf(buff, maxitem, form, (LUAI_UACINT)n);
1255*088332b5SXin Li break;
1256*088332b5SXin Li }
1257*088332b5SXin Li case 'a': case 'A':
1258*088332b5SXin Li addlenmod(form, LUA_NUMBER_FRMLEN);
1259*088332b5SXin Li nb = lua_number2strx(L, buff, maxitem, form,
1260*088332b5SXin Li luaL_checknumber(L, arg));
1261*088332b5SXin Li break;
1262*088332b5SXin Li case 'f':
1263*088332b5SXin Li maxitem = MAX_ITEMF; /* extra space for '%f' */
1264*088332b5SXin Li buff = luaL_prepbuffsize(&b, maxitem);
1265*088332b5SXin Li /* FALLTHROUGH */
1266*088332b5SXin Li case 'e': case 'E': case 'g': case 'G': {
1267*088332b5SXin Li lua_Number n = luaL_checknumber(L, arg);
1268*088332b5SXin Li addlenmod(form, LUA_NUMBER_FRMLEN);
1269*088332b5SXin Li nb = l_sprintf(buff, maxitem, form, (LUAI_UACNUMBER)n);
1270*088332b5SXin Li break;
1271*088332b5SXin Li }
1272*088332b5SXin Li case 'p': {
1273*088332b5SXin Li const void *p = lua_topointer(L, arg);
1274*088332b5SXin Li if (p == NULL) { /* avoid calling 'printf' with argument NULL */
1275*088332b5SXin Li p = "(null)"; /* result */
1276*088332b5SXin Li form[strlen(form) - 1] = 's'; /* format it as a string */
1277*088332b5SXin Li }
1278*088332b5SXin Li nb = l_sprintf(buff, maxitem, form, p);
1279*088332b5SXin Li break;
1280*088332b5SXin Li }
1281*088332b5SXin Li case 'q': {
1282*088332b5SXin Li if (form[2] != '\0') /* modifiers? */
1283*088332b5SXin Li return luaL_error(L, "specifier '%%q' cannot have modifiers");
1284*088332b5SXin Li addliteral(L, &b, arg);
1285*088332b5SXin Li break;
1286*088332b5SXin Li }
1287*088332b5SXin Li case 's': {
1288*088332b5SXin Li size_t l;
1289*088332b5SXin Li const char *s = luaL_tolstring(L, arg, &l);
1290*088332b5SXin Li if (form[2] == '\0') /* no modifiers? */
1291*088332b5SXin Li luaL_addvalue(&b); /* keep entire string */
1292*088332b5SXin Li else {
1293*088332b5SXin Li luaL_argcheck(L, l == strlen(s), arg, "string contains zeros");
1294*088332b5SXin Li if (!strchr(form, '.') && l >= 100) {
1295*088332b5SXin Li /* no precision and string is too long to be formatted */
1296*088332b5SXin Li luaL_addvalue(&b); /* keep entire string */
1297*088332b5SXin Li }
1298*088332b5SXin Li else { /* format the string into 'buff' */
1299*088332b5SXin Li nb = l_sprintf(buff, maxitem, form, s);
1300*088332b5SXin Li lua_pop(L, 1); /* remove result from 'luaL_tolstring' */
1301*088332b5SXin Li }
1302*088332b5SXin Li }
1303*088332b5SXin Li break;
1304*088332b5SXin Li }
1305*088332b5SXin Li default: { /* also treat cases 'pnLlh' */
1306*088332b5SXin Li return luaL_error(L, "invalid conversion '%s' to 'format'", form);
1307*088332b5SXin Li }
1308*088332b5SXin Li }
1309*088332b5SXin Li lua_assert(nb < maxitem);
1310*088332b5SXin Li luaL_addsize(&b, nb);
1311*088332b5SXin Li }
1312*088332b5SXin Li }
1313*088332b5SXin Li luaL_pushresult(&b);
1314*088332b5SXin Li return 1;
1315*088332b5SXin Li }
1316*088332b5SXin Li
1317*088332b5SXin Li /* }====================================================== */
1318*088332b5SXin Li
1319*088332b5SXin Li
1320*088332b5SXin Li /*
1321*088332b5SXin Li ** {======================================================
1322*088332b5SXin Li ** PACK/UNPACK
1323*088332b5SXin Li ** =======================================================
1324*088332b5SXin Li */
1325*088332b5SXin Li
1326*088332b5SXin Li
1327*088332b5SXin Li /* value used for padding */
1328*088332b5SXin Li #if !defined(LUAL_PACKPADBYTE)
1329*088332b5SXin Li #define LUAL_PACKPADBYTE 0x00
1330*088332b5SXin Li #endif
1331*088332b5SXin Li
1332*088332b5SXin Li /* maximum size for the binary representation of an integer */
1333*088332b5SXin Li #define MAXINTSIZE 16
1334*088332b5SXin Li
1335*088332b5SXin Li /* number of bits in a character */
1336*088332b5SXin Li #define NB CHAR_BIT
1337*088332b5SXin Li
1338*088332b5SXin Li /* mask for one character (NB 1's) */
1339*088332b5SXin Li #define MC ((1 << NB) - 1)
1340*088332b5SXin Li
1341*088332b5SXin Li /* size of a lua_Integer */
1342*088332b5SXin Li #define SZINT ((int)sizeof(lua_Integer))
1343*088332b5SXin Li
1344*088332b5SXin Li
1345*088332b5SXin Li /* dummy union to get native endianness */
1346*088332b5SXin Li static const union {
1347*088332b5SXin Li int dummy;
1348*088332b5SXin Li char little; /* true iff machine is little endian */
1349*088332b5SXin Li } nativeendian = {1};
1350*088332b5SXin Li
1351*088332b5SXin Li
1352*088332b5SXin Li /* dummy structure to get native alignment requirements */
1353*088332b5SXin Li struct cD {
1354*088332b5SXin Li char c;
1355*088332b5SXin Li union { double d; void *p; lua_Integer i; lua_Number n; } u;
1356*088332b5SXin Li };
1357*088332b5SXin Li
1358*088332b5SXin Li #define MAXALIGN (offsetof(struct cD, u))
1359*088332b5SXin Li
1360*088332b5SXin Li
1361*088332b5SXin Li /*
1362*088332b5SXin Li ** Union for serializing floats
1363*088332b5SXin Li */
1364*088332b5SXin Li typedef union Ftypes {
1365*088332b5SXin Li float f;
1366*088332b5SXin Li double d;
1367*088332b5SXin Li lua_Number n;
1368*088332b5SXin Li char buff[5 * sizeof(lua_Number)]; /* enough for any float type */
1369*088332b5SXin Li } Ftypes;
1370*088332b5SXin Li
1371*088332b5SXin Li
1372*088332b5SXin Li /*
1373*088332b5SXin Li ** information to pack/unpack stuff
1374*088332b5SXin Li */
1375*088332b5SXin Li typedef struct Header {
1376*088332b5SXin Li lua_State *L;
1377*088332b5SXin Li int islittle;
1378*088332b5SXin Li int maxalign;
1379*088332b5SXin Li } Header;
1380*088332b5SXin Li
1381*088332b5SXin Li
1382*088332b5SXin Li /*
1383*088332b5SXin Li ** options for pack/unpack
1384*088332b5SXin Li */
1385*088332b5SXin Li typedef enum KOption {
1386*088332b5SXin Li Kint, /* signed integers */
1387*088332b5SXin Li Kuint, /* unsigned integers */
1388*088332b5SXin Li Kfloat, /* floating-point numbers */
1389*088332b5SXin Li Kchar, /* fixed-length strings */
1390*088332b5SXin Li Kstring, /* strings with prefixed length */
1391*088332b5SXin Li Kzstr, /* zero-terminated strings */
1392*088332b5SXin Li Kpadding, /* padding */
1393*088332b5SXin Li Kpaddalign, /* padding for alignment */
1394*088332b5SXin Li Knop /* no-op (configuration or spaces) */
1395*088332b5SXin Li } KOption;
1396*088332b5SXin Li
1397*088332b5SXin Li
1398*088332b5SXin Li /*
1399*088332b5SXin Li ** Read an integer numeral from string 'fmt' or return 'df' if
1400*088332b5SXin Li ** there is no numeral
1401*088332b5SXin Li */
digit(int c)1402*088332b5SXin Li static int digit (int c) { return '0' <= c && c <= '9'; }
1403*088332b5SXin Li
getnum(const char ** fmt,int df)1404*088332b5SXin Li static int getnum (const char **fmt, int df) {
1405*088332b5SXin Li if (!digit(**fmt)) /* no number? */
1406*088332b5SXin Li return df; /* return default value */
1407*088332b5SXin Li else {
1408*088332b5SXin Li int a = 0;
1409*088332b5SXin Li do {
1410*088332b5SXin Li a = a*10 + (*((*fmt)++) - '0');
1411*088332b5SXin Li } while (digit(**fmt) && a <= ((int)MAXSIZE - 9)/10);
1412*088332b5SXin Li return a;
1413*088332b5SXin Li }
1414*088332b5SXin Li }
1415*088332b5SXin Li
1416*088332b5SXin Li
1417*088332b5SXin Li /*
1418*088332b5SXin Li ** Read an integer numeral and raises an error if it is larger
1419*088332b5SXin Li ** than the maximum size for integers.
1420*088332b5SXin Li */
getnumlimit(Header * h,const char ** fmt,int df)1421*088332b5SXin Li static int getnumlimit (Header *h, const char **fmt, int df) {
1422*088332b5SXin Li int sz = getnum(fmt, df);
1423*088332b5SXin Li if (sz > MAXINTSIZE || sz <= 0)
1424*088332b5SXin Li return luaL_error(h->L, "integral size (%d) out of limits [1,%d]",
1425*088332b5SXin Li sz, MAXINTSIZE);
1426*088332b5SXin Li return sz;
1427*088332b5SXin Li }
1428*088332b5SXin Li
1429*088332b5SXin Li
1430*088332b5SXin Li /*
1431*088332b5SXin Li ** Initialize Header
1432*088332b5SXin Li */
initheader(lua_State * L,Header * h)1433*088332b5SXin Li static void initheader (lua_State *L, Header *h) {
1434*088332b5SXin Li h->L = L;
1435*088332b5SXin Li h->islittle = nativeendian.little;
1436*088332b5SXin Li h->maxalign = 1;
1437*088332b5SXin Li }
1438*088332b5SXin Li
1439*088332b5SXin Li
1440*088332b5SXin Li /*
1441*088332b5SXin Li ** Read and classify next option. 'size' is filled with option's size.
1442*088332b5SXin Li */
getoption(Header * h,const char ** fmt,int * size)1443*088332b5SXin Li static KOption getoption (Header *h, const char **fmt, int *size) {
1444*088332b5SXin Li int opt = *((*fmt)++);
1445*088332b5SXin Li *size = 0; /* default */
1446*088332b5SXin Li switch (opt) {
1447*088332b5SXin Li case 'b': *size = sizeof(char); return Kint;
1448*088332b5SXin Li case 'B': *size = sizeof(char); return Kuint;
1449*088332b5SXin Li case 'h': *size = sizeof(short); return Kint;
1450*088332b5SXin Li case 'H': *size = sizeof(short); return Kuint;
1451*088332b5SXin Li case 'l': *size = sizeof(long); return Kint;
1452*088332b5SXin Li case 'L': *size = sizeof(long); return Kuint;
1453*088332b5SXin Li case 'j': *size = sizeof(lua_Integer); return Kint;
1454*088332b5SXin Li case 'J': *size = sizeof(lua_Integer); return Kuint;
1455*088332b5SXin Li case 'T': *size = sizeof(size_t); return Kuint;
1456*088332b5SXin Li case 'f': *size = sizeof(float); return Kfloat;
1457*088332b5SXin Li case 'd': *size = sizeof(double); return Kfloat;
1458*088332b5SXin Li case 'n': *size = sizeof(lua_Number); return Kfloat;
1459*088332b5SXin Li case 'i': *size = getnumlimit(h, fmt, sizeof(int)); return Kint;
1460*088332b5SXin Li case 'I': *size = getnumlimit(h, fmt, sizeof(int)); return Kuint;
1461*088332b5SXin Li case 's': *size = getnumlimit(h, fmt, sizeof(size_t)); return Kstring;
1462*088332b5SXin Li case 'c':
1463*088332b5SXin Li *size = getnum(fmt, -1);
1464*088332b5SXin Li if (*size == -1)
1465*088332b5SXin Li luaL_error(h->L, "missing size for format option 'c'");
1466*088332b5SXin Li return Kchar;
1467*088332b5SXin Li case 'z': return Kzstr;
1468*088332b5SXin Li case 'x': *size = 1; return Kpadding;
1469*088332b5SXin Li case 'X': return Kpaddalign;
1470*088332b5SXin Li case ' ': break;
1471*088332b5SXin Li case '<': h->islittle = 1; break;
1472*088332b5SXin Li case '>': h->islittle = 0; break;
1473*088332b5SXin Li case '=': h->islittle = nativeendian.little; break;
1474*088332b5SXin Li case '!': h->maxalign = getnumlimit(h, fmt, MAXALIGN); break;
1475*088332b5SXin Li default: luaL_error(h->L, "invalid format option '%c'", opt);
1476*088332b5SXin Li }
1477*088332b5SXin Li return Knop;
1478*088332b5SXin Li }
1479*088332b5SXin Li
1480*088332b5SXin Li
1481*088332b5SXin Li /*
1482*088332b5SXin Li ** Read, classify, and fill other details about the next option.
1483*088332b5SXin Li ** 'psize' is filled with option's size, 'notoalign' with its
1484*088332b5SXin Li ** alignment requirements.
1485*088332b5SXin Li ** Local variable 'size' gets the size to be aligned. (Kpadal option
1486*088332b5SXin Li ** always gets its full alignment, other options are limited by
1487*088332b5SXin Li ** the maximum alignment ('maxalign'). Kchar option needs no alignment
1488*088332b5SXin Li ** despite its size.
1489*088332b5SXin Li */
getdetails(Header * h,size_t totalsize,const char ** fmt,int * psize,int * ntoalign)1490*088332b5SXin Li static KOption getdetails (Header *h, size_t totalsize,
1491*088332b5SXin Li const char **fmt, int *psize, int *ntoalign) {
1492*088332b5SXin Li KOption opt = getoption(h, fmt, psize);
1493*088332b5SXin Li int align = *psize; /* usually, alignment follows size */
1494*088332b5SXin Li if (opt == Kpaddalign) { /* 'X' gets alignment from following option */
1495*088332b5SXin Li if (**fmt == '\0' || getoption(h, fmt, &align) == Kchar || align == 0)
1496*088332b5SXin Li luaL_argerror(h->L, 1, "invalid next option for option 'X'");
1497*088332b5SXin Li }
1498*088332b5SXin Li if (align <= 1 || opt == Kchar) /* need no alignment? */
1499*088332b5SXin Li *ntoalign = 0;
1500*088332b5SXin Li else {
1501*088332b5SXin Li if (align > h->maxalign) /* enforce maximum alignment */
1502*088332b5SXin Li align = h->maxalign;
1503*088332b5SXin Li if ((align & (align - 1)) != 0) /* is 'align' not a power of 2? */
1504*088332b5SXin Li luaL_argerror(h->L, 1, "format asks for alignment not power of 2");
1505*088332b5SXin Li *ntoalign = (align - (int)(totalsize & (align - 1))) & (align - 1);
1506*088332b5SXin Li }
1507*088332b5SXin Li return opt;
1508*088332b5SXin Li }
1509*088332b5SXin Li
1510*088332b5SXin Li
1511*088332b5SXin Li /*
1512*088332b5SXin Li ** Pack integer 'n' with 'size' bytes and 'islittle' endianness.
1513*088332b5SXin Li ** The final 'if' handles the case when 'size' is larger than
1514*088332b5SXin Li ** the size of a Lua integer, correcting the extra sign-extension
1515*088332b5SXin Li ** bytes if necessary (by default they would be zeros).
1516*088332b5SXin Li */
packint(luaL_Buffer * b,lua_Unsigned n,int islittle,int size,int neg)1517*088332b5SXin Li static void packint (luaL_Buffer *b, lua_Unsigned n,
1518*088332b5SXin Li int islittle, int size, int neg) {
1519*088332b5SXin Li char *buff = luaL_prepbuffsize(b, size);
1520*088332b5SXin Li int i;
1521*088332b5SXin Li buff[islittle ? 0 : size - 1] = (char)(n & MC); /* first byte */
1522*088332b5SXin Li for (i = 1; i < size; i++) {
1523*088332b5SXin Li n >>= NB;
1524*088332b5SXin Li buff[islittle ? i : size - 1 - i] = (char)(n & MC);
1525*088332b5SXin Li }
1526*088332b5SXin Li if (neg && size > SZINT) { /* negative number need sign extension? */
1527*088332b5SXin Li for (i = SZINT; i < size; i++) /* correct extra bytes */
1528*088332b5SXin Li buff[islittle ? i : size - 1 - i] = (char)MC;
1529*088332b5SXin Li }
1530*088332b5SXin Li luaL_addsize(b, size); /* add result to buffer */
1531*088332b5SXin Li }
1532*088332b5SXin Li
1533*088332b5SXin Li
1534*088332b5SXin Li /*
1535*088332b5SXin Li ** Copy 'size' bytes from 'src' to 'dest', correcting endianness if
1536*088332b5SXin Li ** given 'islittle' is different from native endianness.
1537*088332b5SXin Li */
copywithendian(volatile char * dest,volatile const char * src,int size,int islittle)1538*088332b5SXin Li static void copywithendian (volatile char *dest, volatile const char *src,
1539*088332b5SXin Li int size, int islittle) {
1540*088332b5SXin Li if (islittle == nativeendian.little) {
1541*088332b5SXin Li while (size-- != 0)
1542*088332b5SXin Li *(dest++) = *(src++);
1543*088332b5SXin Li }
1544*088332b5SXin Li else {
1545*088332b5SXin Li dest += size - 1;
1546*088332b5SXin Li while (size-- != 0)
1547*088332b5SXin Li *(dest--) = *(src++);
1548*088332b5SXin Li }
1549*088332b5SXin Li }
1550*088332b5SXin Li
1551*088332b5SXin Li
str_pack(lua_State * L)1552*088332b5SXin Li static int str_pack (lua_State *L) {
1553*088332b5SXin Li luaL_Buffer b;
1554*088332b5SXin Li Header h;
1555*088332b5SXin Li const char *fmt = luaL_checkstring(L, 1); /* format string */
1556*088332b5SXin Li int arg = 1; /* current argument to pack */
1557*088332b5SXin Li size_t totalsize = 0; /* accumulate total size of result */
1558*088332b5SXin Li initheader(L, &h);
1559*088332b5SXin Li lua_pushnil(L); /* mark to separate arguments from string buffer */
1560*088332b5SXin Li luaL_buffinit(L, &b);
1561*088332b5SXin Li while (*fmt != '\0') {
1562*088332b5SXin Li int size, ntoalign;
1563*088332b5SXin Li KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign);
1564*088332b5SXin Li totalsize += ntoalign + size;
1565*088332b5SXin Li while (ntoalign-- > 0)
1566*088332b5SXin Li luaL_addchar(&b, LUAL_PACKPADBYTE); /* fill alignment */
1567*088332b5SXin Li arg++;
1568*088332b5SXin Li switch (opt) {
1569*088332b5SXin Li case Kint: { /* signed integers */
1570*088332b5SXin Li lua_Integer n = luaL_checkinteger(L, arg);
1571*088332b5SXin Li if (size < SZINT) { /* need overflow check? */
1572*088332b5SXin Li lua_Integer lim = (lua_Integer)1 << ((size * NB) - 1);
1573*088332b5SXin Li luaL_argcheck(L, -lim <= n && n < lim, arg, "integer overflow");
1574*088332b5SXin Li }
1575*088332b5SXin Li packint(&b, (lua_Unsigned)n, h.islittle, size, (n < 0));
1576*088332b5SXin Li break;
1577*088332b5SXin Li }
1578*088332b5SXin Li case Kuint: { /* unsigned integers */
1579*088332b5SXin Li lua_Integer n = luaL_checkinteger(L, arg);
1580*088332b5SXin Li if (size < SZINT) /* need overflow check? */
1581*088332b5SXin Li luaL_argcheck(L, (lua_Unsigned)n < ((lua_Unsigned)1 << (size * NB)),
1582*088332b5SXin Li arg, "unsigned overflow");
1583*088332b5SXin Li packint(&b, (lua_Unsigned)n, h.islittle, size, 0);
1584*088332b5SXin Li break;
1585*088332b5SXin Li }
1586*088332b5SXin Li case Kfloat: { /* floating-point options */
1587*088332b5SXin Li volatile Ftypes u;
1588*088332b5SXin Li char *buff = luaL_prepbuffsize(&b, size);
1589*088332b5SXin Li lua_Number n = luaL_checknumber(L, arg); /* get argument */
1590*088332b5SXin Li if (size == sizeof(u.f)) u.f = (float)n; /* copy it into 'u' */
1591*088332b5SXin Li else if (size == sizeof(u.d)) u.d = (double)n;
1592*088332b5SXin Li else u.n = n;
1593*088332b5SXin Li /* move 'u' to final result, correcting endianness if needed */
1594*088332b5SXin Li copywithendian(buff, u.buff, size, h.islittle);
1595*088332b5SXin Li luaL_addsize(&b, size);
1596*088332b5SXin Li break;
1597*088332b5SXin Li }
1598*088332b5SXin Li case Kchar: { /* fixed-size string */
1599*088332b5SXin Li size_t len;
1600*088332b5SXin Li const char *s = luaL_checklstring(L, arg, &len);
1601*088332b5SXin Li luaL_argcheck(L, len <= (size_t)size, arg,
1602*088332b5SXin Li "string longer than given size");
1603*088332b5SXin Li luaL_addlstring(&b, s, len); /* add string */
1604*088332b5SXin Li while (len++ < (size_t)size) /* pad extra space */
1605*088332b5SXin Li luaL_addchar(&b, LUAL_PACKPADBYTE);
1606*088332b5SXin Li break;
1607*088332b5SXin Li }
1608*088332b5SXin Li case Kstring: { /* strings with length count */
1609*088332b5SXin Li size_t len;
1610*088332b5SXin Li const char *s = luaL_checklstring(L, arg, &len);
1611*088332b5SXin Li luaL_argcheck(L, size >= (int)sizeof(size_t) ||
1612*088332b5SXin Li len < ((size_t)1 << (size * NB)),
1613*088332b5SXin Li arg, "string length does not fit in given size");
1614*088332b5SXin Li packint(&b, (lua_Unsigned)len, h.islittle, size, 0); /* pack length */
1615*088332b5SXin Li luaL_addlstring(&b, s, len);
1616*088332b5SXin Li totalsize += len;
1617*088332b5SXin Li break;
1618*088332b5SXin Li }
1619*088332b5SXin Li case Kzstr: { /* zero-terminated string */
1620*088332b5SXin Li size_t len;
1621*088332b5SXin Li const char *s = luaL_checklstring(L, arg, &len);
1622*088332b5SXin Li luaL_argcheck(L, strlen(s) == len, arg, "string contains zeros");
1623*088332b5SXin Li luaL_addlstring(&b, s, len);
1624*088332b5SXin Li luaL_addchar(&b, '\0'); /* add zero at the end */
1625*088332b5SXin Li totalsize += len + 1;
1626*088332b5SXin Li break;
1627*088332b5SXin Li }
1628*088332b5SXin Li case Kpadding: luaL_addchar(&b, LUAL_PACKPADBYTE); /* FALLTHROUGH */
1629*088332b5SXin Li case Kpaddalign: case Knop:
1630*088332b5SXin Li arg--; /* undo increment */
1631*088332b5SXin Li break;
1632*088332b5SXin Li }
1633*088332b5SXin Li }
1634*088332b5SXin Li luaL_pushresult(&b);
1635*088332b5SXin Li return 1;
1636*088332b5SXin Li }
1637*088332b5SXin Li
1638*088332b5SXin Li
str_packsize(lua_State * L)1639*088332b5SXin Li static int str_packsize (lua_State *L) {
1640*088332b5SXin Li Header h;
1641*088332b5SXin Li const char *fmt = luaL_checkstring(L, 1); /* format string */
1642*088332b5SXin Li size_t totalsize = 0; /* accumulate total size of result */
1643*088332b5SXin Li initheader(L, &h);
1644*088332b5SXin Li while (*fmt != '\0') {
1645*088332b5SXin Li int size, ntoalign;
1646*088332b5SXin Li KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign);
1647*088332b5SXin Li luaL_argcheck(L, opt != Kstring && opt != Kzstr, 1,
1648*088332b5SXin Li "variable-length format");
1649*088332b5SXin Li size += ntoalign; /* total space used by option */
1650*088332b5SXin Li luaL_argcheck(L, totalsize <= MAXSIZE - size, 1,
1651*088332b5SXin Li "format result too large");
1652*088332b5SXin Li totalsize += size;
1653*088332b5SXin Li }
1654*088332b5SXin Li lua_pushinteger(L, (lua_Integer)totalsize);
1655*088332b5SXin Li return 1;
1656*088332b5SXin Li }
1657*088332b5SXin Li
1658*088332b5SXin Li
1659*088332b5SXin Li /*
1660*088332b5SXin Li ** Unpack an integer with 'size' bytes and 'islittle' endianness.
1661*088332b5SXin Li ** If size is smaller than the size of a Lua integer and integer
1662*088332b5SXin Li ** is signed, must do sign extension (propagating the sign to the
1663*088332b5SXin Li ** higher bits); if size is larger than the size of a Lua integer,
1664*088332b5SXin Li ** it must check the unread bytes to see whether they do not cause an
1665*088332b5SXin Li ** overflow.
1666*088332b5SXin Li */
unpackint(lua_State * L,const char * str,int islittle,int size,int issigned)1667*088332b5SXin Li static lua_Integer unpackint (lua_State *L, const char *str,
1668*088332b5SXin Li int islittle, int size, int issigned) {
1669*088332b5SXin Li lua_Unsigned res = 0;
1670*088332b5SXin Li int i;
1671*088332b5SXin Li int limit = (size <= SZINT) ? size : SZINT;
1672*088332b5SXin Li for (i = limit - 1; i >= 0; i--) {
1673*088332b5SXin Li res <<= NB;
1674*088332b5SXin Li res |= (lua_Unsigned)(unsigned char)str[islittle ? i : size - 1 - i];
1675*088332b5SXin Li }
1676*088332b5SXin Li if (size < SZINT) { /* real size smaller than lua_Integer? */
1677*088332b5SXin Li if (issigned) { /* needs sign extension? */
1678*088332b5SXin Li lua_Unsigned mask = (lua_Unsigned)1 << (size*NB - 1);
1679*088332b5SXin Li res = ((res ^ mask) - mask); /* do sign extension */
1680*088332b5SXin Li }
1681*088332b5SXin Li }
1682*088332b5SXin Li else if (size > SZINT) { /* must check unread bytes */
1683*088332b5SXin Li int mask = (!issigned || (lua_Integer)res >= 0) ? 0 : MC;
1684*088332b5SXin Li for (i = limit; i < size; i++) {
1685*088332b5SXin Li if ((unsigned char)str[islittle ? i : size - 1 - i] != mask)
1686*088332b5SXin Li luaL_error(L, "%d-byte integer does not fit into Lua Integer", size);
1687*088332b5SXin Li }
1688*088332b5SXin Li }
1689*088332b5SXin Li return (lua_Integer)res;
1690*088332b5SXin Li }
1691*088332b5SXin Li
1692*088332b5SXin Li
str_unpack(lua_State * L)1693*088332b5SXin Li static int str_unpack (lua_State *L) {
1694*088332b5SXin Li Header h;
1695*088332b5SXin Li const char *fmt = luaL_checkstring(L, 1);
1696*088332b5SXin Li size_t ld;
1697*088332b5SXin Li const char *data = luaL_checklstring(L, 2, &ld);
1698*088332b5SXin Li size_t pos = posrelatI(luaL_optinteger(L, 3, 1), ld) - 1;
1699*088332b5SXin Li int n = 0; /* number of results */
1700*088332b5SXin Li luaL_argcheck(L, pos <= ld, 3, "initial position out of string");
1701*088332b5SXin Li initheader(L, &h);
1702*088332b5SXin Li while (*fmt != '\0') {
1703*088332b5SXin Li int size, ntoalign;
1704*088332b5SXin Li KOption opt = getdetails(&h, pos, &fmt, &size, &ntoalign);
1705*088332b5SXin Li luaL_argcheck(L, (size_t)ntoalign + size <= ld - pos, 2,
1706*088332b5SXin Li "data string too short");
1707*088332b5SXin Li pos += ntoalign; /* skip alignment */
1708*088332b5SXin Li /* stack space for item + next position */
1709*088332b5SXin Li luaL_checkstack(L, 2, "too many results");
1710*088332b5SXin Li n++;
1711*088332b5SXin Li switch (opt) {
1712*088332b5SXin Li case Kint:
1713*088332b5SXin Li case Kuint: {
1714*088332b5SXin Li lua_Integer res = unpackint(L, data + pos, h.islittle, size,
1715*088332b5SXin Li (opt == Kint));
1716*088332b5SXin Li lua_pushinteger(L, res);
1717*088332b5SXin Li break;
1718*088332b5SXin Li }
1719*088332b5SXin Li case Kfloat: {
1720*088332b5SXin Li volatile Ftypes u;
1721*088332b5SXin Li lua_Number num;
1722*088332b5SXin Li copywithendian(u.buff, data + pos, size, h.islittle);
1723*088332b5SXin Li if (size == sizeof(u.f)) num = (lua_Number)u.f;
1724*088332b5SXin Li else if (size == sizeof(u.d)) num = (lua_Number)u.d;
1725*088332b5SXin Li else num = u.n;
1726*088332b5SXin Li lua_pushnumber(L, num);
1727*088332b5SXin Li break;
1728*088332b5SXin Li }
1729*088332b5SXin Li case Kchar: {
1730*088332b5SXin Li lua_pushlstring(L, data + pos, size);
1731*088332b5SXin Li break;
1732*088332b5SXin Li }
1733*088332b5SXin Li case Kstring: {
1734*088332b5SXin Li size_t len = (size_t)unpackint(L, data + pos, h.islittle, size, 0);
1735*088332b5SXin Li luaL_argcheck(L, len <= ld - pos - size, 2, "data string too short");
1736*088332b5SXin Li lua_pushlstring(L, data + pos + size, len);
1737*088332b5SXin Li pos += len; /* skip string */
1738*088332b5SXin Li break;
1739*088332b5SXin Li }
1740*088332b5SXin Li case Kzstr: {
1741*088332b5SXin Li size_t len = (int)strlen(data + pos);
1742*088332b5SXin Li luaL_argcheck(L, pos + len < ld, 2,
1743*088332b5SXin Li "unfinished string for format 'z'");
1744*088332b5SXin Li lua_pushlstring(L, data + pos, len);
1745*088332b5SXin Li pos += len + 1; /* skip string plus final '\0' */
1746*088332b5SXin Li break;
1747*088332b5SXin Li }
1748*088332b5SXin Li case Kpaddalign: case Kpadding: case Knop:
1749*088332b5SXin Li n--; /* undo increment */
1750*088332b5SXin Li break;
1751*088332b5SXin Li }
1752*088332b5SXin Li pos += size;
1753*088332b5SXin Li }
1754*088332b5SXin Li lua_pushinteger(L, pos + 1); /* next position */
1755*088332b5SXin Li return n + 1;
1756*088332b5SXin Li }
1757*088332b5SXin Li
1758*088332b5SXin Li /* }====================================================== */
1759*088332b5SXin Li
1760*088332b5SXin Li
1761*088332b5SXin Li static const luaL_Reg strlib[] = {
1762*088332b5SXin Li {"byte", str_byte},
1763*088332b5SXin Li {"char", str_char},
1764*088332b5SXin Li {"dump", str_dump},
1765*088332b5SXin Li {"find", str_find},
1766*088332b5SXin Li {"format", str_format},
1767*088332b5SXin Li {"gmatch", gmatch},
1768*088332b5SXin Li {"gsub", str_gsub},
1769*088332b5SXin Li {"len", str_len},
1770*088332b5SXin Li {"lower", str_lower},
1771*088332b5SXin Li {"match", str_match},
1772*088332b5SXin Li {"rep", str_rep},
1773*088332b5SXin Li {"reverse", str_reverse},
1774*088332b5SXin Li {"sub", str_sub},
1775*088332b5SXin Li {"upper", str_upper},
1776*088332b5SXin Li {"pack", str_pack},
1777*088332b5SXin Li {"packsize", str_packsize},
1778*088332b5SXin Li {"unpack", str_unpack},
1779*088332b5SXin Li {NULL, NULL}
1780*088332b5SXin Li };
1781*088332b5SXin Li
1782*088332b5SXin Li
createmetatable(lua_State * L)1783*088332b5SXin Li static void createmetatable (lua_State *L) {
1784*088332b5SXin Li /* table to be metatable for strings */
1785*088332b5SXin Li luaL_newlibtable(L, stringmetamethods);
1786*088332b5SXin Li luaL_setfuncs(L, stringmetamethods, 0);
1787*088332b5SXin Li lua_pushliteral(L, ""); /* dummy string */
1788*088332b5SXin Li lua_pushvalue(L, -2); /* copy table */
1789*088332b5SXin Li lua_setmetatable(L, -2); /* set table as metatable for strings */
1790*088332b5SXin Li lua_pop(L, 1); /* pop dummy string */
1791*088332b5SXin Li lua_pushvalue(L, -2); /* get string library */
1792*088332b5SXin Li lua_setfield(L, -2, "__index"); /* metatable.__index = string */
1793*088332b5SXin Li lua_pop(L, 1); /* pop metatable */
1794*088332b5SXin Li }
1795*088332b5SXin Li
1796*088332b5SXin Li
1797*088332b5SXin Li /*
1798*088332b5SXin Li ** Open string library
1799*088332b5SXin Li */
luaopen_string(lua_State * L)1800*088332b5SXin Li LUAMOD_API int luaopen_string (lua_State *L) {
1801*088332b5SXin Li luaL_newlib(L, strlib);
1802*088332b5SXin Li createmetatable(L);
1803*088332b5SXin Li return 1;
1804*088332b5SXin Li }
1805*088332b5SXin Li
1806