1 /* 2 ** $Id: lstrlib.c,v 1.178.1.1 2013/04/12 18:48:47 roberto Exp $ 3 ** Standard library for string operations and pattern-matching 4 ** See Copyright Notice in lua.h 5 */ 6 7 8 #include <sys/ctype.h> 9 #include <sys/zfs_context.h> 10 11 #define lstrlib_c 12 #define LUA_LIB 13 14 #include "lua.h" 15 16 #include "lauxlib.h" 17 #include "lualib.h" 18 19 20 /* 21 ** maximum number of captures that a pattern can do during 22 ** pattern-matching. This limit is arbitrary. 23 */ 24 #if !defined(LUA_MAXCAPTURES) 25 #define LUA_MAXCAPTURES 32 26 #endif 27 28 29 /* macro to `unsign' a character */ 30 #define uchar(c) ((unsigned char)(c)) 31 32 /* 33 * PATCHED: add missing character macros. 34 */ 35 #define tolower(C) (((C) >= 'A' && (C) <= 'Z') ? (C) - 'A' + 'a' : (C)) 36 #define toupper(C) (((C) >= 'a' && (C) <= 'z') ? (C) - 'a' + 'A': (C)) 37 #define iscntrl(C) ((((C) >= 0) && ((C) <= 0x1f)) || ((C) == 0x7f)) 38 #define isgraph(C) ((C) >= 0x21 && (C) <= 0x7E) 39 #define ispunct(C) (((C) >= 0x21 && (C) <= 0x2F) || \ 40 ((C) >= 0x3A && (C) <= 0x40) || \ 41 ((C) >= 0x5B && (C) <= 0x60) || \ 42 ((C) >= 0x7B && (C) <= 0x7E)) 43 44 /* 45 * The provided version of sprintf returns a char *, but str_format expects 46 * it to return the number of characters printed. This version has the expected 47 * behavior. 48 */ 49 static size_t str_sprintf(char *buf, const char *fmt, ...) { 50 va_list args; 51 size_t len; 52 53 va_start(args, fmt); 54 len = vsnprintf(buf, INT_MAX, fmt, args); 55 va_end(args); 56 57 return len; 58 } 59 60 61 static int str_len (lua_State *L) { 62 size_t l; 63 luaL_checklstring(L, 1, &l); 64 lua_pushinteger(L, (lua_Integer)l); 65 return 1; 66 } 67 68 69 /* translate a relative string position: negative means back from end */ 70 static size_t posrelat (ptrdiff_t pos, size_t len) { 71 if (pos >= 0) return (size_t)pos; 72 else if (0u - (size_t)pos > len) return 0; 73 else return len - ((size_t)-pos) + 1; 74 } 75 76 77 static int str_sub (lua_State *L) { 78 size_t l; 79 const char *s = luaL_checklstring(L, 1, &l); 80 size_t start = posrelat(luaL_checkinteger(L, 2), l); 81 size_t end = posrelat(luaL_optinteger(L, 3, -1), l); 82 if (start < 1) start = 1; 83 if (end > l) end = l; 84 if (start <= end) 85 lua_pushlstring(L, s + start - 1, end - start + 1); 86 else lua_pushliteral(L, ""); 87 return 1; 88 } 89 90 91 static int str_reverse (lua_State *L) { 92 size_t l, i; 93 luaL_Buffer b; 94 const char *s = luaL_checklstring(L, 1, &l); 95 char *p = luaL_buffinitsize(L, &b, l); 96 for (i = 0; i < l; i++) 97 p[i] = s[l - i - 1]; 98 luaL_pushresultsize(&b, l); 99 return 1; 100 } 101 102 103 static int str_lower (lua_State *L) { 104 size_t l; 105 size_t i; 106 luaL_Buffer b; 107 const char *s = luaL_checklstring(L, 1, &l); 108 char *p = luaL_buffinitsize(L, &b, l); 109 for (i=0; i<l; i++) 110 p[i] = tolower(uchar(s[i])); 111 luaL_pushresultsize(&b, l); 112 return 1; 113 } 114 115 116 static int str_upper (lua_State *L) { 117 size_t l; 118 size_t i; 119 luaL_Buffer b; 120 const char *s = luaL_checklstring(L, 1, &l); 121 char *p = luaL_buffinitsize(L, &b, l); 122 for (i=0; i<l; i++) 123 p[i] = toupper(uchar(s[i])); 124 luaL_pushresultsize(&b, l); 125 return 1; 126 } 127 128 129 /* reasonable limit to avoid arithmetic overflow */ 130 #define MAXSIZE ((~(size_t)0) >> 1) 131 132 static int str_rep (lua_State *L) { 133 size_t l, lsep; 134 const char *s = luaL_checklstring(L, 1, &l); 135 int n = luaL_checkint(L, 2); 136 const char *sep = luaL_optlstring(L, 3, "", &lsep); 137 if (n <= 0) lua_pushliteral(L, ""); 138 else if (l + lsep < l || l + lsep >= MAXSIZE / n) /* may overflow? */ 139 return luaL_error(L, "resulting string too large"); 140 else { 141 size_t totallen = n * l + (n - 1) * lsep; 142 luaL_Buffer b; 143 char *p = luaL_buffinitsize(L, &b, totallen); 144 while (n-- > 1) { /* first n-1 copies (followed by separator) */ 145 memcpy(p, s, l * sizeof(char)); p += l; 146 if (lsep > 0) { /* avoid empty 'memcpy' (may be expensive) */ 147 memcpy(p, sep, lsep * sizeof(char)); p += lsep; 148 } 149 } 150 memcpy(p, s, l * sizeof(char)); /* last copy (not followed by separator) */ 151 luaL_pushresultsize(&b, totallen); 152 } 153 return 1; 154 } 155 156 157 static int str_byte (lua_State *L) { 158 size_t l; 159 const char *s = luaL_checklstring(L, 1, &l); 160 size_t posi = posrelat(luaL_optinteger(L, 2, 1), l); 161 size_t pose = posrelat(luaL_optinteger(L, 3, posi), l); 162 int n, i; 163 if (posi < 1) posi = 1; 164 if (pose > l) pose = l; 165 if (posi > pose) return 0; /* empty interval; return no values */ 166 n = (int)(pose - posi + 1); 167 if (posi + n <= pose) /* (size_t -> int) overflow? */ 168 return luaL_error(L, "string slice too long"); 169 luaL_checkstack(L, n, "string slice too long"); 170 for (i=0; i<n; i++) 171 lua_pushinteger(L, uchar(s[posi+i-1])); 172 return n; 173 } 174 175 176 static int str_char (lua_State *L) { 177 int n = lua_gettop(L); /* number of arguments */ 178 int i; 179 luaL_Buffer b; 180 char *p = luaL_buffinitsize(L, &b, n); 181 for (i=1; i<=n; i++) { 182 int c = luaL_checkint(L, i); 183 luaL_argcheck(L, uchar(c) == c, i, "value out of range"); 184 p[i - 1] = uchar(c); 185 } 186 luaL_pushresultsize(&b, n); 187 return 1; 188 } 189 190 191 static int writer (lua_State *L, const void* b, size_t size, void* B) { 192 (void)L; 193 luaL_addlstring((luaL_Buffer*) B, (const char *)b, size); 194 return 0; 195 } 196 197 198 static int str_dump (lua_State *L) { 199 luaL_Buffer b; 200 luaL_checktype(L, 1, LUA_TFUNCTION); 201 lua_settop(L, 1); 202 luaL_buffinit(L,&b); 203 if (lua_dump(L, writer, &b) != 0) 204 return luaL_error(L, "unable to dump given function"); 205 luaL_pushresult(&b); 206 return 1; 207 } 208 209 210 211 /* 212 ** {====================================================== 213 ** PATTERN MATCHING 214 ** ======================================================= 215 */ 216 217 218 #define CAP_UNFINISHED (-1) 219 #define CAP_POSITION (-2) 220 221 222 typedef struct MatchState { 223 int matchdepth; /* control for recursive depth (to avoid C stack overflow) */ 224 const char *src_init; /* init of source string */ 225 const char *src_end; /* end ('\0') of source string */ 226 const char *p_end; /* end ('\0') of pattern */ 227 lua_State *L; 228 int level; /* total number of captures (finished or unfinished) */ 229 struct { 230 const char *init; 231 ptrdiff_t len; 232 } capture[LUA_MAXCAPTURES]; 233 } MatchState; 234 235 236 /* recursive function */ 237 static const char *match (MatchState *ms, const char *s, const char *p); 238 239 240 /* maximum recursion depth for 'match' */ 241 #if !defined(MAXCCALLS) 242 #define MAXCCALLS 200 243 #endif 244 245 246 #define L_ESC '%' 247 #define SPECIALS "^$*+?.([%-" 248 249 250 static int check_capture (MatchState *ms, int l) { 251 l -= '1'; 252 if (l < 0 || l >= ms->level || ms->capture[l].len == CAP_UNFINISHED) 253 return luaL_error(ms->L, "invalid capture index %%%d", l + 1); 254 return l; 255 } 256 257 258 static int capture_to_close (MatchState *ms) { 259 int level = ms->level; 260 for (level--; level>=0; level--) 261 if (ms->capture[level].len == CAP_UNFINISHED) return level; 262 return luaL_error(ms->L, "invalid pattern capture"); 263 } 264 265 266 static const char *classend (MatchState *ms, const char *p) { 267 switch (*p++) { 268 case L_ESC: { 269 if (p == ms->p_end) 270 luaL_error(ms->L, "malformed pattern (ends with " LUA_QL("%%") ")"); 271 return p+1; 272 } 273 case '[': { 274 if (*p == '^') p++; 275 do { /* look for a `]' */ 276 if (p == ms->p_end) 277 luaL_error(ms->L, "malformed pattern (missing " LUA_QL("]") ")"); 278 if (*(p++) == L_ESC && p < ms->p_end) 279 p++; /* skip escapes (e.g. `%]') */ 280 } while (*p != ']'); 281 return p+1; 282 } 283 default: { 284 return p; 285 } 286 } 287 } 288 289 290 static int match_class (int c, int cl) { 291 int res; 292 switch (tolower(cl)) { 293 case 'a' : res = isalpha(c); break; 294 case 'c' : res = iscntrl(c); break; 295 case 'd' : res = isdigit(c); break; 296 case 'g' : res = isgraph(c); break; 297 case 'l' : res = islower(c); break; 298 case 'p' : res = ispunct(c); break; 299 case 's' : res = isspace(c); break; 300 case 'u' : res = isupper(c); break; 301 case 'w' : res = isalnum(c); break; 302 case 'x' : res = isxdigit(c); break; 303 case 'z' : res = (c == 0); break; /* deprecated option */ 304 default: return (cl == c); 305 } 306 return (islower(cl) ? res : !res); 307 } 308 309 310 static int matchbracketclass (int c, const char *p, const char *ec) { 311 int sig = 1; 312 if (*(p+1) == '^') { 313 sig = 0; 314 p++; /* skip the `^' */ 315 } 316 while (++p < ec) { 317 if (*p == L_ESC) { 318 p++; 319 if (match_class(c, uchar(*p))) 320 return sig; 321 } 322 else if ((*(p+1) == '-') && (p+2 < ec)) { 323 p+=2; 324 if (uchar(*(p-2)) <= c && c <= uchar(*p)) 325 return sig; 326 } 327 else if (uchar(*p) == c) return sig; 328 } 329 return !sig; 330 } 331 332 333 static int singlematch (MatchState *ms, const char *s, const char *p, 334 const char *ep) { 335 if (s >= ms->src_end) 336 return 0; 337 else { 338 int c = uchar(*s); 339 switch (*p) { 340 case '.': return 1; /* matches any char */ 341 case L_ESC: return match_class(c, uchar(*(p+1))); 342 case '[': return matchbracketclass(c, p, ep-1); 343 default: return (uchar(*p) == c); 344 } 345 } 346 } 347 348 349 static const char *matchbalance (MatchState *ms, const char *s, 350 const char *p) { 351 if (p >= ms->p_end - 1) 352 luaL_error(ms->L, "malformed pattern " 353 "(missing arguments to " LUA_QL("%%b") ")"); 354 if (*s != *p) return NULL; 355 else { 356 int b = *p; 357 int e = *(p+1); 358 int cont = 1; 359 while (++s < ms->src_end) { 360 if (*s == e) { 361 if (--cont == 0) return s+1; 362 } 363 else if (*s == b) cont++; 364 } 365 } 366 return NULL; /* string ends out of balance */ 367 } 368 369 370 static const char *max_expand (MatchState *ms, const char *s, 371 const char *p, const char *ep) { 372 ptrdiff_t i = 0; /* counts maximum expand for item */ 373 while (singlematch(ms, s + i, p, ep)) 374 i++; 375 /* keeps trying to match with the maximum repetitions */ 376 while (i>=0) { 377 const char *res = match(ms, (s+i), ep+1); 378 if (res) return res; 379 i--; /* else didn't match; reduce 1 repetition to try again */ 380 } 381 return NULL; 382 } 383 384 385 static const char *min_expand (MatchState *ms, const char *s, 386 const char *p, const char *ep) { 387 for (;;) { 388 const char *res = match(ms, s, ep+1); 389 if (res != NULL) 390 return res; 391 else if (singlematch(ms, s, p, ep)) 392 s++; /* try with one more repetition */ 393 else return NULL; 394 } 395 } 396 397 398 static const char *start_capture (MatchState *ms, const char *s, 399 const char *p, int what) { 400 const char *res; 401 int level = ms->level; 402 if (level >= LUA_MAXCAPTURES) luaL_error(ms->L, "too many captures"); 403 ms->capture[level].init = s; 404 ms->capture[level].len = what; 405 ms->level = level+1; 406 if ((res=match(ms, s, p)) == NULL) /* match failed? */ 407 ms->level--; /* undo capture */ 408 return res; 409 } 410 411 412 static const char *end_capture (MatchState *ms, const char *s, 413 const char *p) { 414 int l = capture_to_close(ms); 415 const char *res; 416 ms->capture[l].len = s - ms->capture[l].init; /* close capture */ 417 if ((res = match(ms, s, p)) == NULL) /* match failed? */ 418 ms->capture[l].len = CAP_UNFINISHED; /* undo capture */ 419 return res; 420 } 421 422 423 static const char *match_capture (MatchState *ms, const char *s, int l) { 424 size_t len; 425 l = check_capture(ms, l); 426 len = ms->capture[l].len; 427 if ((size_t)(ms->src_end-s) >= len && 428 memcmp(ms->capture[l].init, s, len) == 0) 429 return s+len; 430 else return NULL; 431 } 432 433 434 static const char *match (MatchState *ms, const char *s, const char *p) { 435 if (ms->matchdepth-- == 0) 436 luaL_error(ms->L, "pattern too complex"); 437 init: /* using goto's to optimize tail recursion */ 438 if (p != ms->p_end) { /* end of pattern? */ 439 switch (*p) { 440 case '(': { /* start capture */ 441 if (*(p + 1) == ')') /* position capture? */ 442 s = start_capture(ms, s, p + 2, CAP_POSITION); 443 else 444 s = start_capture(ms, s, p + 1, CAP_UNFINISHED); 445 break; 446 } 447 case ')': { /* end capture */ 448 s = end_capture(ms, s, p + 1); 449 break; 450 } 451 case '$': { 452 if ((p + 1) != ms->p_end) /* is the `$' the last char in pattern? */ 453 goto dflt; /* no; go to default */ 454 s = (s == ms->src_end) ? s : NULL; /* check end of string */ 455 break; 456 } 457 case L_ESC: { /* escaped sequences not in the format class[*+?-]? */ 458 switch (*(p + 1)) { 459 case 'b': { /* balanced string? */ 460 s = matchbalance(ms, s, p + 2); 461 if (s != NULL) { 462 p += 4; goto init; /* return match(ms, s, p + 4); */ 463 } /* else fail (s == NULL) */ 464 break; 465 } 466 case 'f': { /* frontier? */ 467 const char *ep; char previous; 468 p += 2; 469 if (*p != '[') 470 luaL_error(ms->L, "missing " LUA_QL("[") " after " 471 LUA_QL("%%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), p, ep - 1) && 475 matchbracketclass(uchar(*s), p, ep - 1)) { 476 p = ep; goto init; /* return match(ms, s, ep); */ 477 } 478 s = NULL; /* 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))); 485 if (s != NULL) { 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; /* fail */ 503 } 504 else { /* matched once */ 505 switch (*ep) { /* handle optional suffix */ 506 case '?': { /* optional */ 507 const char *res; 508 if ((res = match(ms, s + 1, ep + 1)) != NULL) 509 s = res; 510 else { 511 p = ep + 1; goto init; /* else return match(ms, s, ep + 1); */ 512 } 513 break; 514 } 515 case '+': /* 1 or more repetitions */ 516 s++; /* 1 match already done */ 517 /* go through */ 518 case '*': /* 0 or more repetitions */ 519 s = max_expand(ms, s, p, ep); 520 break; 521 case '-': /* 0 or more repetitions (minimum) */ 522 s = min_expand(ms, s, p, ep); 523 break; 524 default: /* no suffix */ 525 s++; p = ep; goto init; /* return match(ms, s + 1, ep); */ 526 } 527 } 528 break; 529 } 530 } 531 } 532 ms->matchdepth++; 533 return s; 534 } 535 536 537 538 static const char *lmemfind (const char *s1, size_t l1, 539 const char *s2, size_t l2) { 540 if (l2 == 0) return s1; /* empty strings are everywhere */ 541 else if (l2 > l1) return NULL; /* avoids a negative `l1' */ 542 else { 543 const char *init; /* to search for a `*s2' inside `s1' */ 544 l2--; /* 1st char will be checked by `memchr' */ 545 l1 = l1-l2; /* `s2' cannot be found after that */ 546 while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) { 547 init++; /* 1st char is already checked */ 548 if (memcmp(init, s2+1, l2) == 0) 549 return init-1; 550 else { /* correct `l1' and `s1' to try again */ 551 l1 -= init-s1; 552 s1 = init; 553 } 554 } 555 return NULL; /* not found */ 556 } 557 } 558 559 560 static void push_onecapture (MatchState *ms, int i, const char *s, 561 const char *e) { 562 if (i >= ms->level) { 563 if (i == 0) /* ms->level == 0, too */ 564 lua_pushlstring(ms->L, s, e - s); /* add whole match */ 565 else 566 luaL_error(ms->L, "invalid capture index"); 567 } 568 else { 569 ptrdiff_t l = ms->capture[i].len; 570 if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture"); 571 if (l == CAP_POSITION) 572 lua_pushinteger(ms->L, ms->capture[i].init - ms->src_init + 1); 573 else 574 lua_pushlstring(ms->L, ms->capture[i].init, l); 575 } 576 } 577 578 579 static int push_captures (MatchState *ms, const char *s, const char *e) { 580 int i; 581 int nlevels = (ms->level == 0 && s) ? 1 : ms->level; 582 luaL_checkstack(ms->L, nlevels, "too many captures"); 583 for (i = 0; i < nlevels; i++) 584 push_onecapture(ms, i, s, e); 585 return nlevels; /* number of strings pushed */ 586 } 587 588 589 /* check whether pattern has no special characters */ 590 static int nospecials (const char *p, size_t l) { 591 size_t upto = 0; 592 do { 593 if (strpbrk(p + upto, SPECIALS)) 594 return 0; /* pattern has a special character */ 595 upto += strlen(p + upto) + 1; /* may have more after \0 */ 596 } while (upto <= l); 597 return 1; /* no special chars found */ 598 } 599 600 601 static int str_find_aux (lua_State *L, int find) { 602 size_t ls, lp; 603 const char *s = luaL_checklstring(L, 1, &ls); 604 const char *p = luaL_checklstring(L, 2, &lp); 605 size_t init = posrelat(luaL_optinteger(L, 3, 1), ls); 606 if (init < 1) init = 1; 607 else if (init > ls + 1) { /* start after string's end? */ 608 lua_pushnil(L); /* cannot find anything */ 609 return 1; 610 } 611 /* explicit request or no special characters? */ 612 if (find && (lua_toboolean(L, 4) || nospecials(p, lp))) { 613 /* do a plain search */ 614 const char *s2 = lmemfind(s + init - 1, ls - init + 1, p, lp); 615 if (s2) { 616 lua_pushinteger(L, s2 - s + 1); 617 lua_pushinteger(L, s2 - s + lp); 618 return 2; 619 } 620 } 621 else { 622 MatchState ms; 623 const char *s1 = s + init - 1; 624 int anchor = (*p == '^'); 625 if (anchor) { 626 p++; lp--; /* skip anchor character */ 627 } 628 ms.L = L; 629 ms.matchdepth = MAXCCALLS; 630 ms.src_init = s; 631 ms.src_end = s + ls; 632 ms.p_end = p + lp; 633 do { 634 const char *res; 635 ms.level = 0; 636 lua_assert(ms.matchdepth == MAXCCALLS); 637 if ((res=match(&ms, s1, p)) != NULL) { 638 if (find) { 639 lua_pushinteger(L, s1 - s + 1); /* start */ 640 lua_pushinteger(L, res - s); /* end */ 641 return push_captures(&ms, NULL, 0) + 2; 642 } 643 else 644 return push_captures(&ms, s1, res); 645 } 646 } while (s1++ < ms.src_end && !anchor); 647 } 648 lua_pushnil(L); /* not found */ 649 return 1; 650 } 651 652 653 static int str_find (lua_State *L) { 654 return str_find_aux(L, 1); 655 } 656 657 658 static int str_match (lua_State *L) { 659 return str_find_aux(L, 0); 660 } 661 662 663 static int gmatch_aux (lua_State *L) { 664 MatchState ms; 665 size_t ls, lp; 666 const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls); 667 const char *p = lua_tolstring(L, lua_upvalueindex(2), &lp); 668 const char *src; 669 ms.L = L; 670 ms.matchdepth = MAXCCALLS; 671 ms.src_init = s; 672 ms.src_end = s+ls; 673 ms.p_end = p + lp; 674 for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3)); 675 src <= ms.src_end; 676 src++) { 677 const char *e; 678 ms.level = 0; 679 lua_assert(ms.matchdepth == MAXCCALLS); 680 if ((e = match(&ms, src, p)) != NULL) { 681 lua_Integer newstart = e-s; 682 if (e == src) newstart++; /* empty match? go at least one position */ 683 lua_pushinteger(L, newstart); 684 lua_replace(L, lua_upvalueindex(3)); 685 return push_captures(&ms, src, e); 686 } 687 } 688 return 0; /* not found */ 689 } 690 691 692 static int str_gmatch (lua_State *L) { 693 luaL_checkstring(L, 1); 694 luaL_checkstring(L, 2); 695 lua_settop(L, 2); 696 lua_pushinteger(L, 0); 697 lua_pushcclosure(L, gmatch_aux, 3); 698 return 1; 699 } 700 701 702 static void add_s (MatchState *ms, luaL_Buffer *b, const char *s, 703 const char *e) { 704 size_t l, i; 705 const char *news = lua_tolstring(ms->L, 3, &l); 706 for (i = 0; i < l; i++) { 707 if (news[i] != L_ESC) 708 luaL_addchar(b, news[i]); 709 else { 710 i++; /* skip ESC */ 711 if (!isdigit(uchar(news[i]))) { 712 if (news[i] != L_ESC) 713 luaL_error(ms->L, "invalid use of " LUA_QL("%c") 714 " in replacement string", L_ESC); 715 luaL_addchar(b, news[i]); 716 } 717 else if (news[i] == '0') 718 luaL_addlstring(b, s, e - s); 719 else { 720 push_onecapture(ms, news[i] - '1', s, e); 721 luaL_addvalue(b); /* add capture to accumulated result */ 722 } 723 } 724 } 725 } 726 727 728 static void add_value (MatchState *ms, luaL_Buffer *b, const char *s, 729 const char *e, int tr) { 730 lua_State *L = ms->L; 731 switch (tr) { 732 case LUA_TFUNCTION: { 733 int n; 734 lua_pushvalue(L, 3); 735 n = push_captures(ms, s, e); 736 lua_call(L, n, 1); 737 break; 738 } 739 case LUA_TTABLE: { 740 push_onecapture(ms, 0, s, e); 741 lua_gettable(L, 3); 742 break; 743 } 744 default: { /* LUA_TNUMBER or LUA_TSTRING */ 745 add_s(ms, b, s, e); 746 return; 747 } 748 } 749 if (!lua_toboolean(L, -1)) { /* nil or false? */ 750 lua_pop(L, 1); 751 lua_pushlstring(L, s, e - s); /* keep original text */ 752 } 753 else if (!lua_isstring(L, -1)) 754 luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1)); 755 luaL_addvalue(b); /* add result to accumulator */ 756 } 757 758 759 static int str_gsub (lua_State *L) { 760 size_t srcl, lp; 761 const char *src = luaL_checklstring(L, 1, &srcl); 762 const char *p = luaL_checklstring(L, 2, &lp); 763 int tr = lua_type(L, 3); 764 size_t max_s = luaL_optinteger(L, 4, srcl+1); 765 int anchor = (*p == '^'); 766 size_t n = 0; 767 MatchState ms; 768 luaL_Buffer b; 769 luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING || 770 tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3, 771 "string/function/table expected"); 772 luaL_buffinit(L, &b); 773 if (anchor) { 774 p++; lp--; /* skip anchor character */ 775 } 776 ms.L = L; 777 ms.matchdepth = MAXCCALLS; 778 ms.src_init = src; 779 ms.src_end = src+srcl; 780 ms.p_end = p + lp; 781 while (n < max_s) { 782 const char *e; 783 ms.level = 0; 784 lua_assert(ms.matchdepth == MAXCCALLS); 785 e = match(&ms, src, p); 786 if (e) { 787 n++; 788 add_value(&ms, &b, src, e, tr); 789 } 790 if (e && e>src) /* non empty match? */ 791 src = e; /* skip it */ 792 else if (src < ms.src_end) 793 luaL_addchar(&b, *src++); 794 else break; 795 if (anchor) break; 796 } 797 luaL_addlstring(&b, src, ms.src_end-src); 798 luaL_pushresult(&b); 799 lua_pushinteger(L, n); /* number of substitutions */ 800 return 2; 801 } 802 803 /* }====================================================== */ 804 805 806 807 /* 808 ** {====================================================== 809 ** STRING FORMAT 810 ** ======================================================= 811 */ 812 813 /* 814 ** LUA_INTFRMLEN is the length modifier for integer conversions in 815 ** 'string.format'; LUA_INTFRM_T is the integer type corresponding to 816 ** the previous length 817 */ 818 #if !defined(LUA_INTFRMLEN) /* { */ 819 #if defined(LUA_USE_LONGLONG) 820 821 #define LUA_INTFRMLEN "ll" 822 #define LUA_INTFRM_T long long 823 824 #else 825 826 #define LUA_INTFRMLEN "l" 827 #define LUA_INTFRM_T long 828 829 #endif 830 #endif /* } */ 831 832 833 /* 834 ** LUA_FLTFRMLEN is the length modifier for float conversions in 835 ** 'string.format'; LUA_FLTFRM_T is the float type corresponding to 836 ** the previous length 837 */ 838 #if !defined(LUA_FLTFRMLEN) 839 840 #define LUA_FLTFRMLEN "" 841 #define LUA_FLTFRM_T double 842 843 #endif 844 845 846 /* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */ 847 #define MAX_ITEM 512 848 /* valid flags in a format specification */ 849 #define FLAGS "-+ #0" 850 /* 851 ** maximum size of each format specification (such as '%-099.99d') 852 ** (+10 accounts for %99.99x plus margin of error) 853 */ 854 #define MAX_FORMAT (sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10) 855 856 857 static void addquoted (lua_State *L, luaL_Buffer *b, int arg) { 858 size_t l; 859 const char *s = luaL_checklstring(L, arg, &l); 860 luaL_addchar(b, '"'); 861 while (l--) { 862 if (*s == '"' || *s == '\\' || *s == '\n') { 863 luaL_addchar(b, '\\'); 864 luaL_addchar(b, *s); 865 } 866 else if (*s == '\0' || iscntrl(uchar(*s))) { 867 char buff[10]; 868 if (!isdigit(uchar(*(s+1)))) 869 sprintf(buff, "\\%d", (int)uchar(*s)); 870 else 871 sprintf(buff, "\\%03d", (int)uchar(*s)); 872 luaL_addstring(b, buff); 873 } 874 else 875 luaL_addchar(b, *s); 876 s++; 877 } 878 luaL_addchar(b, '"'); 879 } 880 881 static const char *scanformat (lua_State *L, const char *strfrmt, char *form) { 882 const char *p = strfrmt; 883 while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */ 884 if ((size_t)(p - strfrmt) >= sizeof(FLAGS)/sizeof(char)) 885 luaL_error(L, "invalid format (repeated flags)"); 886 if (isdigit(uchar(*p))) p++; /* skip width */ 887 if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ 888 if (*p == '.') { 889 p++; 890 if (isdigit(uchar(*p))) p++; /* skip precision */ 891 if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ 892 } 893 if (isdigit(uchar(*p))) 894 luaL_error(L, "invalid format (width or precision too long)"); 895 *(form++) = '%'; 896 memcpy(form, strfrmt, (p - strfrmt + 1) * sizeof(char)); 897 form += p - strfrmt + 1; 898 *form = '\0'; 899 return p; 900 } 901 902 903 /* 904 ** add length modifier into formats 905 */ 906 static void addlenmod (char *form, const char *lenmod) { 907 size_t l = strlen(form); 908 size_t lm = strlen(lenmod); 909 char spec = form[l - 1]; 910 strcpy(form + l - 1, lenmod); 911 form[l + lm - 1] = spec; 912 form[l + lm] = '\0'; 913 } 914 915 916 static int str_format (lua_State *L) { 917 int top = lua_gettop(L); 918 int arg = 1; 919 size_t sfl; 920 const char *strfrmt = luaL_checklstring(L, arg, &sfl); 921 const char *strfrmt_end = strfrmt+sfl; 922 luaL_Buffer b; 923 luaL_buffinit(L, &b); 924 while (strfrmt < strfrmt_end) { 925 if (*strfrmt != L_ESC) 926 luaL_addchar(&b, *strfrmt++); 927 else if (*++strfrmt == L_ESC) 928 luaL_addchar(&b, *strfrmt++); /* %% */ 929 else { /* format item */ 930 char form[MAX_FORMAT]; /* to store the format (`%...') */ 931 char *buff = luaL_prepbuffsize(&b, MAX_ITEM); /* to put formatted item */ 932 int nb = 0; /* number of bytes in added item */ 933 if (++arg > top) 934 luaL_argerror(L, arg, "no value"); 935 strfrmt = scanformat(L, strfrmt, form); 936 switch (*strfrmt++) { 937 case 'c': { 938 nb = str_sprintf(buff, form, luaL_checkint(L, arg)); 939 break; 940 } 941 case 'd': case 'i': { 942 lua_Number n = luaL_checknumber(L, arg); 943 LUA_INTFRM_T ni = (LUA_INTFRM_T)n; 944 lua_Number diff = n - (lua_Number)ni; 945 luaL_argcheck(L, -1 < diff && diff < 1, arg, 946 "not a number in proper range"); 947 addlenmod(form, LUA_INTFRMLEN); 948 nb = str_sprintf(buff, form, ni); 949 break; 950 } 951 case 'o': case 'u': case 'x': case 'X': { 952 lua_Number n = luaL_checknumber(L, arg); 953 unsigned LUA_INTFRM_T ni = (unsigned LUA_INTFRM_T)n; 954 lua_Number diff = n - (lua_Number)ni; 955 luaL_argcheck(L, -1 < diff && diff < 1, arg, 956 "not a non-negative number in proper range"); 957 addlenmod(form, LUA_INTFRMLEN); 958 nb = str_sprintf(buff, form, ni); 959 break; 960 } 961 #if defined(LUA_USE_FLOAT_FORMATS) 962 case 'e': case 'E': case 'f': 963 #if defined(LUA_USE_AFORMAT) 964 case 'a': case 'A': 965 #endif 966 case 'g': case 'G': { 967 addlenmod(form, LUA_FLTFRMLEN); 968 nb = str_sprintf(buff, form, (LUA_FLTFRM_T)luaL_checknumber(L, arg)); 969 break; 970 } 971 #endif 972 case 'q': { 973 addquoted(L, &b, arg); 974 break; 975 } 976 case 's': { 977 size_t l; 978 const char *s = luaL_tolstring(L, arg, &l); 979 if (!strchr(form, '.') && l >= 100) { 980 /* no precision and string is too long to be formatted; 981 keep original string */ 982 luaL_addvalue(&b); 983 break; 984 } 985 else { 986 nb = str_sprintf(buff, form, s); 987 lua_pop(L, 1); /* remove result from 'luaL_tolstring' */ 988 break; 989 } 990 } 991 default: { /* also treat cases `pnLlh' */ 992 return luaL_error(L, "invalid option " LUA_QL("%%%c") " to " 993 LUA_QL("format"), *(strfrmt - 1)); 994 } 995 } 996 luaL_addsize(&b, nb); 997 } 998 } 999 luaL_pushresult(&b); 1000 return 1; 1001 } 1002 1003 /* }====================================================== */ 1004 1005 1006 static const luaL_Reg strlib[] = { 1007 {"byte", str_byte}, 1008 {"char", str_char}, 1009 {"dump", str_dump}, 1010 {"find", str_find}, 1011 {"format", str_format}, 1012 {"gmatch", str_gmatch}, 1013 {"gsub", str_gsub}, 1014 {"len", str_len}, 1015 {"lower", str_lower}, 1016 {"match", str_match}, 1017 {"rep", str_rep}, 1018 {"reverse", str_reverse}, 1019 {"sub", str_sub}, 1020 {"upper", str_upper}, 1021 {NULL, NULL} 1022 }; 1023 1024 1025 static void createmetatable (lua_State *L) { 1026 lua_createtable(L, 0, 1); /* table to be metatable for strings */ 1027 lua_pushliteral(L, ""); /* dummy string */ 1028 lua_pushvalue(L, -2); /* copy table */ 1029 lua_setmetatable(L, -2); /* set table as metatable for strings */ 1030 lua_pop(L, 1); /* pop dummy string */ 1031 lua_pushvalue(L, -2); /* get string library */ 1032 lua_setfield(L, -2, "__index"); /* metatable.__index = string */ 1033 lua_pop(L, 1); /* pop metatable */ 1034 } 1035 1036 1037 /* 1038 ** Open string library 1039 */ 1040 LUAMOD_API int luaopen_string (lua_State *L) { 1041 luaL_newlib(L, strlib); 1042 createmetatable(L); 1043 return 1; 1044 } 1045 1046