diff options
| -rw-r--r-- | lstrlib.c | 78 |
1 files changed, 49 insertions, 29 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lstrlib.c,v 1.86 2002/06/25 19:16:44 roberto Exp roberto $ | 2 | ** $Id: lstrlib.c,v 1.87 2002/06/26 19:28:08 roberto Exp roberto $ |
| 3 | ** Standard library for string operations and pattern-matching | 3 | ** Standard library for string operations and pattern-matching |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -166,11 +166,12 @@ static int capture_to_close (MatchState *ms) { | |||
| 166 | 166 | ||
| 167 | static const char *luaI_classend (MatchState *ms, const char *p) { | 167 | static const char *luaI_classend (MatchState *ms, const char *p) { |
| 168 | switch (*p++) { | 168 | switch (*p++) { |
| 169 | case ESC: | 169 | case ESC: { |
| 170 | if (*p == '\0') | 170 | if (*p == '\0') |
| 171 | luaL_error(ms->L, "malformed pattern (ends with `%')"); | 171 | luaL_error(ms->L, "malformed pattern (ends with `%')"); |
| 172 | return p+1; | 172 | return p+1; |
| 173 | case '[': | 173 | } |
| 174 | case '[': { | ||
| 174 | if (*p == '^') p++; | 175 | if (*p == '^') p++; |
| 175 | do { /* look for a `]' */ | 176 | do { /* look for a `]' */ |
| 176 | if (*p == '\0') | 177 | if (*p == '\0') |
| @@ -179,8 +180,10 @@ static const char *luaI_classend (MatchState *ms, const char *p) { | |||
| 179 | p++; /* skip escapes (e.g. `%]') */ | 180 | p++; /* skip escapes (e.g. `%]') */ |
| 180 | } while (*p != ']'); | 181 | } while (*p != ']'); |
| 181 | return p+1; | 182 | return p+1; |
| 182 | default: | 183 | } |
| 184 | default: { | ||
| 183 | return p; | 185 | return p; |
| 186 | } | ||
| 184 | } | 187 | } |
| 185 | } | 188 | } |
| 186 | 189 | ||
| @@ -229,14 +232,10 @@ static int matchbracketclass (int c, const char *p, const char *ec) { | |||
| 229 | 232 | ||
| 230 | static int luaI_singlematch (int c, const char *p, const char *ep) { | 233 | static int luaI_singlematch (int c, const char *p, const char *ep) { |
| 231 | switch (*p) { | 234 | switch (*p) { |
| 232 | case '.': /* matches any char */ | 235 | case '.': return 1; /* matches any char */ |
| 233 | return 1; | 236 | case ESC: return match_class(c, *(p+1)); |
| 234 | case ESC: | 237 | case '[': return matchbracketclass(c, p, ep-1); |
| 235 | return match_class(c, *(p+1)); | 238 | default: return (uchar(*p) == c); |
| 236 | case '[': | ||
| 237 | return matchbracketclass(c, p, ep-1); | ||
| 238 | default: | ||
| 239 | return (uchar(*p) == c); | ||
| 240 | } | 239 | } |
| 241 | } | 240 | } |
| 242 | 241 | ||
| @@ -331,14 +330,16 @@ static const char *match_capture (MatchState *ms, const char *s, int l) { | |||
| 331 | static const char *match (MatchState *ms, const char *s, const char *p) { | 330 | static const char *match (MatchState *ms, const char *s, const char *p) { |
| 332 | init: /* using goto's to optimize tail recursion */ | 331 | init: /* using goto's to optimize tail recursion */ |
| 333 | switch (*p) { | 332 | switch (*p) { |
| 334 | case '(': /* start capture */ | 333 | case '(': { /* start capture */ |
| 335 | if (*(p+1) == ')') /* position capture? */ | 334 | if (*(p+1) == ')') /* position capture? */ |
| 336 | return start_capture(ms, s, p+2, CAP_POSITION); | 335 | return start_capture(ms, s, p+2, CAP_POSITION); |
| 337 | else | 336 | else |
| 338 | return start_capture(ms, s, p+1, CAP_UNFINISHED); | 337 | return start_capture(ms, s, p+1, CAP_UNFINISHED); |
| 339 | case ')': /* end capture */ | 338 | } |
| 339 | case ')': { /* end capture */ | ||
| 340 | return end_capture(ms, s, p+1); | 340 | return end_capture(ms, s, p+1); |
| 341 | case ESC: /* may be %[0-9] or %b */ | 341 | } |
| 342 | case ESC: { /* may be %[0-9] or %b */ | ||
| 342 | if (isdigit(uchar(*(p+1)))) { /* capture? */ | 343 | if (isdigit(uchar(*(p+1)))) { /* capture? */ |
| 343 | s = match_capture(ms, s, *(p+1)); | 344 | s = match_capture(ms, s, *(p+1)); |
| 344 | if (s == NULL) return NULL; | 345 | if (s == NULL) return NULL; |
| @@ -350,12 +351,15 @@ static const char *match (MatchState *ms, const char *s, const char *p) { | |||
| 350 | p+=4; goto init; /* else return match(ms, s, p+4); */ | 351 | p+=4; goto init; /* else return match(ms, s, p+4); */ |
| 351 | } | 352 | } |
| 352 | else goto dflt; /* case default */ | 353 | else goto dflt; /* case default */ |
| 353 | case '\0': /* end of pattern */ | 354 | } |
| 355 | case '\0': { /* end of pattern */ | ||
| 354 | return s; /* match succeeded */ | 356 | return s; /* match succeeded */ |
| 355 | case '$': | 357 | } |
| 358 | case '$': { | ||
| 356 | if (*(p+1) == '\0') /* is the `$' the last char in pattern? */ | 359 | if (*(p+1) == '\0') /* is the `$' the last char in pattern? */ |
| 357 | return (s == ms->src_end) ? s : NULL; /* check end of string */ | 360 | return (s == ms->src_end) ? s : NULL; /* check end of string */ |
| 358 | else goto dflt; | 361 | else goto dflt; |
| 362 | } | ||
| 359 | default: dflt: { /* it is a pattern item */ | 363 | default: dflt: { /* it is a pattern item */ |
| 360 | const char *ep = luaI_classend(ms, p); /* points to what is next */ | 364 | const char *ep = luaI_classend(ms, p); /* points to what is next */ |
| 361 | int m = s<ms->src_end && luaI_singlematch(uchar(*s), p, ep); | 365 | int m = s<ms->src_end && luaI_singlematch(uchar(*s), p, ep); |
| @@ -366,15 +370,19 @@ static const char *match (MatchState *ms, const char *s, const char *p) { | |||
| 366 | return res; | 370 | return res; |
| 367 | p=ep+1; goto init; /* else return match(ms, s, ep+1); */ | 371 | p=ep+1; goto init; /* else return match(ms, s, ep+1); */ |
| 368 | } | 372 | } |
| 369 | case '*': /* 0 or more repetitions */ | 373 | case '*': { /* 0 or more repetitions */ |
| 370 | return max_expand(ms, s, p, ep); | 374 | return max_expand(ms, s, p, ep); |
| 371 | case '+': /* 1 or more repetitions */ | 375 | } |
| 376 | case '+': { /* 1 or more repetitions */ | ||
| 372 | return (m ? max_expand(ms, s+1, p, ep) : NULL); | 377 | return (m ? max_expand(ms, s+1, p, ep) : NULL); |
| 373 | case '-': /* 0 or more repetitions (minimum) */ | 378 | } |
| 379 | case '-': { /* 0 or more repetitions (minimum) */ | ||
| 374 | return min_expand(ms, s, p, ep); | 380 | return min_expand(ms, s, p, ep); |
| 375 | default: | 381 | } |
| 382 | default: { | ||
| 376 | if (!m) return NULL; | 383 | if (!m) return NULL; |
| 377 | s++; p=ep; goto init; /* else return match(ms, s+1, ep); */ | 384 | s++; p=ep; goto init; /* else return match(ms, s+1, ep); */ |
| 385 | } | ||
| 378 | } | 386 | } |
| 379 | } | 387 | } |
| 380 | } | 388 | } |
| @@ -590,12 +598,19 @@ static void luaI_addquoted (lua_State *L, luaL_Buffer *b, int arg) { | |||
| 590 | luaL_putchar(b, '"'); | 598 | luaL_putchar(b, '"'); |
| 591 | while (l--) { | 599 | while (l--) { |
| 592 | switch (*s) { | 600 | switch (*s) { |
| 593 | case '"': case '\\': case '\n': | 601 | case '"': case '\\': case '\n': { |
| 594 | luaL_putchar(b, '\\'); | 602 | luaL_putchar(b, '\\'); |
| 595 | luaL_putchar(b, *s); | 603 | luaL_putchar(b, *s); |
| 596 | break; | 604 | break; |
| 597 | case '\0': luaL_addlstring(b, "\\000", 4); break; | 605 | } |
| 598 | default: luaL_putchar(b, *s); | 606 | case '\0': { |
| 607 | luaL_addlstring(b, "\\000", 4); | ||
| 608 | break; | ||
| 609 | } | ||
| 610 | default: { | ||
| 611 | luaL_putchar(b, *s); | ||
| 612 | break; | ||
| 613 | } | ||
| 599 | } | 614 | } |
| 600 | s++; | 615 | s++; |
| 601 | } | 616 | } |
| @@ -647,19 +662,23 @@ static int str_format (lua_State *L) { | |||
| 647 | arg++; | 662 | arg++; |
| 648 | strfrmt = scanformat(L, strfrmt, form, &hasprecision); | 663 | strfrmt = scanformat(L, strfrmt, form, &hasprecision); |
| 649 | switch (*strfrmt++) { | 664 | switch (*strfrmt++) { |
| 650 | case 'c': case 'd': case 'i': | 665 | case 'c': case 'd': case 'i': { |
| 651 | sprintf(buff, form, luaL_check_int(L, arg)); | 666 | sprintf(buff, form, luaL_check_int(L, arg)); |
| 652 | break; | 667 | break; |
| 653 | case 'o': case 'u': case 'x': case 'X': | 668 | } |
| 669 | case 'o': case 'u': case 'x': case 'X': { | ||
| 654 | sprintf(buff, form, (unsigned int)(luaL_check_number(L, arg))); | 670 | sprintf(buff, form, (unsigned int)(luaL_check_number(L, arg))); |
| 655 | break; | 671 | break; |
| 672 | } | ||
| 656 | case 'e': case 'E': case 'f': | 673 | case 'e': case 'E': case 'f': |
| 657 | case 'g': case 'G': | 674 | case 'g': case 'G': { |
| 658 | sprintf(buff, form, luaL_check_number(L, arg)); | 675 | sprintf(buff, form, luaL_check_number(L, arg)); |
| 659 | break; | 676 | break; |
| 660 | case 'q': | 677 | } |
| 678 | case 'q': { | ||
| 661 | luaI_addquoted(L, &b, arg); | 679 | luaI_addquoted(L, &b, arg); |
| 662 | continue; /* skip the `addsize' at the end */ | 680 | continue; /* skip the `addsize' at the end */ |
| 681 | } | ||
| 663 | case 's': { | 682 | case 's': { |
| 664 | size_t l; | 683 | size_t l; |
| 665 | const char *s = luaL_check_lstr(L, arg, &l); | 684 | const char *s = luaL_check_lstr(L, arg, &l); |
| @@ -675,8 +694,9 @@ static int str_format (lua_State *L) { | |||
| 675 | break; | 694 | break; |
| 676 | } | 695 | } |
| 677 | } | 696 | } |
| 678 | default: /* also treat cases `pnLlh' */ | 697 | default: { /* also treat cases `pnLlh' */ |
| 679 | return luaL_error(L, "invalid option in `format'"); | 698 | return luaL_error(L, "invalid option in `format'"); |
| 699 | } | ||
| 680 | } | 700 | } |
| 681 | luaL_addlstring(&b, buff, strlen(buff)); | 701 | luaL_addlstring(&b, buff, strlen(buff)); |
| 682 | } | 702 | } |
