?login_element?

Subversion Repositories NedoOS

Rev

Blame | Last modification | View Log | Download | RSS feed

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