summaryrefslogtreecommitdiff
path: root/apps/plugins/lua/lstrlib.c
diff options
context:
space:
mode:
authorRichard Quirk <richard.quirk@gmail.com>2014-03-19 19:31:31 +0100
committerMarcin Bukat <marcin.bukat@gmail.com>2014-04-02 20:31:54 +0200
commit36378988ad4059982742f05f5eb50580b456840a (patch)
treeee70be810d894566c5e351f21a1ebb79be742a85 /apps/plugins/lua/lstrlib.c
parent020f16a1c7d5bc9a302671cef03f56ac735e20c5 (diff)
downloadrockbox-36378988ad4059982742f05f5eb50580b456840a.tar.gz
rockbox-36378988ad4059982742f05f5eb50580b456840a.zip
Update lua plugin to 5.2.3
Prior to this patch the Lua plugin used version 5.1.4. This change reduces the number of modifications in the Lua source using some new defines and because the upstream source is now more flexible. Unless otherwise stated, l*.[ch] files are taken unmodified from the upstream lua-5.2.3. fscanf.c: file descriptors in rockbox are just ints, they are hidden behind a void* now so liolib requires less modifications. fscanf is updated to use void* too. getc.c: this is a new file required for getc implementation in lauxlib.c lauxlib.c: LoadF replaced FILE* with int, the rockbox file descriptor int are cast to FILE* (actually void* due to typedef). getc uses the PREFIX version. stdin is not used, as per 5.1.4. lbaselib.c: now uses strspn in the number parsing. print uses DEBUGF now rather than being commented out. lbitlib.c: use the built-in version from 5.2.3 rather than Reuben Thomas's external library. Backwards compatible and adds some new bit operations. ldo.c: the LUAI_THROW/TRY defines are now in the core lua code, so have been removed from rockconf.h liolib.c: here the implementation has changed to use the LStream from the original source, and cast the FILE* pointers to int. This has reduced the number of modifications from the upstream version. llex.c: the only change from upstream is to remove the locale include. lmathlib.c: updated from the 5.2.3 version and re-applied the changes that were made vs 5.1.4 for random numbers and to remove unsupported float functions. loadlib.c: upstream version, with the 5.1.4 changes for missing functions. lobject.c: upstream version, with ctype.h added and sprintf changed to snprintf. loslib.c: upstream version with locale.h removed and 5.1.4 changes for unsupportable functions. lstrlib.c: sprintf changed to snprintf. ltable.c: upstream with the hashnum function from 5.1.4 to avoid frexp in luai_hashnum. luaconf.h: updated to 5.2.3 version, restored relevant parts from the original 5.1.4 configuration. The COMPAT defines that are no longer available are not included. lundump.c: VERSION macro conflicts with the core Rockbox equivalent. rocklib.c: luaL_reg is no longer available, replaced by luaL_Reg equivalent. Moved checkboolean/optboolean functions to this file and out of core lua files. luaL_getn is no longer available, replaced by luaL_rawlen. luaL_register is deprecated, use the newlib/setfuncs replacements. rli_init has to be called before setting up the newlib to avoid overwriting the rb table. rocklib_aux.pl: use rli_checkboolean from rocklib.c. rocklua.c: new default bits library used, update the library loading code with idiomatic 5.2 code. strcspn.c: no longer needed, but strspn.c is required for strspn in lbaselib.c Change-Id: I0c7945c755f79083afe98ec117e1e8cf13de2651 Reviewed-on: http://gerrit.rockbox.org/774 Tested: Richard Quirk <richard.quirk@gmail.com> Reviewed-by: Marcin Bukat <marcin.bukat@gmail.com>
Diffstat (limited to 'apps/plugins/lua/lstrlib.c')
-rw-r--r--apps/plugins/lua/lstrlib.c580
1 files changed, 365 insertions, 215 deletions
diff --git a/apps/plugins/lua/lstrlib.c b/apps/plugins/lua/lstrlib.c
index 3d6103692f..04cc2f60d6 100644
--- a/apps/plugins/lua/lstrlib.c
+++ b/apps/plugins/lua/lstrlib.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstrlib.c,v 1.132.1.4 2008/07/11 17:27:21 roberto Exp $ 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 3** Standard library for string operations and pattern-matching
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -20,47 +20,58 @@
20#include "lualib.h" 20#include "lualib.h"
21 21
22 22
23/*
24** maximum number of captures that a pattern can do during
25** pattern-matching. This limit is arbitrary.
26*/
27#if !defined(LUA_MAXCAPTURES)
28#define LUA_MAXCAPTURES 32
29#endif
30
31
23/* macro to `unsign' a character */ 32/* macro to `unsign' a character */
24#define uchar(c) ((unsigned char)(c)) 33#define uchar(c) ((unsigned char)(c))
25 34
26 35
27 36
28static int str_len (lua_State *L) { 37static int str_len (lua_State *L) {
29 size_t l; 38 size_t l;
30 luaL_checklstring(L, 1, &l); 39 luaL_checklstring(L, 1, &l);
31 lua_pushinteger(L, l); 40 lua_pushinteger(L, (lua_Integer)l);
32 return 1; 41 return 1;
33} 42}
34 43
35 44
36static ptrdiff_t posrelat (ptrdiff_t pos, size_t len) { 45/* translate a relative string position: negative means back from end */
37 /* relative string position: negative means back from end */ 46static size_t posrelat (ptrdiff_t pos, size_t len) {
38 if (pos < 0) pos += (ptrdiff_t)len + 1; 47 if (pos >= 0) return (size_t)pos;
39 return (pos >= 0) ? pos : 0; 48 else if (0u - (size_t)pos > len) return 0;
49 else return len - ((size_t)-pos) + 1;
40} 50}
41 51
42 52
43static int str_sub (lua_State *L) { 53static int str_sub (lua_State *L) {
44 size_t l; 54 size_t l;
45 const char *s = luaL_checklstring(L, 1, &l); 55 const char *s = luaL_checklstring(L, 1, &l);
46 ptrdiff_t start = posrelat(luaL_checkinteger(L, 2), l); 56 size_t start = posrelat(luaL_checkinteger(L, 2), l);
47 ptrdiff_t end = posrelat(luaL_optinteger(L, 3, -1), l); 57 size_t end = posrelat(luaL_optinteger(L, 3, -1), l);
48 if (start < 1) start = 1; 58 if (start < 1) start = 1;
49 if (end > (ptrdiff_t)l) end = (ptrdiff_t)l; 59 if (end > l) end = l;
50 if (start <= end) 60 if (start <= end)
51 lua_pushlstring(L, s+start-1, end-start+1); 61 lua_pushlstring(L, s + start - 1, end - start + 1);
52 else lua_pushliteral(L, ""); 62 else lua_pushliteral(L, "");
53 return 1; 63 return 1;
54} 64}
55 65
56 66
57static int str_reverse (lua_State *L) { 67static int str_reverse (lua_State *L) {
58 size_t l; 68 size_t l, i;
59 luaL_Buffer b; 69 luaL_Buffer b;
60 const char *s = luaL_checklstring(L, 1, &l); 70 const char *s = luaL_checklstring(L, 1, &l);
61 luaL_buffinit(L, &b); 71 char *p = luaL_buffinitsize(L, &b, l);
62 while (l--) luaL_addchar(&b, s[l]); 72 for (i = 0; i < l; i++)
63 luaL_pushresult(&b); 73 p[i] = s[l - i - 1];
74 luaL_pushresultsize(&b, l);
64 return 1; 75 return 1;
65} 76}
66 77
@@ -70,10 +81,10 @@ static int str_lower (lua_State *L) {
70 size_t i; 81 size_t i;
71 luaL_Buffer b; 82 luaL_Buffer b;
72 const char *s = luaL_checklstring(L, 1, &l); 83 const char *s = luaL_checklstring(L, 1, &l);
73 luaL_buffinit(L, &b); 84 char *p = luaL_buffinitsize(L, &b, l);
74 for (i=0; i<l; i++) 85 for (i=0; i<l; i++)
75 luaL_addchar(&b, tolower(uchar(s[i]))); 86 p[i] = tolower(uchar(s[i]));
76 luaL_pushresult(&b); 87 luaL_pushresultsize(&b, l);
77 return 1; 88 return 1;
78} 89}
79 90
@@ -83,22 +94,38 @@ static int str_upper (lua_State *L) {
83 size_t i; 94 size_t i;
84 luaL_Buffer b; 95 luaL_Buffer b;
85 const char *s = luaL_checklstring(L, 1, &l); 96 const char *s = luaL_checklstring(L, 1, &l);
86 luaL_buffinit(L, &b); 97 char *p = luaL_buffinitsize(L, &b, l);
87 for (i=0; i<l; i++) 98 for (i=0; i<l; i++)
88 luaL_addchar(&b, toupper(uchar(s[i]))); 99 p[i] = toupper(uchar(s[i]));
89 luaL_pushresult(&b); 100 luaL_pushresultsize(&b, l);
90 return 1; 101 return 1;
91} 102}
92 103
104
105/* reasonable limit to avoid arithmetic overflow */
106#define MAXSIZE ((~(size_t)0) >> 1)
107
93static int str_rep (lua_State *L) { 108static int str_rep (lua_State *L) {
94 size_t l; 109 size_t l, lsep;
95 luaL_Buffer b;
96 const char *s = luaL_checklstring(L, 1, &l); 110 const char *s = luaL_checklstring(L, 1, &l);
97 int n = luaL_checkint(L, 2); 111 int n = luaL_checkint(L, 2);
98 luaL_buffinit(L, &b); 112 const char *sep = luaL_optlstring(L, 3, "", &lsep);
99 while (n-- > 0) 113 if (n <= 0) lua_pushliteral(L, "");
100 luaL_addlstring(&b, s, l); 114 else if (l + lsep < l || l + lsep >= MAXSIZE / n) /* may overflow? */
101 luaL_pushresult(&b); 115 return luaL_error(L, "resulting string too large");
116 else {
117 size_t totallen = n * l + (n - 1) * lsep;
118 luaL_Buffer b;
119 char *p = luaL_buffinitsize(L, &b, totallen);
120 while (n-- > 1) { /* first n-1 copies (followed by separator) */
121 memcpy(p, s, l * sizeof(char)); p += l;
122 if (lsep > 0) { /* avoid empty 'memcpy' (may be expensive) */
123 memcpy(p, sep, lsep * sizeof(char)); p += lsep;
124 }
125 }
126 memcpy(p, s, l * sizeof(char)); /* last copy (not followed by separator) */
127 luaL_pushresultsize(&b, totallen);
128 }
102 return 1; 129 return 1;
103} 130}
104 131
@@ -106,15 +133,15 @@ static int str_rep (lua_State *L) {
106static int str_byte (lua_State *L) { 133static int str_byte (lua_State *L) {
107 size_t l; 134 size_t l;
108 const char *s = luaL_checklstring(L, 1, &l); 135 const char *s = luaL_checklstring(L, 1, &l);
109 ptrdiff_t posi = posrelat(luaL_optinteger(L, 2, 1), l); 136 size_t posi = posrelat(luaL_optinteger(L, 2, 1), l);
110 ptrdiff_t pose = posrelat(luaL_optinteger(L, 3, posi), l); 137 size_t pose = posrelat(luaL_optinteger(L, 3, posi), l);
111 int n, i; 138 int n, i;
112 if (posi <= 0) posi = 1; 139 if (posi < 1) posi = 1;
113 if ((size_t)pose > l) pose = l; 140 if (pose > l) pose = l;
114 if (posi > pose) return 0; /* empty interval; return no values */ 141 if (posi > pose) return 0; /* empty interval; return no values */
115 n = (int)(pose - posi + 1); 142 n = (int)(pose - posi + 1);
116 if (posi + n <= pose) /* overflow? */ 143 if (posi + n <= pose) /* (size_t -> int) overflow? */
117 luaL_error(L, "string slice too long"); 144 return luaL_error(L, "string slice too long");
118 luaL_checkstack(L, n, "string slice too long"); 145 luaL_checkstack(L, n, "string slice too long");
119 for (i=0; i<n; i++) 146 for (i=0; i<n; i++)
120 lua_pushinteger(L, uchar(s[posi+i-1])); 147 lua_pushinteger(L, uchar(s[posi+i-1]));
@@ -126,13 +153,13 @@ static int str_char (lua_State *L) {
126 int n = lua_gettop(L); /* number of arguments */ 153 int n = lua_gettop(L); /* number of arguments */
127 int i; 154 int i;
128 luaL_Buffer b; 155 luaL_Buffer b;
129 luaL_buffinit(L, &b); 156 char *p = luaL_buffinitsize(L, &b, n);
130 for (i=1; i<=n; i++) { 157 for (i=1; i<=n; i++) {
131 int c = luaL_checkint(L, i); 158 int c = luaL_checkint(L, i);
132 luaL_argcheck(L, uchar(c) == c, i, "invalid value"); 159 luaL_argcheck(L, uchar(c) == c, i, "value out of range");
133 luaL_addchar(&b, uchar(c)); 160 p[i - 1] = uchar(c);
134 } 161 }
135 luaL_pushresult(&b); 162 luaL_pushresultsize(&b, n);
136 return 1; 163 return 1;
137} 164}
138 165
@@ -150,7 +177,7 @@ static int str_dump (lua_State *L) {
150 lua_settop(L, 1); 177 lua_settop(L, 1);
151 luaL_buffinit(L,&b); 178 luaL_buffinit(L,&b);
152 if (lua_dump(L, writer, &b) != 0) 179 if (lua_dump(L, writer, &b) != 0)
153 luaL_error(L, "unable to dump given function"); 180 return luaL_error(L, "unable to dump given function");
154 luaL_pushresult(&b); 181 luaL_pushresult(&b);
155 return 1; 182 return 1;
156} 183}
@@ -167,9 +194,12 @@ static int str_dump (lua_State *L) {
167#define CAP_UNFINISHED (-1) 194#define CAP_UNFINISHED (-1)
168#define CAP_POSITION (-2) 195#define CAP_POSITION (-2)
169 196
197
170typedef struct MatchState { 198typedef struct MatchState {
199 int matchdepth; /* control for recursive depth (to avoid C stack overflow) */
171 const char *src_init; /* init of source string */ 200 const char *src_init; /* init of source string */
172 const char *src_end; /* end (`\0') of source string */ 201 const char *src_end; /* end ('\0') of source string */
202 const char *p_end; /* end ('\0') of pattern */
173 lua_State *L; 203 lua_State *L;
174 int level; /* total number of captures (finished or unfinished) */ 204 int level; /* total number of captures (finished or unfinished) */
175 struct { 205 struct {
@@ -179,6 +209,16 @@ typedef struct MatchState {
179} MatchState; 209} MatchState;
180 210
181 211
212/* recursive function */
213static const char *match (MatchState *ms, const char *s, const char *p);
214
215
216/* maximum recursion depth for 'match' */
217#if !defined(MAXCCALLS)
218#define MAXCCALLS 200
219#endif
220
221
182#define L_ESC '%' 222#define L_ESC '%'
183#define SPECIALS "^$*+?.([%-" 223#define SPECIALS "^$*+?.([%-"
184 224
@@ -186,7 +226,7 @@ typedef struct MatchState {
186static int check_capture (MatchState *ms, int l) { 226static int check_capture (MatchState *ms, int l) {
187 l -= '1'; 227 l -= '1';
188 if (l < 0 || l >= ms->level || ms->capture[l].len == CAP_UNFINISHED) 228 if (l < 0 || l >= ms->level || ms->capture[l].len == CAP_UNFINISHED)
189 return luaL_error(ms->L, "invalid capture index"); 229 return luaL_error(ms->L, "invalid capture index %%%d", l + 1);
190 return l; 230 return l;
191} 231}
192 232
@@ -202,16 +242,16 @@ static int capture_to_close (MatchState *ms) {
202static const char *classend (MatchState *ms, const char *p) { 242static const char *classend (MatchState *ms, const char *p) {
203 switch (*p++) { 243 switch (*p++) {
204 case L_ESC: { 244 case L_ESC: {
205 if (*p == '\0') 245 if (p == ms->p_end)
206 luaL_error(ms->L, "malformed pattern (ends with " LUA_QL("%%") ")"); 246 luaL_error(ms->L, "malformed pattern (ends with " LUA_QL("%%") ")");
207 return p+1; 247 return p+1;
208 } 248 }
209 case '[': { 249 case '[': {
210 if (*p == '^') p++; 250 if (*p == '^') p++;
211 do { /* look for a `]' */ 251 do { /* look for a `]' */
212 if (*p == '\0') 252 if (p == ms->p_end)
213 luaL_error(ms->L, "malformed pattern (missing " LUA_QL("]") ")"); 253 luaL_error(ms->L, "malformed pattern (missing " LUA_QL("]") ")");
214 if (*(p++) == L_ESC && *p != '\0') 254 if (*(p++) == L_ESC && p < ms->p_end)
215 p++; /* skip escapes (e.g. `%]') */ 255 p++; /* skip escapes (e.g. `%]') */
216 } while (*p != ']'); 256 } while (*p != ']');
217 return p+1; 257 return p+1;
@@ -229,13 +269,14 @@ static int match_class (int c, int cl) {
229 case 'a' : res = isalpha(c); break; 269 case 'a' : res = isalpha(c); break;
230 case 'c' : res = iscntrl(c); break; 270 case 'c' : res = iscntrl(c); break;
231 case 'd' : res = isdigit(c); break; 271 case 'd' : res = isdigit(c); break;
272 case 'g' : res = isgraph(c); break;
232 case 'l' : res = islower(c); break; 273 case 'l' : res = islower(c); break;
233 case 'p' : res = ispunct(c); break; 274 case 'p' : res = ispunct(c); break;
234 case 's' : res = isspace(c); break; 275 case 's' : res = isspace(c); break;
235 case 'u' : res = isupper(c); break; 276 case 'u' : res = isupper(c); break;
236 case 'w' : res = isalnum(c); break; 277 case 'w' : res = isalnum(c); break;
237 case 'x' : res = isxdigit(c); break; 278 case 'x' : res = isxdigit(c); break;
238 case 'z' : res = (c == 0); break; 279 case 'z' : res = (c == 0); break; /* deprecated option */
239 default: return (cl == c); 280 default: return (cl == c);
240 } 281 }
241 return (islower(cl) ? res : !res); 282 return (islower(cl) ? res : !res);
@@ -265,23 +306,27 @@ static int matchbracketclass (int c, const char *p, const char *ec) {
265} 306}
266 307
267 308
268static int singlematch (int c, const char *p, const char *ep) { 309static int singlematch (MatchState *ms, const char *s, const char *p,
269 switch (*p) { 310 const char *ep) {
270 case '.': return 1; /* matches any char */ 311 if (s >= ms->src_end)
271 case L_ESC: return match_class(c, uchar(*(p+1))); 312 return 0;
272 case '[': return matchbracketclass(c, p, ep-1); 313 else {
273 default: return (uchar(*p) == c); 314 int c = uchar(*s);
315 switch (*p) {
316 case '.': return 1; /* matches any char */
317 case L_ESC: return match_class(c, uchar(*(p+1)));
318 case '[': return matchbracketclass(c, p, ep-1);
319 default: return (uchar(*p) == c);
320 }
274 } 321 }
275} 322}
276 323
277 324
278static const char *match (MatchState *ms, const char *s, const char *p);
279
280
281static const char *matchbalance (MatchState *ms, const char *s, 325static const char *matchbalance (MatchState *ms, const char *s,
282 const char *p) { 326 const char *p) {
283 if (*p == 0 || *(p+1) == 0) 327 if (p >= ms->p_end - 1)
284 luaL_error(ms->L, "unbalanced pattern"); 328 luaL_error(ms->L, "malformed pattern "
329 "(missing arguments to " LUA_QL("%%b") ")");
285 if (*s != *p) return NULL; 330 if (*s != *p) return NULL;
286 else { 331 else {
287 int b = *p; 332 int b = *p;
@@ -301,7 +346,7 @@ static const char *matchbalance (MatchState *ms, const char *s,
301static const char *max_expand (MatchState *ms, const char *s, 346static const char *max_expand (MatchState *ms, const char *s,
302 const char *p, const char *ep) { 347 const char *p, const char *ep) {
303 ptrdiff_t i = 0; /* counts maximum expand for item */ 348 ptrdiff_t i = 0; /* counts maximum expand for item */
304 while ((s+i)<ms->src_end && singlematch(uchar(*(s+i)), p, ep)) 349 while (singlematch(ms, s + i, p, ep))
305 i++; 350 i++;
306 /* keeps trying to match with the maximum repetitions */ 351 /* keeps trying to match with the maximum repetitions */
307 while (i>=0) { 352 while (i>=0) {
@@ -319,7 +364,7 @@ static const char *min_expand (MatchState *ms, const char *s,
319 const char *res = match(ms, s, ep+1); 364 const char *res = match(ms, s, ep+1);
320 if (res != NULL) 365 if (res != NULL)
321 return res; 366 return res;
322 else if (s<ms->src_end && singlematch(uchar(*s), p, ep)) 367 else if (singlematch(ms, s, p, ep))
323 s++; /* try with one more repetition */ 368 s++; /* try with one more repetition */
324 else return NULL; 369 else return NULL;
325 } 370 }
@@ -363,80 +408,105 @@ static const char *match_capture (MatchState *ms, const char *s, int l) {
363 408
364 409
365static const char *match (MatchState *ms, const char *s, const char *p) { 410static const char *match (MatchState *ms, const char *s, const char *p) {
411 if (ms->matchdepth-- == 0)
412 luaL_error(ms->L, "pattern too complex");
366 init: /* using goto's to optimize tail recursion */ 413 init: /* using goto's to optimize tail recursion */
367 switch (*p) { 414 if (p != ms->p_end) { /* end of pattern? */
368 case '(': { /* start capture */ 415 switch (*p) {
369 if (*(p+1) == ')') /* position capture? */ 416 case '(': { /* start capture */
370 return start_capture(ms, s, p+2, CAP_POSITION); 417 if (*(p + 1) == ')') /* position capture? */
371 else 418 s = start_capture(ms, s, p + 2, CAP_POSITION);
372 return start_capture(ms, s, p+1, CAP_UNFINISHED); 419 else
373 } 420 s = start_capture(ms, s, p + 1, CAP_UNFINISHED);
374 case ')': { /* end capture */ 421 break;
375 return end_capture(ms, s, p+1); 422 }
376 } 423 case ')': { /* end capture */
377 case L_ESC: { 424 s = end_capture(ms, s, p + 1);
378 switch (*(p+1)) { 425 break;
379 case 'b': { /* balanced string? */ 426 }
380 s = matchbalance(ms, s, p+2); 427 case '$': {
381 if (s == NULL) return NULL; 428 if ((p + 1) != ms->p_end) /* is the `$' the last char in pattern? */
382 p+=4; goto init; /* else return match(ms, s, p+4); */ 429 goto dflt; /* no; go to default */
383 } 430 s = (s == ms->src_end) ? s : NULL; /* check end of string */
384 case 'f': { /* frontier? */ 431 break;
385 const char *ep; char previous; 432 }
386 p += 2; 433 case L_ESC: { /* escaped sequences not in the format class[*+?-]? */
387 if (*p != '[') 434 switch (*(p + 1)) {
388 luaL_error(ms->L, "missing " LUA_QL("[") " after " 435 case 'b': { /* balanced string? */
389 LUA_QL("%%f") " in pattern"); 436 s = matchbalance(ms, s, p + 2);
390 ep = classend(ms, p); /* points to what is next */ 437 if (s != NULL) {
391 previous = (s == ms->src_init) ? '\0' : *(s-1); 438 p += 4; goto init; /* return match(ms, s, p + 4); */
392 if (matchbracketclass(uchar(previous), p, ep-1) || 439 } /* else fail (s == NULL) */
393 !matchbracketclass(uchar(*s), p, ep-1)) return NULL; 440 break;
394 p=ep; goto init; /* else return match(ms, s, ep); */ 441 }
395 } 442 case 'f': { /* frontier? */
396 default: { 443 const char *ep; char previous;
397 if (isdigit(uchar(*(p+1)))) { /* capture results (%0-%9)? */ 444 p += 2;
398 s = match_capture(ms, s, uchar(*(p+1))); 445 if (*p != '[')
399 if (s == NULL) return NULL; 446 luaL_error(ms->L, "missing " LUA_QL("[") " after "
400 p+=2; goto init; /* else return match(ms, s, p+2) */ 447 LUA_QL("%%f") " in pattern");
448 ep = classend(ms, p); /* points to what is next */
449 previous = (s == ms->src_init) ? '\0' : *(s - 1);
450 if (!matchbracketclass(uchar(previous), p, ep - 1) &&
451 matchbracketclass(uchar(*s), p, ep - 1)) {
452 p = ep; goto init; /* return match(ms, s, ep); */
453 }
454 s = NULL; /* match failed */
455 break;
401 } 456 }
402 goto dflt; /* case default */ 457 case '0': case '1': case '2': case '3':
458 case '4': case '5': case '6': case '7':
459 case '8': case '9': { /* capture results (%0-%9)? */
460 s = match_capture(ms, s, uchar(*(p + 1)));
461 if (s != NULL) {
462 p += 2; goto init; /* return match(ms, s, p + 2) */
463 }
464 break;
465 }
466 default: goto dflt;
403 } 467 }
468 break;
404 } 469 }
405 } 470 default: dflt: { /* pattern class plus optional suffix */
406 case '\0': { /* end of pattern */ 471 const char *ep = classend(ms, p); /* points to optional suffix */
407 return s; /* match succeeded */ 472 /* does not match at least once? */
408 } 473 if (!singlematch(ms, s, p, ep)) {
409 case '$': { 474 if (*ep == '*' || *ep == '?' || *ep == '-') { /* accept empty? */
410 if (*(p+1) == '\0') /* is the `$' the last char in pattern? */ 475 p = ep + 1; goto init; /* return match(ms, s, ep + 1); */
411 return (s == ms->src_end) ? s : NULL; /* check end of string */ 476 }
412 else goto dflt; 477 else /* '+' or no suffix */
413 } 478 s = NULL; /* fail */
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 } 479 }
433 default: { 480 else { /* matched once */
434 if (!m) return NULL; 481 switch (*ep) { /* handle optional suffix */
435 s++; p=ep; goto init; /* else return match(ms, s+1, ep); */ 482 case '?': { /* optional */
483 const char *res;
484 if ((res = match(ms, s + 1, ep + 1)) != NULL)
485 s = res;
486 else {
487 p = ep + 1; goto init; /* else return match(ms, s, ep + 1); */
488 }
489 break;
490 }
491 case '+': /* 1 or more repetitions */
492 s++; /* 1 match already done */
493 /* go through */
494 case '*': /* 0 or more repetitions */
495 s = max_expand(ms, s, p, ep);
496 break;
497 case '-': /* 0 or more repetitions (minimum) */
498 s = min_expand(ms, s, p, ep);
499 break;
500 default: /* no suffix */
501 s++; p = ep; goto init; /* return match(ms, s + 1, ep); */
502 }
436 } 503 }
504 break;
437 } 505 }
438 } 506 }
439 } 507 }
508 ms->matchdepth++;
509 return s;
440} 510}
441 511
442 512
@@ -492,37 +562,58 @@ static int push_captures (MatchState *ms, const char *s, const char *e) {
492} 562}
493 563
494 564
565/* check whether pattern has no special characters */
566static int nospecials (const char *p, size_t l) {
567 size_t upto = 0;
568 do {
569 if (strpbrk(p + upto, SPECIALS))
570 return 0; /* pattern has a special character */
571 upto += strlen(p + upto) + 1; /* may have more after \0 */
572 } while (upto <= l);
573 return 1; /* no special chars found */
574}
575
576
495static int str_find_aux (lua_State *L, int find) { 577static int str_find_aux (lua_State *L, int find) {
496 size_t l1, l2; 578 size_t ls, lp;
497 const char *s = luaL_checklstring(L, 1, &l1); 579 const char *s = luaL_checklstring(L, 1, &ls);
498 const char *p = luaL_checklstring(L, 2, &l2); 580 const char *p = luaL_checklstring(L, 2, &lp);
499 ptrdiff_t init = posrelat(luaL_optinteger(L, 3, 1), l1) - 1; 581 size_t init = posrelat(luaL_optinteger(L, 3, 1), ls);
500 if (init < 0) init = 0; 582 if (init < 1) init = 1;
501 else if ((size_t)(init) > l1) init = (ptrdiff_t)l1; 583 else if (init > ls + 1) { /* start after string's end? */
502 if (find && (lua_toboolean(L, 4) || /* explicit request? */ 584 lua_pushnil(L); /* cannot find anything */
503 strpbrk(p, SPECIALS) == NULL)) { /* or no special characters? */ 585 return 1;
586 }
587 /* explicit request or no special characters? */
588 if (find && (lua_toboolean(L, 4) || nospecials(p, lp))) {
504 /* do a plain search */ 589 /* do a plain search */
505 const char *s2 = lmemfind(s+init, l1-init, p, l2); 590 const char *s2 = lmemfind(s + init - 1, ls - init + 1, p, lp);
506 if (s2) { 591 if (s2) {
507 lua_pushinteger(L, s2-s+1); 592 lua_pushinteger(L, s2 - s + 1);
508 lua_pushinteger(L, s2-s+l2); 593 lua_pushinteger(L, s2 - s + lp);
509 return 2; 594 return 2;
510 } 595 }
511 } 596 }
512 else { 597 else {
513 MatchState ms; 598 MatchState ms;
514 int anchor = (*p == '^') ? (p++, 1) : 0; 599 const char *s1 = s + init - 1;
515 const char *s1=s+init; 600 int anchor = (*p == '^');
601 if (anchor) {
602 p++; lp--; /* skip anchor character */
603 }
516 ms.L = L; 604 ms.L = L;
605 ms.matchdepth = MAXCCALLS;
517 ms.src_init = s; 606 ms.src_init = s;
518 ms.src_end = s+l1; 607 ms.src_end = s + ls;
608 ms.p_end = p + lp;
519 do { 609 do {
520 const char *res; 610 const char *res;
521 ms.level = 0; 611 ms.level = 0;
612 lua_assert(ms.matchdepth == MAXCCALLS);
522 if ((res=match(&ms, s1, p)) != NULL) { 613 if ((res=match(&ms, s1, p)) != NULL) {
523 if (find) { 614 if (find) {
524 lua_pushinteger(L, s1-s+1); /* start */ 615 lua_pushinteger(L, s1 - s + 1); /* start */
525 lua_pushinteger(L, res-s); /* end */ 616 lua_pushinteger(L, res - s); /* end */
526 return push_captures(&ms, NULL, 0) + 2; 617 return push_captures(&ms, NULL, 0) + 2;
527 } 618 }
528 else 619 else
@@ -547,18 +638,21 @@ static int str_match (lua_State *L) {
547 638
548static int gmatch_aux (lua_State *L) { 639static int gmatch_aux (lua_State *L) {
549 MatchState ms; 640 MatchState ms;
550 size_t ls; 641 size_t ls, lp;
551 const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls); 642 const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls);
552 const char *p = lua_tostring(L, lua_upvalueindex(2)); 643 const char *p = lua_tolstring(L, lua_upvalueindex(2), &lp);
553 const char *src; 644 const char *src;
554 ms.L = L; 645 ms.L = L;
646 ms.matchdepth = MAXCCALLS;
555 ms.src_init = s; 647 ms.src_init = s;
556 ms.src_end = s+ls; 648 ms.src_end = s+ls;
649 ms.p_end = p + lp;
557 for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3)); 650 for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3));
558 src <= ms.src_end; 651 src <= ms.src_end;
559 src++) { 652 src++) {
560 const char *e; 653 const char *e;
561 ms.level = 0; 654 ms.level = 0;
655 lua_assert(ms.matchdepth == MAXCCALLS);
562 if ((e = match(&ms, src, p)) != NULL) { 656 if ((e = match(&ms, src, p)) != NULL) {
563 lua_Integer newstart = e-s; 657 lua_Integer newstart = e-s;
564 if (e == src) newstart++; /* empty match? go at least one position */ 658 if (e == src) newstart++; /* empty match? go at least one position */
@@ -581,12 +675,6 @@ static int gmatch (lua_State *L) {
581} 675}
582 676
583 677
584static 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
590static void add_s (MatchState *ms, luaL_Buffer *b, const char *s, 678static void add_s (MatchState *ms, luaL_Buffer *b, const char *s,
591 const char *e) { 679 const char *e) {
592 size_t l, i; 680 size_t l, i;
@@ -596,8 +684,12 @@ static void add_s (MatchState *ms, luaL_Buffer *b, const char *s,
596 luaL_addchar(b, news[i]); 684 luaL_addchar(b, news[i]);
597 else { 685 else {
598 i++; /* skip ESC */ 686 i++; /* skip ESC */
599 if (!isdigit(uchar(news[i]))) 687 if (!isdigit(uchar(news[i]))) {
688 if (news[i] != L_ESC)
689 luaL_error(ms->L, "invalid use of " LUA_QL("%c")
690 " in replacement string", L_ESC);
600 luaL_addchar(b, news[i]); 691 luaL_addchar(b, news[i]);
692 }
601 else if (news[i] == '0') 693 else if (news[i] == '0')
602 luaL_addlstring(b, s, e - s); 694 luaL_addlstring(b, s, e - s);
603 else { 695 else {
@@ -610,14 +702,9 @@ static void add_s (MatchState *ms, luaL_Buffer *b, const char *s,
610 702
611 703
612static void add_value (MatchState *ms, luaL_Buffer *b, const char *s, 704static void add_value (MatchState *ms, luaL_Buffer *b, const char *s,
613 const char *e) { 705 const char *e, int tr) {
614 lua_State *L = ms->L; 706 lua_State *L = ms->L;
615 switch (lua_type(L, 3)) { 707 switch (tr) {
616 case LUA_TNUMBER:
617 case LUA_TSTRING: {
618 add_s(ms, b, s, e);
619 return;
620 }
621 case LUA_TFUNCTION: { 708 case LUA_TFUNCTION: {
622 int n; 709 int n;
623 lua_pushvalue(L, 3); 710 lua_pushvalue(L, 3);
@@ -630,41 +717,51 @@ static void add_value (MatchState *ms, luaL_Buffer *b, const char *s,
630 lua_gettable(L, 3); 717 lua_gettable(L, 3);
631 break; 718 break;
632 } 719 }
720 default: { /* LUA_TNUMBER or LUA_TSTRING */
721 add_s(ms, b, s, e);
722 return;
723 }
633 } 724 }
634 if (!lua_toboolean(L, -1)) { /* nil or false? */ 725 if (!lua_toboolean(L, -1)) { /* nil or false? */
635 lua_pop(L, 1); 726 lua_pop(L, 1);
636 lua_pushlstring(L, s, e - s); /* keep original text */ 727 lua_pushlstring(L, s, e - s); /* keep original text */
637 } 728 }
638 else if (!lua_isstring(L, -1)) 729 else if (!lua_isstring(L, -1))
639 luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1)); 730 luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1));
640 luaL_addvalue(b); /* add result to accumulator */ 731 luaL_addvalue(b); /* add result to accumulator */
641} 732}
642 733
643 734
644static int str_gsub (lua_State *L) { 735static int str_gsub (lua_State *L) {
645 size_t srcl; 736 size_t srcl, lp;
646 const char *src = luaL_checklstring(L, 1, &srcl); 737 const char *src = luaL_checklstring(L, 1, &srcl);
647 const char *p = luaL_checkstring(L, 2); 738 const char *p = luaL_checklstring(L, 2, &lp);
648 int tr = lua_type(L, 3); 739 int tr = lua_type(L, 3);
649 int max_s = luaL_optint(L, 4, srcl+1); 740 size_t max_s = luaL_optinteger(L, 4, srcl+1);
650 int anchor = (*p == '^') ? (p++, 1) : 0; 741 int anchor = (*p == '^');
651 int n = 0; 742 size_t n = 0;
652 MatchState ms; 743 MatchState ms;
653 luaL_Buffer b; 744 luaL_Buffer b;
654 luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING || 745 luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING ||
655 tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3, 746 tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3,
656 "string/function/table expected"); 747 "string/function/table expected");
657 luaL_buffinit(L, &b); 748 luaL_buffinit(L, &b);
749 if (anchor) {
750 p++; lp--; /* skip anchor character */
751 }
658 ms.L = L; 752 ms.L = L;
753 ms.matchdepth = MAXCCALLS;
659 ms.src_init = src; 754 ms.src_init = src;
660 ms.src_end = src+srcl; 755 ms.src_end = src+srcl;
756 ms.p_end = p + lp;
661 while (n < max_s) { 757 while (n < max_s) {
662 const char *e; 758 const char *e;
663 ms.level = 0; 759 ms.level = 0;
760 lua_assert(ms.matchdepth == MAXCCALLS);
664 e = match(&ms, src, p); 761 e = match(&ms, src, p);
665 if (e) { 762 if (e) {
666 n++; 763 n++;
667 add_value(&ms, &b, src, e); 764 add_value(&ms, &b, src, e, tr);
668 } 765 }
669 if (e && e>src) /* non empty match? */ 766 if (e && e>src) /* non empty match? */
670 src = e; /* skip it */ 767 src = e; /* skip it */
@@ -682,6 +779,46 @@ static int str_gsub (lua_State *L) {
682/* }====================================================== */ 779/* }====================================================== */
683 780
684 781
782
783/*
784** {======================================================
785** STRING FORMAT
786** =======================================================
787*/
788
789/*
790** LUA_INTFRMLEN is the length modifier for integer conversions in
791** 'string.format'; LUA_INTFRM_T is the integer type corresponding to
792** the previous length
793*/
794#if !defined(LUA_INTFRMLEN) /* { */
795#if defined(LUA_USE_LONGLONG)
796
797#define LUA_INTFRMLEN "ll"
798#define LUA_INTFRM_T long long
799
800#else
801
802#define LUA_INTFRMLEN "l"
803#define LUA_INTFRM_T long
804
805#endif
806#endif /* } */
807
808
809/*
810** LUA_FLTFRMLEN is the length modifier for float conversions in
811** 'string.format'; LUA_FLTFRM_T is the float type corresponding to
812** the previous length
813*/
814#if !defined(LUA_FLTFRMLEN)
815
816#define LUA_FLTFRMLEN ""
817#define LUA_FLTFRM_T double
818
819#endif
820
821
685/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */ 822/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */
686#define MAX_ITEM 512 823#define MAX_ITEM 512
687/* valid flags in a format specification */ 824/* valid flags in a format specification */
@@ -698,25 +835,20 @@ static void addquoted (lua_State *L, luaL_Buffer *b, int arg) {
698 const char *s = luaL_checklstring(L, arg, &l); 835 const char *s = luaL_checklstring(L, arg, &l);
699 luaL_addchar(b, '"'); 836 luaL_addchar(b, '"');
700 while (l--) { 837 while (l--) {
701 switch (*s) { 838 if (*s == '"' || *s == '\\' || *s == '\n') {
702 case '"': case '\\': case '\n': { 839 luaL_addchar(b, '\\');
703 luaL_addchar(b, '\\'); 840 luaL_addchar(b, *s);
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 } 841 }
842 else if (*s == '\0' || iscntrl(uchar(*s))) {
843 char buff[10];
844 if (!isdigit(uchar(*(s+1))))
845 snprintf(buff, sizeof(buff), "\\%d", (int)uchar(*s));
846 else
847 snprintf(buff, sizeof(buff), "\\%03d", (int)uchar(*s));
848 luaL_addstring(b, buff);
849 }
850 else
851 luaL_addchar(b, *s);
720 s++; 852 s++;
721 } 853 }
722 luaL_addchar(b, '"'); 854 luaL_addchar(b, '"');
@@ -725,7 +857,7 @@ static void addquoted (lua_State *L, luaL_Buffer *b, int arg) {
725static const char *scanformat (lua_State *L, const char *strfrmt, char *form) { 857static const char *scanformat (lua_State *L, const char *strfrmt, char *form) {
726 const char *p = strfrmt; 858 const char *p = strfrmt;
727 while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */ 859 while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */
728 if ((size_t)(p - strfrmt) >= sizeof(FLAGS)) 860 if ((size_t)(p - strfrmt) >= sizeof(FLAGS)/sizeof(char))
729 luaL_error(L, "invalid format (repeated flags)"); 861 luaL_error(L, "invalid format (repeated flags)");
730 if (isdigit(uchar(*p))) p++; /* skip width */ 862 if (isdigit(uchar(*p))) p++; /* skip width */
731 if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ 863 if (isdigit(uchar(*p))) p++; /* (2 digits at most) */
@@ -737,23 +869,28 @@ static const char *scanformat (lua_State *L, const char *strfrmt, char *form) {
737 if (isdigit(uchar(*p))) 869 if (isdigit(uchar(*p)))
738 luaL_error(L, "invalid format (width or precision too long)"); 870 luaL_error(L, "invalid format (width or precision too long)");
739 *(form++) = '%'; 871 *(form++) = '%';
740 strncpy(form, strfrmt, p - strfrmt + 1); 872 memcpy(form, strfrmt, (p - strfrmt + 1) * sizeof(char));
741 form += p - strfrmt + 1; 873 form += p - strfrmt + 1;
742 *form = '\0'; 874 *form = '\0';
743 return p; 875 return p;
744} 876}
745 877
746 878
747static void addintlen (char *form) { 879/*
880** add length modifier into formats
881*/
882static void addlenmod (char *form, const char *lenmod) {
748 size_t l = strlen(form); 883 size_t l = strlen(form);
884 size_t lm = strlen(lenmod);
749 char spec = form[l - 1]; 885 char spec = form[l - 1];
750 strcpy(form + l - 1, LUA_INTFRMLEN); 886 strcpy(form + l - 1, lenmod);
751 form[l + sizeof(LUA_INTFRMLEN) - 2] = spec; 887 form[l + lm - 1] = spec;
752 form[l + sizeof(LUA_INTFRMLEN) - 1] = '\0'; 888 form[l + lm] = '\0';
753} 889}
754 890
755 891
756static int str_format (lua_State *L) { 892static int str_format (lua_State *L) {
893 int top = lua_gettop(L);
757 int arg = 1; 894 int arg = 1;
758 size_t sfl; 895 size_t sfl;
759 const char *strfrmt = luaL_checklstring(L, arg, &sfl); 896 const char *strfrmt = luaL_checklstring(L, arg, &sfl);
@@ -767,45 +904,61 @@ static int str_format (lua_State *L) {
767 luaL_addchar(&b, *strfrmt++); /* %% */ 904 luaL_addchar(&b, *strfrmt++); /* %% */
768 else { /* format item */ 905 else { /* format item */
769 char form[MAX_FORMAT]; /* to store the format (`%...') */ 906 char form[MAX_FORMAT]; /* to store the format (`%...') */
770 char buff[MAX_ITEM]; /* to store the formatted item */ 907 char *buff = luaL_prepbuffsize(&b, MAX_ITEM); /* to put formatted item */
771 arg++; 908 int nb = 0; /* number of bytes in added item */
909 if (++arg > top)
910 luaL_argerror(L, arg, "no value");
772 strfrmt = scanformat(L, strfrmt, form); 911 strfrmt = scanformat(L, strfrmt, form);
773 switch (*strfrmt++) { 912 switch (*strfrmt++) {
774 case 'c': { 913 case 'c': {
775 snprintf(buff, MAX_ITEM, form, (int)luaL_checknumber(L, arg)); 914 nb = snprintf(buff, MAX_ITEM, form, luaL_checkint(L, arg));
776 break; 915 break;
777 } 916 }
778 case 'd': case 'i': { 917 case 'd': case 'i': {
779 addintlen(form); 918 lua_Number n = luaL_checknumber(L, arg);
780 snprintf(buff, MAX_ITEM, form, (LUA_INTFRM_T)luaL_checknumber(L, arg)); 919 LUA_INTFRM_T ni = (LUA_INTFRM_T)n;
920 lua_Number diff = n - (lua_Number)ni;
921 luaL_argcheck(L, -1 < diff && diff < 1, arg,
922 "not a number in proper range");
923 addlenmod(form, LUA_INTFRMLEN);
924 nb = snprintf(buff, MAX_ITEM, form, ni);
781 break; 925 break;
782 } 926 }
783 case 'o': case 'u': case 'x': case 'X': { 927 case 'o': case 'u': case 'x': case 'X': {
784 addintlen(form); 928 lua_Number n = luaL_checknumber(L, arg);
785 snprintf(buff, MAX_ITEM, form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg)); 929 unsigned LUA_INTFRM_T ni = (unsigned LUA_INTFRM_T)n;
930 lua_Number diff = n - (lua_Number)ni;
931 luaL_argcheck(L, -1 < diff && diff < 1, arg,
932 "not a non-negative number in proper range");
933 addlenmod(form, LUA_INTFRMLEN);
934 nb = snprintf(buff, MAX_ITEM, form, ni);
786 break; 935 break;
787 } 936 }
788 case 'e': case 'E': case 'f': 937 case 'e': case 'E': case 'f':
938#if defined(LUA_USE_AFORMAT)
939 case 'a': case 'A':
940#endif
789 case 'g': case 'G': { 941 case 'g': case 'G': {
790 snprintf(buff, MAX_ITEM, form, (double)luaL_checknumber(L, arg)); 942 addlenmod(form, LUA_FLTFRMLEN);
943 nb = snprintf(buff, MAX_ITEM, form, (LUA_FLTFRM_T)luaL_checknumber(L, arg));
791 break; 944 break;
792 } 945 }
793 case 'q': { 946 case 'q': {
794 addquoted(L, &b, arg); 947 addquoted(L, &b, arg);
795 continue; /* skip the 'addsize' at the end */ 948 break;
796 } 949 }
797 case 's': { 950 case 's': {
798 size_t l; 951 size_t l;
799 const char *s = luaL_checklstring(L, arg, &l); 952 const char *s = luaL_tolstring(L, arg, &l);
800 if (!strchr(form, '.') && l >= 100) { 953 if (!strchr(form, '.') && l >= 100) {
801 /* no precision and string is too long to be formatted; 954 /* no precision and string is too long to be formatted;
802 keep original string */ 955 keep original string */
803 lua_pushvalue(L, arg);
804 luaL_addvalue(&b); 956 luaL_addvalue(&b);
805 continue; /* skip the `addsize' at the end */ 957 break;
806 } 958 }
807 else { 959 else {
808 snprintf(buff, MAX_ITEM, form, s); 960 nb = snprintf(buff, MAX_ITEM, form, s);
961 lua_pop(L, 1); /* remove result from 'luaL_tolstring' */
809 break; 962 break;
810 } 963 }
811 } 964 }
@@ -814,13 +967,15 @@ static int str_format (lua_State *L) {
814 LUA_QL("format"), *(strfrmt - 1)); 967 LUA_QL("format"), *(strfrmt - 1));
815 } 968 }
816 } 969 }
817 luaL_addlstring(&b, buff, strlen(buff)); 970 luaL_addsize(&b, nb);
818 } 971 }
819 } 972 }
820 luaL_pushresult(&b); 973 luaL_pushresult(&b);
821 return 1; 974 return 1;
822} 975}
823 976
977/* }====================================================== */
978
824 979
825static const luaL_Reg strlib[] = { 980static const luaL_Reg strlib[] = {
826 {"byte", str_byte}, 981 {"byte", str_byte},
@@ -828,7 +983,6 @@ static const luaL_Reg strlib[] = {
828 {"dump", str_dump}, 983 {"dump", str_dump},
829 {"find", str_find}, 984 {"find", str_find},
830 {"format", str_format}, 985 {"format", str_format},
831 {"gfind", gfind_nodef},
832 {"gmatch", gmatch}, 986 {"gmatch", gmatch},
833 {"gsub", str_gsub}, 987 {"gsub", str_gsub},
834 {"len", str_len}, 988 {"len", str_len},
@@ -843,13 +997,13 @@ static const luaL_Reg strlib[] = {
843 997
844 998
845static void createmetatable (lua_State *L) { 999static void createmetatable (lua_State *L) {
846 lua_createtable(L, 0, 1); /* create metatable for strings */ 1000 lua_createtable(L, 0, 1); /* table to be metatable for strings */
847 lua_pushliteral(L, ""); /* dummy string */ 1001 lua_pushliteral(L, ""); /* dummy string */
848 lua_pushvalue(L, -2); 1002 lua_pushvalue(L, -2); /* copy table */
849 lua_setmetatable(L, -2); /* set string metatable */ 1003 lua_setmetatable(L, -2); /* set table as metatable for strings */
850 lua_pop(L, 1); /* pop dummy string */ 1004 lua_pop(L, 1); /* pop dummy string */
851 lua_pushvalue(L, -2); /* string library... */ 1005 lua_pushvalue(L, -2); /* get string library */
852 lua_setfield(L, -2, "__index"); /* ...is the __index metamethod */ 1006 lua_setfield(L, -2, "__index"); /* metatable.__index = string */
853 lua_pop(L, 1); /* pop metatable */ 1007 lua_pop(L, 1); /* pop metatable */
854} 1008}
855 1009
@@ -857,12 +1011,8 @@ static void createmetatable (lua_State *L) {
857/* 1011/*
858** Open string library 1012** Open string library
859*/ 1013*/
860LUALIB_API int luaopen_string (lua_State *L) { 1014LUAMOD_API int luaopen_string (lua_State *L) {
861 luaL_register(L, LUA_STRLIBNAME, strlib); 1015 luaL_newlib(L, strlib);
862#if defined(LUA_COMPAT_GFIND)
863 lua_getfield(L, -1, "gmatch");
864 lua_setfield(L, -2, "gfind");
865#endif
866 createmetatable(L); 1016 createmetatable(L);
867 return 1; 1017 return 1;
868} 1018}