LCOV - code coverage report
Current view: top level - src - lstrlib.c Coverage Total Hit
Test: Lua 5.3.6 Lines: 97.8 % 804 786
Test Date: 2024-04-28 10:23:15
Legend: Lines: hit not hit

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

Generated by: LCOV version 2.0-1