xref: /freebsd/sys/contrib/openzfs/module/lua/lstrlib.c (revision b077aed33b7b6aefca7b17ddb250cf521f938613)
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 '0': 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] == '0')
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
1039