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