Lua 5.1.4: lstrlib.c
L0001
L0006
L0007
L0008 #include <ctype.h>
L0009 #include <stddef.h>
L0010 #include <stdio.h>
L0011 #include <stdlib.h>
L0012 #include <string.h>
L0013
L0014 #define lstrlib_c
L0015 #define LUA_LIB
L0016
L0017 #include "lua.h"
L0018
L0019 #include "lauxlib.h"
L0020 #include "lualib.h"
L0021
L0022
L0023
L0024 #define uchar(c) ((unsigned char)(c))
L0025
L0026
L0027
L0028 static int str_len (lua_State *L) {
L0029 size_t l;
L0030 luaL_checklstring(L, 1, &l);
L0031 lua_pushinteger(L, l);
L0032 return 1;
L0033 }
L0034
L0035
L0036 static ptrdiff_t posrelat (ptrdiff_t pos, size_t len) {
L0037
L0038 if (pos < 0) pos += (ptrdiff_t)len + 1;
L0039 return (pos >= 0) ? pos : 0;
L0040 }
L0041
L0042
L0043 static int str_sub (lua_State *L) {
L0044 size_t l;
L0045 const char *s = luaL_checklstring(L, 1, &l);
L0046 ptrdiff_t start = posrelat(luaL_checkinteger(L, 2), l);
L0047 ptrdiff_t end = posrelat(luaL_optinteger(L, 3, -1), l);
L0048 if (start < 1) start = 1;
L0049 if (end > (ptrdiff_t)l) end = (ptrdiff_t)l;
L0050 if (start <= end)
L0051 lua_pushlstring(L, s+start-1, end-start+1);
L0052 else lua_pushliteral(L, "");
L0053 return 1;
L0054 }
L0055
L0056
L0057 static int str_reverse (lua_State *L) {
L0058 size_t l;
L0059 luaL_Buffer b;
L0060 const char *s = luaL_checklstring(L, 1, &l);
L0061 luaL_buffinit(L, &b);
L0062 while (l--) luaL_addchar(&b, s[l]);
L0063 luaL_pushresult(&b);
L0064 return 1;
L0065 }
L0066
L0067
L0068 static int str_lower (lua_State *L) {
L0069 size_t l;
L0070 size_t i;
L0071 luaL_Buffer b;
L0072 const char *s = luaL_checklstring(L, 1, &l);
L0073 luaL_buffinit(L, &b);
L0074 for (i=0; i<l; i++)
L0075 luaL_addchar(&b, tolower(uchar(s[i])));
L0076 luaL_pushresult(&b);
L0077 return 1;
L0078 }
L0079
L0080
L0081 static int str_upper (lua_State *L) {
L0082 size_t l;
L0083 size_t i;
L0084 luaL_Buffer b;
L0085 const char *s = luaL_checklstring(L, 1, &l);
L0086 luaL_buffinit(L, &b);
L0087 for (i=0; i<l; i++)
L0088 luaL_addchar(&b, toupper(uchar(s[i])));
L0089 luaL_pushresult(&b);
L0090 return 1;
L0091 }
L0092
L0093 static int str_rep (lua_State *L) {
L0094 size_t l;
L0095 luaL_Buffer b;
L0096 const char *s = luaL_checklstring(L, 1, &l);
L0097 int n = luaL_checkint(L, 2);
L0098 luaL_buffinit(L, &b);
L0099 while (n-- > 0)
L0100 luaL_addlstring(&b, s, l);
L0101 luaL_pushresult(&b);
L0102 return 1;
L0103 }
L0104
L0105
L0106 static int str_byte (lua_State *L) {
L0107 size_t l;
L0108 const char *s = luaL_checklstring(L, 1, &l);
L0109 ptrdiff_t posi = posrelat(luaL_optinteger(L, 2, 1), l);
L0110 ptrdiff_t pose = posrelat(luaL_optinteger(L, 3, posi), l);
L0111 int n, i;
L0112 if (posi <= 0) posi = 1;
L0113 if ((size_t)pose > l) pose = l;
L0114 if (posi > pose) return 0;
L0115 n = (int)(pose - posi + 1);
L0116 if (posi + n <= pose)
L0117 luaL_error(L, "string slice too long");
L0118 luaL_checkstack(L, n, "string slice too long");
L0119 for (i=0; i<n; i++)
L0120 lua_pushinteger(L, uchar(s[posi+i-1]));
L0121 return n;
L0122 }
L0123
L0124
L0125 static int str_char (lua_State *L) {
L0126 int n = lua_gettop(L);
L0127 int i;
L0128 luaL_Buffer b;
L0129 luaL_buffinit(L, &b);
L0130 for (i=1; i<=n; i++) {
L0131 int c = luaL_checkint(L, i);
L0132 luaL_argcheck(L, uchar(c) == c, i, "invalid value");
L0133 luaL_addchar(&b, uchar(c));
L0134 }
L0135 luaL_pushresult(&b);
L0136 return 1;
L0137 }
L0138
L0139
L0140 static int writer (lua_State *L, const void* b, size_t size, void* B) {
L0141 (void)L;
L0142 luaL_addlstring((luaL_Buffer*) B, (const char *)b, size);
L0143 return 0;
L0144 }
L0145
L0146
L0147 static int str_dump (lua_State *L) {
L0148 luaL_Buffer b;
L0149 luaL_checktype(L, 1, LUA_TFUNCTION);
L0150 lua_settop(L, 1);
L0151 luaL_buffinit(L,&b);
L0152 if (lua_dump(L, writer, &b) != 0)
L0153 luaL_error(L, "unable to dump given function");
L0154 luaL_pushresult(&b);
L0155 return 1;
L0156 }
L0157
L0158
L0159
L0160
L0165
L0166
L0167 #define CAP_UNFINISHED (-1)
L0168 #define CAP_POSITION (-2)
L0169
L0170 typedef struct MatchState {
L0171 const char *src_init;
L0172 const char *src_end;
L0173 lua_State *L;
L0174 int level;
L0175 struct {
L0176 const char *init;
L0177 ptrdiff_t len;
L0178 } capture[LUA_MAXCAPTURES];
L0179 } MatchState;
L0180
L0181
L0182 #define L_ESC '%'
L0183 #define SPECIALS "^$*+?.([%-"
L0184
L0185
L0186 static int check_capture (MatchState *ms, int l) {
L0187 l -= '1';
L0188 if (l < 0 || l >= ms->level || ms->capture[l].len == CAP_UNFINISHED)
L0189 return luaL_error(ms->L, "invalid capture index");
L0190 return l;
L0191 }
L0192
L0193
L0194 static int capture_to_close (MatchState *ms) {
L0195 int level = ms->level;
L0196 for (level--; level>=0; level--)
L0197 if (ms->capture[level].len == CAP_UNFINISHED) return level;
L0198 return luaL_error(ms->L, "invalid pattern capture");
L0199 }
L0200
L0201
L0202 static const char *classend (MatchState *ms, const char *p) {
L0203 switch (*p++) {
L0204 case L_ESC: {
L0205 if (*p == '\0')
L0206 luaL_error(ms->L, "malformed pattern (ends with " LUA_QL("%%") ")");
L0207 return p+1;
L0208 }
L0209 case '[': {
L0210 if (*p == '^') p++;
L0211 do {
L0212 if (*p == '\0')
L0213 luaL_error(ms->L, "malformed pattern (missing " LUA_QL("]") ")");
L0214 if (*(p++) == L_ESC && *p != '\0')
L0215 p++;
L0216 } while (*p != ']');
L0217 return p+1;
L0218 }
L0219 default: {
L0220 return p;
L0221 }
L0222 }
L0223 }
L0224
L0225
L0226 static int match_class (int c, int cl) {
L0227 int res;
L0228 switch (tolower(cl)) {
L0229 case 'a' : res = isalpha(c); break;
L0230 case 'c' : res = iscntrl(c); break;
L0231 case 'd' : res = isdigit(c); break;
L0232 case 'l' : res = islower(c); break;
L0233 case 'p' : res = ispunct(c); break;
L0234 case 's' : res = isspace(c); break;
L0235 case 'u' : res = isupper(c); break;
L0236 case 'w' : res = isalnum(c); break;
L0237 case 'x' : res = isxdigit(c); break;
L0238 case 'z' : res = (c == 0); break;
L0239 default: return (cl == c);
L0240 }
L0241 return (islower(cl) ? res : !res);
L0242 }
L0243
L0244
L0245 static int matchbracketclass (int c, const char *p, const char *ec) {
L0246 int sig = 1;
L0247 if (*(p+1) == '^') {
L0248 sig = 0;
L0249 p++;
L0250 }
L0251 while (++p < ec) {
L0252 if (*p == L_ESC) {
L0253 p++;
L0254 if (match_class(c, uchar(*p)))
L0255 return sig;
L0256 }
L0257 else if ((*(p+1) == '-') && (p+2 < ec)) {
L0258 p+=2;
L0259 if (uchar(*(p-2)) <= c && c <= uchar(*p))
L0260 return sig;
L0261 }
L0262 else if (uchar(*p) == c) return sig;
L0263 }
L0264 return !sig;
L0265 }
L0266
L0267
L0268 static int singlematch (int c, const char *p, const char *ep) {
L0269 switch (*p) {
L0270 case '.': return 1;
L0271 case L_ESC: return match_class(c, uchar(*(p+1)));
L0272 case '[': return matchbracketclass(c, p, ep-1);
L0273 default: return (uchar(*p) == c);
L0274 }
L0275 }
L0276
L0277
L0278 static const char *match (MatchState *ms, const char *s, const char *p);
L0279
L0280
L0281 static const char *matchbalance (MatchState *ms, const char *s,
L0282 const char *p) {
L0283 if (*p == 0 || *(p+1) == 0)
L0284 luaL_error(ms->L, "unbalanced pattern");
L0285 if (*s != *p) return NULL;
L0286 else {
L0287 int b = *p;
L0288 int e = *(p+1);
L0289 int cont = 1;
L0290 while (++s < ms->src_end) {
L0291 if (*s == e) {
L0292 if (--cont == 0) return s+1;
L0293 }
L0294 else if (*s == b) cont++;
L0295 }
L0296 }
L0297 return NULL;
L0298 }
L0299
L0300
L0301 static const char *max_expand (MatchState *ms, const char *s,
L0302 const char *p, const char *ep) {
L0303 ptrdiff_t i = 0;
L0304 while ((s+i)<ms->src_end && singlematch(uchar(*(s+i)), p, ep))
L0305 i++;
L0306
L0307 while (i>=0) {
L0308 const char *res = match(ms, (s+i), ep+1);
L0309 if (res) return res;
L0310 i--;
L0311 }
L0312 return NULL;
L0313 }
L0314
L0315
L0316 static const char *min_expand (MatchState *ms, const char *s,
L0317 const char *p, const char *ep) {
L0318 for (;;) {
L0319 const char *res = match(ms, s, ep+1);
L0320 if (res != NULL)
L0321 return res;
L0322 else if (s<ms->src_end && singlematch(uchar(*s), p, ep))
L0323 s++;
L0324 else return NULL;
L0325 }
L0326 }
L0327
L0328
L0329 static const char *start_capture (MatchState *ms, const char *s,
L0330 const char *p, int what) {
L0331 const char *res;
L0332 int level = ms->level;
L0333 if (level >= LUA_MAXCAPTURES) luaL_error(ms->L, "too many captures");
L0334 ms->capture[level].init = s;
L0335 ms->capture[level].len = what;
L0336 ms->level = level+1;
L0337 if ((res=match(ms, s, p)) == NULL)
L0338 ms->level--;
L0339 return res;
L0340 }
L0341
L0342
L0343 static const char *end_capture (MatchState *ms, const char *s,
L0344 const char *p) {
L0345 int l = capture_to_close(ms);
L0346 const char *res;
L0347 ms->capture[l].len = s - ms->capture[l].init;
L0348 if ((res = match(ms, s, p)) == NULL)
L0349 ms->capture[l].len = CAP_UNFINISHED;
L0350 return res;
L0351 }
L0352
L0353
L0354 static const char *match_capture (MatchState *ms, const char *s, int l) {
L0355 size_t len;
L0356 l = check_capture(ms, l);
L0357 len = ms->capture[l].len;
L0358 if ((size_t)(ms->src_end-s) >= len &&
L0359 memcmp(ms->capture[l].init, s, len) == 0)
L0360 return s+len;
L0361 else return NULL;
L0362 }
L0363
L0364
L0365 static const char *match (MatchState *ms, const char *s, const char *p) {
L0366 init:
L0367 switch (*p) {
L0368 case '(': {
L0369 if (*(p+1) == ')')
L0370 return start_capture(ms, s, p+2, CAP_POSITION);
L0371 else
L0372 return start_capture(ms, s, p+1, CAP_UNFINISHED);
L0373 }
L0374 case ')': {
L0375 return end_capture(ms, s, p+1);
L0376 }
L0377 case L_ESC: {
L0378 switch (*(p+1)) {
L0379 case 'b': {
L0380 s = matchbalance(ms, s, p+2);
L0381 if (s == NULL) return NULL;
L0382 p+=4; goto init;
L0383 }
L0384 case 'f': {
L0385 const char *ep; char previous;
L0386 p += 2;
L0387 if (*p != '[')
L0388 luaL_error(ms->L, "missing " LUA_QL("[") " after "
L0389 LUA_QL("%%f") " in pattern");
L0390 ep = classend(ms, p);
L0391 previous = (s == ms->src_init) ? '\0' : *(s-1);
L0392 if (matchbracketclass(uchar(previous), p, ep-1) ||
L0393 !matchbracketclass(uchar(*s), p, ep-1)) return NULL;
L0394 p=ep; goto init;
L0395 }
L0396 default: {
L0397 if (isdigit(uchar(*(p+1)))) {
L0398 s = match_capture(ms, s, uchar(*(p+1)));
L0399 if (s == NULL) return NULL;
L0400 p+=2; goto init;
L0401 }
L0402 goto dflt;
L0403 }
L0404 }
L0405 }
L0406 case '\0': {
L0407 return s;
L0408 }
L0409 case '$': {
L0410 if (*(p+1) == '\0')
L0411 return (s == ms->src_end) ? s : NULL;
L0412 else goto dflt;
L0413 }
L0414 default: dflt: {
L0415 const char *ep = classend(ms, p);
L0416 int m = s<ms->src_end && singlematch(uchar(*s), p, ep);
L0417 switch (*ep) {
L0418 case '?': {
L0419 const char *res;
L0420 if (m && ((res=match(ms, s+1, ep+1)) != NULL))
L0421 return res;
L0422 p=ep+1; goto init;
L0423 }
L0424 case '*': {
L0425 return max_expand(ms, s, p, ep);
L0426 }
L0427 case '+': {
L0428 return (m ? max_expand(ms, s+1, p, ep) : NULL);
L0429 }
L0430 case '-': {
L0431 return min_expand(ms, s, p, ep);
L0432 }
L0433 default: {
L0434 if (!m) return NULL;
L0435 s++; p=ep; goto init;
L0436 }
L0437 }
L0438 }
L0439 }
L0440 }
L0441
L0442
L0443
L0444 static const char *lmemfind (const char *s1, size_t l1,
L0445 const char *s2, size_t l2) {
L0446 if (l2 == 0) return s1;
L0447 else if (l2 > l1) return NULL;
L0448 else {
L0449 const char *init;
L0450 l2--;
L0451 l1 = l1-l2;
L0452 while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) {
L0453 init++;
L0454 if (memcmp(init, s2+1, l2) == 0)
L0455 return init-1;
L0456 else {
L0457 l1 -= init-s1;
L0458 s1 = init;
L0459 }
L0460 }
L0461 return NULL;
L0462 }
L0463 }
L0464
L0465
L0466 static void push_onecapture (MatchState *ms, int i, const char *s,
L0467 const char *e) {
L0468 if (i >= ms->level) {
L0469 if (i == 0)
L0470 lua_pushlstring(ms->L, s, e - s);
L0471 else
L0472 luaL_error(ms->L, "invalid capture index");
L0473 }
L0474 else {
L0475 ptrdiff_t l = ms->capture[i].len;
L0476 if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture");
L0477 if (l == CAP_POSITION)
L0478 lua_pushinteger(ms->L, ms->capture[i].init - ms->src_init + 1);
L0479 else
L0480 lua_pushlstring(ms->L, ms->capture[i].init, l);
L0481 }
L0482 }
L0483
L0484
L0485 static int push_captures (MatchState *ms, const char *s, const char *e) {
L0486 int i;
L0487 int nlevels = (ms->level == 0 && s) ? 1 : ms->level;
L0488 luaL_checkstack(ms->L, nlevels, "too many captures");
L0489 for (i = 0; i < nlevels; i++)
L0490 push_onecapture(ms, i, s, e);
L0491 return nlevels;
L0492 }
L0493
L0494
L0495 static int str_find_aux (lua_State *L, int find) {
L0496 size_t l1, l2;
L0497 const char *s = luaL_checklstring(L, 1, &l1);
L0498 const char *p = luaL_checklstring(L, 2, &l2);
L0499 ptrdiff_t init = posrelat(luaL_optinteger(L, 3, 1), l1) - 1;
L0500 if (init < 0) init = 0;
L0501 else if ((size_t)(init) > l1) init = (ptrdiff_t)l1;
L0502 if (find && (lua_toboolean(L, 4) ||
L0503 strpbrk(p, SPECIALS) == NULL)) {
L0504
L0505 const char *s2 = lmemfind(s+init, l1-init, p, l2);
L0506 if (s2) {
L0507 lua_pushinteger(L, s2-s+1);
L0508 lua_pushinteger(L, s2-s+l2);
L0509 return 2;
L0510 }
L0511 }
L0512 else {
L0513 MatchState ms;
L0514 int anchor = (*p == '^') ? (p++, 1) : 0;
L0515 const char *s1=s+init;
L0516 ms.L = L;
L0517 ms.src_init = s;
L0518 ms.src_end = s+l1;
L0519 do {
L0520 const char *res;
L0521 ms.level = 0;
L0522 if ((res=match(&ms, s1, p)) != NULL) {
L0523 if (find) {
L0524 lua_pushinteger(L, s1-s+1);
L0525 lua_pushinteger(L, res-s);
L0526 return push_captures(&ms, NULL, 0) + 2;
L0527 }
L0528 else
L0529 return push_captures(&ms, s1, res);
L0530 }
L0531 } while (s1++ < ms.src_end && !anchor);
L0532 }
L0533 lua_pushnil(L);
L0534 return 1;
L0535 }
L0536
L0537
L0538 static int str_find (lua_State *L) {
L0539 return str_find_aux(L, 1);
L0540 }
L0541
L0542
L0543 static int str_match (lua_State *L) {
L0544 return str_find_aux(L, 0);
L0545 }
L0546
L0547
L0548 static int gmatch_aux (lua_State *L) {
L0549 MatchState ms;
L0550 size_t ls;
L0551 const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls);
L0552 const char *p = lua_tostring(L, lua_upvalueindex(2));
L0553 const char *src;
L0554 ms.L = L;
L0555 ms.src_init = s;
L0556 ms.src_end = s+ls;
L0557 for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3));
L0558 src <= ms.src_end;
L0559 src++) {
L0560 const char *e;
L0561 ms.level = 0;
L0562 if ((e = match(&ms, src, p)) != NULL) {
L0563 lua_Integer newstart = e-s;
L0564 if (e == src) newstart++;
L0565 lua_pushinteger(L, newstart);
L0566 lua_replace(L, lua_upvalueindex(3));
L0567 return push_captures(&ms, src, e);
L0568 }
L0569 }
L0570 return 0;
L0571 }
L0572
L0573
L0574 static int gmatch (lua_State *L) {
L0575 luaL_checkstring(L, 1);
L0576 luaL_checkstring(L, 2);
L0577 lua_settop(L, 2);
L0578 lua_pushinteger(L, 0);
L0579 lua_pushcclosure(L, gmatch_aux, 3);
L0580 return 1;
L0581 }
L0582
L0583
L0584 static int gfind_nodef (lua_State *L) {
L0585 return luaL_error(L, LUA_QL("string.gfind") " was renamed to "
L0586 LUA_QL("string.gmatch"));
L0587 }
L0588
L0589
L0590 static void add_s (MatchState *ms, luaL_Buffer *b, const char *s,
L0591 const char *e) {
L0592 size_t l, i;
L0593 const char *news = lua_tolstring(ms->L, 3, &l);
L0594 for (i = 0; i < l; i++) {
L0595 if (news[i] != L_ESC)
L0596 luaL_addchar(b, news[i]);
L0597 else {
L0598 i++;
L0599 if (!isdigit(uchar(news[i])))
L0600 luaL_addchar(b, news[i]);
L0601 else if (news[i] == '0')
L0602 luaL_addlstring(b, s, e - s);
L0603 else {
L0604 push_onecapture(ms, news[i] - '1', s, e);
L0605 luaL_addvalue(b);
L0606 }
L0607 }
L0608 }
L0609 }
L0610
L0611
L0612 static void add_value (MatchState *ms, luaL_Buffer *b, const char *s,
L0613 const char *e) {
L0614 lua_State *L = ms->L;
L0615 switch (lua_type(L, 3)) {
L0616 case LUA_TNUMBER:
L0617 case LUA_TSTRING: {
L0618 add_s(ms, b, s, e);
L0619 return;
L0620 }
L0621 case LUA_TFUNCTION: {
L0622 int n;
L0623 lua_pushvalue(L, 3);
L0624 n = push_captures(ms, s, e);
L0625 lua_call(L, n, 1);
L0626 break;
L0627 }
L0628 case LUA_TTABLE: {
L0629 push_onecapture(ms, 0, s, e);
L0630 lua_gettable(L, 3);
L0631 break;
L0632 }
L0633 }
L0634 if (!lua_toboolean(L, -1)) {
L0635 lua_pop(L, 1);
L0636 lua_pushlstring(L, s, e - s);
L0637 }
L0638 else if (!lua_isstring(L, -1))
L0639 luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1));
L0640 luaL_addvalue(b);
L0641 }
L0642
L0643
L0644 static int str_gsub (lua_State *L) {
L0645 size_t srcl;
L0646 const char *src = luaL_checklstring(L, 1, &srcl);
L0647 const char *p = luaL_checkstring(L, 2);
L0648 int tr = lua_type(L, 3);
L0649 int max_s = luaL_optint(L, 4, srcl+1);
L0650 int anchor = (*p == '^') ? (p++, 1) : 0;
L0651 int n = 0;
L0652 MatchState ms;
L0653 luaL_Buffer b;
L0654 luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING ||
L0655 tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3,
L0656 "string/function/table expected");
L0657 luaL_buffinit(L, &b);
L0658 ms.L = L;
L0659 ms.src_init = src;
L0660 ms.src_end = src+srcl;
L0661 while (n < max_s) {
L0662 const char *e;
L0663 ms.level = 0;
L0664 e = match(&ms, src, p);
L0665 if (e) {
L0666 n++;
L0667 add_value(&ms, &b, src, e);
L0668 }
L0669 if (e && e>src)
L0670 src = e;
L0671 else if (src < ms.src_end)
L0672 luaL_addchar(&b, *src++);
L0673 else break;
L0674 if (anchor) break;
L0675 }
L0676 luaL_addlstring(&b, src, ms.src_end-src);
L0677 luaL_pushresult(&b);
L0678 lua_pushinteger(L, n);
L0679 return 2;
L0680 }
L0681
L0682
L0683
L0684
L0685
L0686 #define MAX_ITEM 512
L0687
L0688 #define FLAGS "-+ #0"
L0689
L0693 #define MAX_FORMAT (sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10)
L0694
L0695
L0696 static void addquoted (lua_State *L, luaL_Buffer *b, int arg) {
L0697 size_t l;
L0698 const char *s = luaL_checklstring(L, arg, &l);
L0699 luaL_addchar(b, '"');
L0700 while (l--) {
L0701 switch (*s) {
L0702 case '"': case '\\': case '\n': {
L0703 luaL_addchar(b, '\\');
L0704 luaL_addchar(b, *s);
L0705 break;
L0706 }
L0707 case '\r': {
L0708 luaL_addlstring(b, "\\r", 2);
L0709 break;
L0710 }
L0711 case '\0': {
L0712 luaL_addlstring(b, "\\000", 4);
L0713 break;
L0714 }
L0715 default: {
L0716 luaL_addchar(b, *s);
L0717 break;
L0718 }
L0719 }
L0720 s++;
L0721 }
L0722 luaL_addchar(b, '"');
L0723 }
L0724
L0725 static const char *scanformat (lua_State *L, const char *strfrmt, char *form) {
L0726 const char *p = strfrmt;
L0727 while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++;
L0728 if ((size_t)(p - strfrmt) >= sizeof(FLAGS))
L0729 luaL_error(L, "invalid format (repeated flags)");
L0730 if (isdigit(uchar(*p))) p++;
L0731 if (isdigit(uchar(*p))) p++;
L0732 if (*p == '.') {
L0733 p++;
L0734 if (isdigit(uchar(*p))) p++;
L0735 if (isdigit(uchar(*p))) p++;
L0736 }
L0737 if (isdigit(uchar(*p)))
L0738 luaL_error(L, "invalid format (width or precision too long)");
L0739 *(form++) = '%';
L0740 strncpy(form, strfrmt, p - strfrmt + 1);
L0741 form += p - strfrmt + 1;
L0742 *form = '\0';
L0743 return p;
L0744 }
L0745
L0746
L0747 static void addintlen (char *form) {
L0748 size_t l = strlen(form);
L0749 char spec = form[l - 1];
L0750 strcpy(form + l - 1, LUA_INTFRMLEN);
L0751 form[l + sizeof(LUA_INTFRMLEN) - 2] = spec;
L0752 form[l + sizeof(LUA_INTFRMLEN) - 1] = '\0';
L0753 }
L0754
L0755
L0756 static int str_format (lua_State *L) {
L0757 int arg = 1;
L0758 size_t sfl;
L0759 const char *strfrmt = luaL_checklstring(L, arg, &sfl);
L0760 const char *strfrmt_end = strfrmt+sfl;
L0761 luaL_Buffer b;
L0762 luaL_buffinit(L, &b);
L0763 while (strfrmt < strfrmt_end) {
L0764 if (*strfrmt != L_ESC)
L0765 luaL_addchar(&b, *strfrmt++);
L0766 else if (*++strfrmt == L_ESC)
L0767 luaL_addchar(&b, *strfrmt++);
L0768 else {
L0769 char form[MAX_FORMAT];
L0770 char buff[MAX_ITEM];
L0771 arg++;
L0772 strfrmt = scanformat(L, strfrmt, form);
L0773 switch (*strfrmt++) {
L0774 case 'c': {
L0775 sprintf(buff, form, (int)luaL_checknumber(L, arg));
L0776 break;
L0777 }
L0778 case 'd': case 'i': {
L0779 addintlen(form);
L0780 sprintf(buff, form, (LUA_INTFRM_T)luaL_checknumber(L, arg));
L0781 break;
L0782 }
L0783 case 'o': case 'u': case 'x': case 'X': {
L0784 addintlen(form);
L0785 sprintf(buff, form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg));
L0786 break;
L0787 }
L0788 case 'e': case 'E': case 'f':
L0789 case 'g': case 'G': {
L0790 sprintf(buff, form, (double)luaL_checknumber(L, arg));
L0791 break;
L0792 }
L0793 case 'q': {
L0794 addquoted(L, &b, arg);
L0795 continue;
L0796 }
L0797 case 's': {
L0798 size_t l;
L0799 const char *s = luaL_checklstring(L, arg, &l);
L0800 if (!strchr(form, '.') && l >= 100) {
L0801
L0803 lua_pushvalue(L, arg);
L0804 luaL_addvalue(&b);
L0805 continue;
L0806 }
L0807 else {
L0808 sprintf(buff, form, s);
L0809 break;
L0810 }
L0811 }
L0812 default: {
L0813 return luaL_error(L, "invalid option " LUA_QL("%%%c") " to "
L0814 LUA_QL("format"), *(strfrmt - 1));
L0815 }
L0816 }
L0817 luaL_addlstring(&b, buff, strlen(buff));
L0818 }
L0819 }
L0820 luaL_pushresult(&b);
L0821 return 1;
L0822 }
L0823
L0824
L0825 static const luaL_Reg strlib[] = {
L0826 {"byte", str_byte},
L0827 {"char", str_char},
L0828 {"dump", str_dump},
L0829 {"find", str_find},
L0830 {"format", str_format},
L0831 {"gfind", gfind_nodef},
L0832 {"gmatch", gmatch},
L0833 {"gsub", str_gsub},
L0834 {"len", str_len},
L0835 {"lower", str_lower},
L0836 {"match", str_match},
L0837 {"rep", str_rep},
L0838 {"reverse", str_reverse},
L0839 {"sub", str_sub},
L0840 {"upper", str_upper},
L0841 {NULL, NULL}
L0842 };
L0843
L0844
L0845 static void createmetatable (lua_State *L) {
L0846 lua_createtable(L, 0, 1);
L0847 lua_pushliteral(L, "");
L0848 lua_pushvalue(L, -2);
L0849 lua_setmetatable(L, -2);
L0850 lua_pop(L, 1);
L0851 lua_pushvalue(L, -2);
L0852 lua_setfield(L, -2, "__index");
L0853 lua_pop(L, 1);
L0854 }
L0855
L0856
L0857
L0860 LUALIB_API int luaopen_string (lua_State *L) {
L0861 luaL_register(L, LUA_STRLIBNAME, strlib);
L0862 #if defined(LUA_COMPAT_GFIND)
L0863 lua_getfield(L, -1, "gmatch");
L0864 lua_setfield(L, -2, "gfind");
L0865 #endif
L0866 createmetatable(L);
L0867 return 1;
L0868 }
L0869
Generated by pretty.lua