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