The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/openzfs/module/lua/lstrlib.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 494a00f864f44b5f021fa299ae52fa5d


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.