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