lstrlib.c
上传用户:yisoukefu
上传日期:2020-08-09
资源大小:39506k
文件大小:23k
源码类别:

其他游戏

开发平台:

Visual C++

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