aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--liolib.c128
-rw-r--r--lstrlib.c239
-rw-r--r--lualib.h8
3 files changed, 164 insertions, 211 deletions
diff --git a/liolib.c b/liolib.c
index 4ef4c439..e47ebd81 100644
--- a/liolib.c
+++ b/liolib.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: liolib.c,v 1.90 2000/10/27 16:15:53 roberto Exp roberto $ 2** $Id: liolib.c,v 1.91 2000/10/31 13:10:24 roberto Exp roberto $
3** Standard I/O (and system) library 3** Standard I/O (and system) library
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -51,6 +51,8 @@ int pclose(); */
51 51
52#define INFILE 0 52#define INFILE 0
53#define OUTFILE 1 53#define OUTFILE 1
54#define NOFILE 2
55
54 56
55typedef struct IOCtrl { 57typedef struct IOCtrl {
56 int ref[2]; /* ref for strings _INPUT/_OUTPUT */ 58 int ref[2]; /* ref for strings _INPUT/_OUTPUT */
@@ -132,7 +134,8 @@ static int setreturn (lua_State *L, IOCtrl *ctrl, FILE *f, int inout) {
132 if (f == NULL) 134 if (f == NULL)
133 return pushresult(L, 0); 135 return pushresult(L, 0);
134 else { 136 else {
135 setfile(L, ctrl, f, inout); 137 if (inout != NOFILE)
138 setfile(L, ctrl, f, inout);
136 lua_pushusertag(L, f, ctrl->iotag); 139 lua_pushusertag(L, f, ctrl->iotag);
137 return 1; 140 return 1;
138 } 141 }
@@ -171,12 +174,13 @@ static int io_open (lua_State *L) {
171 FILE *f; 174 FILE *f;
172 lua_pop(L, 1); /* remove upvalue */ 175 lua_pop(L, 1); /* remove upvalue */
173 f = fopen(luaL_check_string(L, 1), luaL_check_string(L, 2)); 176 f = fopen(luaL_check_string(L, 1), luaL_check_string(L, 2));
174 if (f) { 177 return setreturn(L, ctrl, f, NOFILE);
175 lua_pushusertag(L, f, ctrl->iotag); 178}
176 return 1; 179
177 } 180
178 else 181static int io_tmpfile (lua_State *L) {
179 return pushresult(L, 0); 182 IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, -1);
183 return setreturn(L, ctrl, tmpfile(), NOFILE);
180} 184}
181 185
182 186
@@ -227,71 +231,9 @@ static int io_appendto (lua_State *L) {
227 231
228 232
229 233
230#ifdef LUA_COMPAT_READPATTERN
231
232/*
233** We cannot lookahead without need, because this can lock stdin.
234** This flag signals when we need to read a next char.
235*/
236#define NEED_OTHER (EOF-1) /* just some flag different from EOF */
237
238
239static int read_pattern (lua_State *L, FILE *f, const char *p) {
240 int inskip = 0; /* {skip} level */
241 int c = NEED_OTHER;
242 luaL_Buffer b;
243 luaL_buffinit(L, &b);
244 while (*p != '\0') {
245 switch (*p) {
246 case '{':
247 inskip++;
248 p++;
249 continue;
250 case '}':
251 if (!inskip) lua_error(L, "unbalanced braces in read pattern");
252 inskip--;
253 p++;
254 continue;
255 default: {
256 const char *ep = luaI_classend(L, p); /* get what is next */
257 int m; /* match result */
258 if (c == NEED_OTHER) c = getc(f);
259 m = (c==EOF) ? 0 : luaI_singlematch(c, p, ep);
260 if (m) {
261 if (!inskip) luaL_putchar(&b, c);
262 c = NEED_OTHER;
263 }
264 switch (*ep) {
265 case '+': /* repetition (1 or more) */
266 if (!m) goto break_while; /* pattern fails? */
267 /* else go through */
268 case '*': /* repetition (0 or more) */
269 while (m) { /* reads the same item until it fails */
270 c = getc(f);
271 m = (c==EOF) ? 0 : luaI_singlematch(c, p, ep);
272 if (m && !inskip) luaL_putchar(&b, c);
273 }
274 /* go through to continue reading the pattern */
275 case '?': /* optional */
276 p = ep+1; /* continues reading the pattern */
277 continue;
278 default:
279 if (!m) goto break_while; /* pattern fails? */
280 p = ep; /* else continues reading the pattern */
281 }
282 }
283 }
284 } break_while:
285 if (c != NEED_OTHER) ungetc(c, f);
286 luaL_pushresult(&b); /* close buffer */
287 return (*p == '\0');
288}
289
290#else
291 234
292#define read_pattern(L, f, p) (lua_error(L, "read patterns are deprecated"), 0) 235#define read_pattern(L, f, p) (lua_error(L, "read patterns are deprecated"), 0)
293 236
294#endif
295 237
296 238
297static int read_number (lua_State *L, FILE *f) { 239static int read_number (lua_State *L, FILE *f) {
@@ -400,8 +342,10 @@ static int io_read (lua_State *L) {
400 success = read_chars(L, f, (size_t)lua_tonumber(L, n)); 342 success = read_chars(L, f, (size_t)lua_tonumber(L, n));
401 else { 343 else {
402 const char *p = luaL_check_string(L, n); 344 const char *p = luaL_check_string(L, n);
403 if (p[0] != '*') 345 if (p[0] != '*') {
404 success = read_pattern(L, f, p); /* deprecated! */ 346 lua_error(L, "read patterns are deprecated");
347 success = 0; /* to avoid warnings */
348 }
405 else { 349 else {
406 switch (p[1]) { 350 switch (p[1]) {
407 case 'n': /* number */ 351 case 'n': /* number */
@@ -516,7 +460,10 @@ static int io_rename (lua_State *L) {
516 460
517 461
518static int io_tmpname (lua_State *L) { 462static int io_tmpname (lua_State *L) {
519 lua_pushstring(L, tmpnam(NULL)); 463 char buff[L_tmpnam];
464 if (tmpnam(buff) != buff)
465 lua_error(L, "unable to generate a unique filename");
466 lua_pushstring(L, buff);
520 return 1; 467 return 1;
521} 468}
522 469
@@ -548,7 +495,7 @@ static int io_date (lua_State *L) {
548} 495}
549 496
550 497
551static int setloc (lua_State *L) { 498static int io_setloc (lua_State *L) {
552 static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, 499 static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY,
553 LC_NUMERIC, LC_TIME}; 500 LC_NUMERIC, LC_TIME};
554 static const char *const catnames[] = {"all", "collate", "ctype", "monetary", 501 static const char *const catnames[] = {"all", "collate", "ctype", "monetary",
@@ -658,28 +605,29 @@ static int errorfb (lua_State *L) {
658static const struct luaL_reg iolib[] = { 605static const struct luaL_reg iolib[] = {
659 {LUA_ERRORMESSAGE, errorfb}, 606 {LUA_ERRORMESSAGE, errorfb},
660 {"clock", io_clock}, 607 {"clock", io_clock},
661 {"date", io_date}, 608 {"date", io_date},
662 {"debug", io_debug}, 609 {"debug", io_debug},
663 {"execute", io_execute}, 610 {"execute", io_execute},
664 {"exit", io_exit}, 611 {"exit", io_exit},
665 {"getenv", io_getenv}, 612 {"getenv", io_getenv},
666 {"remove", io_remove}, 613 {"remove", io_remove},
667 {"rename", io_rename}, 614 {"rename", io_rename},
668 {"setlocale", setloc}, 615 {"setlocale", io_setloc},
669 {"tmpname", io_tmpname} 616 {"tmpname", io_tmpname}
670}; 617};
671 618
672 619
673static const struct luaL_reg iolibtag[] = { 620static const struct luaL_reg iolibtag[] = {
674 {"appendto", io_appendto}, 621 {"appendto", io_appendto},
675 {"closefile", io_close}, 622 {"closefile", io_close},
676 {"flush", io_flush}, 623 {"flush", io_flush},
677 {"openfile", io_open}, 624 {"openfile", io_open},
678 {"read", io_read}, 625 {"read", io_read},
679 {"readfrom", io_readfrom}, 626 {"readfrom", io_readfrom},
680 {"seek", io_seek}, 627 {"seek", io_seek},
681 {"write", io_write}, 628 {"tmpfile", io_tmpfile},
682 {"writeto", io_writeto} 629 {"write", io_write},
630 {"writeto", io_writeto}
683}; 631};
684 632
685 633
diff --git a/lstrlib.c b/lstrlib.c
index 6013de24..9b960190 100644
--- a/lstrlib.c
+++ b/lstrlib.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstrlib.c,v 1.55 2000/10/20 16:39:03 roberto Exp roberto $ 2** $Id: lstrlib.c,v 1.56 2000/10/27 16:15:53 roberto Exp roberto $
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*/
@@ -121,46 +121,47 @@ static int str_char (lua_State *L) {
121#endif 121#endif
122 122
123 123
124struct Capture { 124typedef struct MatchState {
125 const char *src_end; /* end ('\0') of source string */ 125 const char *src_end; /* end ('\0') of source string */
126 int level; /* total number of captures (finished or unfinished) */ 126 int level; /* total number of captures (finished or unfinished) */
127 struct { 127 struct {
128 const char *init; 128 const char *init;
129 long len; /* -1 signals unfinished capture */ 129 long len; /* -1 signals unfinished capture */
130 } capture[MAX_CAPTURES]; 130 } capture[MAX_CAPTURES];
131}; 131 lua_State *L;
132} MatchState;
132 133
133 134
134#define ESC '%' 135#define ESC '%'
135#define SPECIALS "^$*+?.([%-" 136#define SPECIALS "^$*+?.([%-"
136 137
137 138
138static int check_capture (lua_State *L, int l, struct Capture *cap) { 139static int check_capture (MatchState *ms, int l) {
139 l -= '1'; 140 l -= '1';
140 if (!(0 <= l && l < cap->level && cap->capture[l].len != -1)) 141 if (!(0 <= l && l < ms->level && ms->capture[l].len != -1))
141 lua_error(L, "invalid capture index"); 142 lua_error(ms->L, "invalid capture index");
142 return l; 143 return l;
143} 144}
144 145
145 146
146static int capture_to_close (lua_State *L, struct Capture *cap) { 147static int capture_to_close (MatchState *ms) {
147 int level = cap->level; 148 int level = ms->level;
148 for (level--; level>=0; level--) 149 for (level--; level>=0; level--)
149 if (cap->capture[level].len == -1) return level; 150 if (ms->capture[level].len == -1) return level;
150 lua_error(L, "invalid pattern capture"); 151 lua_error(ms->L, "invalid pattern capture");
151 return 0; /* to avoid warnings */ 152 return 0; /* to avoid warnings */
152} 153}
153 154
154 155
155const char *luaI_classend (lua_State *L, const char *p) { 156static const char *luaI_classend (MatchState *ms, const char *p) {
156 switch (*p++) { 157 switch (*p++) {
157 case ESC: 158 case ESC:
158 if (*p == '\0') lua_error(L, "malformed pattern (ends with `%')"); 159 if (*p == '\0') lua_error(ms->L, "malformed pattern (ends with `%')");
159 return p+1; 160 return p+1;
160 case '[': 161 case '[':
161 if (*p == '^') p++; 162 if (*p == '^') p++;
162 do { /* look for a ']' */ 163 do { /* look for a ']' */
163 if (*p == '\0') lua_error(L, "malformed pattern (missing `]')"); 164 if (*p == '\0') lua_error(ms->L, "malformed pattern (missing `]')");
164 if (*(p++) == ESC && *p != '\0') p++; /* skip escapes (e.g. '%]') */ 165 if (*(p++) == ESC && *p != '\0') p++; /* skip escapes (e.g. '%]') */
165 } while (*p != ']'); 166 } while (*p != ']');
166 return p+1; 167 return p+1;
@@ -189,7 +190,6 @@ static int match_class (int c, int cl) {
189} 190}
190 191
191 192
192
193static int matchbracketclass (int c, const char *p, const char *endclass) { 193static int matchbracketclass (int c, const char *p, const char *endclass) {
194 int sig = 1; 194 int sig = 1;
195 if (*(p+1) == '^') { 195 if (*(p+1) == '^') {
@@ -213,8 +213,7 @@ static int matchbracketclass (int c, const char *p, const char *endclass) {
213} 213}
214 214
215 215
216 216static int luaI_singlematch (int c, const char *p, const char *ep) {
217int luaI_singlematch (int c, const char *p, const char *ep) {
218 switch (*p) { 217 switch (*p) {
219 case '.': /* matches any char */ 218 case '.': /* matches any char */
220 return 1; 219 return 1;
@@ -228,20 +227,18 @@ int luaI_singlematch (int c, const char *p, const char *ep) {
228} 227}
229 228
230 229
231static const char *match (lua_State *L, const char *s, const char *p, 230static const char *match (MatchState *ms, const char *s, const char *p);
232 struct Capture *cap);
233 231
234 232
235static const char *matchbalance (lua_State *L, const char *s, const char *p, 233static const char *matchbalance (MatchState *ms, const char *s, const char *p) {
236 struct Capture *cap) {
237 if (*p == 0 || *(p+1) == 0) 234 if (*p == 0 || *(p+1) == 0)
238 lua_error(L, "unbalanced pattern"); 235 lua_error(ms->L, "unbalanced pattern");
239 if (*s != *p) return NULL; 236 if (*s != *p) return NULL;
240 else { 237 else {
241 int b = *p; 238 int b = *p;
242 int e = *(p+1); 239 int e = *(p+1);
243 int cont = 1; 240 int cont = 1;
244 while (++s < cap->src_end) { 241 while (++s < ms->src_end) {
245 if (*s == e) { 242 if (*s == e) {
246 if (--cont == 0) return s+1; 243 if (--cont == 0) return s+1;
247 } 244 }
@@ -252,14 +249,14 @@ static const char *matchbalance (lua_State *L, const char *s, const char *p,
252} 249}
253 250
254 251
255static const char *max_expand (lua_State *L, const char *s, const char *p, 252static const char *max_expand (MatchState *ms, const char *s, const char *p,
256 const char *ep, struct Capture *cap) { 253 const char *ep) {
257 long i = 0; /* counts maximum expand for item */ 254 long i = 0; /* counts maximum expand for item */
258 while ((s+i)<cap->src_end && luaI_singlematch((unsigned char)*(s+i), p, ep)) 255 while ((s+i)<ms->src_end && luaI_singlematch((unsigned char)*(s+i), p, ep))
259 i++; 256 i++;
260 /* keeps trying to match with the maximum repetitions */ 257 /* keeps trying to match with the maximum repetitions */
261 while (i>=0) { 258 while (i>=0) {
262 const char *res = match(L, (s+i), ep+1, cap); 259 const char *res = match(ms, (s+i), ep+1);
263 if (res) return res; 260 if (res) return res;
264 i--; /* else didn't match; reduce 1 repetition to try again */ 261 i--; /* else didn't match; reduce 1 repetition to try again */
265 } 262 }
@@ -267,100 +264,96 @@ static const char *max_expand (lua_State *L, const char *s, const char *p,
267} 264}
268 265
269 266
270static const char *min_expand (lua_State *L, const char *s, const char *p, 267static const char *min_expand (MatchState *ms, const char *s, const char *p,
271 const char *ep, struct Capture *cap) { 268 const char *ep) {
272 for (;;) { 269 for (;;) {
273 const char *res = match(L, s, ep+1, cap); 270 const char *res = match(ms, s, ep+1);
274 if (res != NULL) 271 if (res != NULL)
275 return res; 272 return res;
276 else if (s<cap->src_end && luaI_singlematch((unsigned char)*s, p, ep)) 273 else if (s<ms->src_end && luaI_singlematch((unsigned char)*s, p, ep))
277 s++; /* try with one more repetition */ 274 s++; /* try with one more repetition */
278 else return NULL; 275 else return NULL;
279 } 276 }
280} 277}
281 278
282 279
283static const char *start_capture (lua_State *L, const char *s, const char *p, 280static const char *start_capture (MatchState *ms, const char *s, const char *p){
284 struct Capture *cap) {
285 const char *res; 281 const char *res;
286 int level = cap->level; 282 int level = ms->level;
287 if (level >= MAX_CAPTURES) lua_error(L, "too many captures"); 283 if (level >= MAX_CAPTURES) lua_error(ms->L, "too many captures");
288 cap->capture[level].init = s; 284 ms->capture[level].init = s;
289 cap->capture[level].len = -1; 285 ms->capture[level].len = -1;
290 cap->level = level+1; 286 ms->level = level+1;
291 if ((res=match(L, s, p+1, cap)) == NULL) /* match failed? */ 287 if ((res=match(ms, s, p+1)) == NULL) /* match failed? */
292 cap->level--; /* undo capture */ 288 ms->level--; /* undo capture */
293 return res; 289 return res;
294} 290}
295 291
296 292
297static const char *end_capture (lua_State *L, const char *s, const char *p, 293static const char *end_capture (MatchState *ms, const char *s, const char *p) {
298 struct Capture *cap) { 294 int l = capture_to_close(ms);
299 int l = capture_to_close(L, cap);
300 const char *res; 295 const char *res;
301 cap->capture[l].len = s - cap->capture[l].init; /* close capture */ 296 ms->capture[l].len = s - ms->capture[l].init; /* close capture */
302 if ((res = match(L, s, p+1, cap)) == NULL) /* match failed? */ 297 if ((res = match(ms, s, p+1)) == NULL) /* match failed? */
303 cap->capture[l].len = -1; /* undo capture */ 298 ms->capture[l].len = -1; /* undo capture */
304 return res; 299 return res;
305} 300}
306 301
307 302
308static const char *match_capture (lua_State *L, const char *s, int level, 303static const char *match_capture (MatchState *ms, const char *s, int level) {
309 struct Capture *cap) { 304 int l = check_capture(ms, level);
310 int l = check_capture(L, level, cap); 305 size_t len = ms->capture[l].len;
311 size_t len = cap->capture[l].len; 306 if ((size_t)(ms->src_end-s) >= len &&
312 if ((size_t)(cap->src_end-s) >= len && 307 memcmp(ms->capture[l].init, s, len) == 0)
313 memcmp(cap->capture[l].init, s, len) == 0)
314 return s+len; 308 return s+len;
315 else return NULL; 309 else return NULL;
316} 310}
317 311
318 312
319static const char *match (lua_State *L, const char *s, const char *p, 313static const char *match (MatchState *ms, const char *s, const char *p) {
320 struct Capture *cap) {
321 init: /* using goto's to optimize tail recursion */ 314 init: /* using goto's to optimize tail recursion */
322 switch (*p) { 315 switch (*p) {
323 case '(': /* start capture */ 316 case '(': /* start capture */
324 return start_capture(L, s, p, cap); 317 return start_capture(ms, s, p);
325 case ')': /* end capture */ 318 case ')': /* end capture */
326 return end_capture(L, s, p, cap); 319 return end_capture(ms, s, p);
327 case ESC: /* may be %[0-9] or %b */ 320 case ESC: /* may be %[0-9] or %b */
328 if (isdigit((unsigned char)(*(p+1)))) { /* capture? */ 321 if (isdigit((unsigned char)(*(p+1)))) { /* capture? */
329 s = match_capture(L, s, *(p+1), cap); 322 s = match_capture(ms, s, *(p+1));
330 if (s == NULL) return NULL; 323 if (s == NULL) return NULL;
331 p+=2; goto init; /* else return match(L, s, p+2, cap) */ 324 p+=2; goto init; /* else return match(ms, s, p+2) */
332 } 325 }
333 else if (*(p+1) == 'b') { /* balanced string? */ 326 else if (*(p+1) == 'b') { /* balanced string? */
334 s = matchbalance(L, s, p+2, cap); 327 s = matchbalance(ms, s, p+2);
335 if (s == NULL) return NULL; 328 if (s == NULL) return NULL;
336 p+=4; goto init; /* else return match(L, s, p+4, cap); */ 329 p+=4; goto init; /* else return match(ms, s, p+4); */
337 } 330 }
338 else goto dflt; /* case default */ 331 else goto dflt; /* case default */
339 case '\0': /* end of pattern */ 332 case '\0': /* end of pattern */
340 return s; /* match succeeded */ 333 return s; /* match succeeded */
341 case '$': 334 case '$':
342 if (*(p+1) == '\0') /* is the '$' the last char in pattern? */ 335 if (*(p+1) == '\0') /* is the '$' the last char in pattern? */
343 return (s == cap->src_end) ? s : NULL; /* check end of string */ 336 return (s == ms->src_end) ? s : NULL; /* check end of string */
344 else goto dflt; 337 else goto dflt;
345 default: dflt: { /* it is a pattern item */ 338 default: dflt: { /* it is a pattern item */
346 const char *ep = luaI_classend(L, p); /* points to what is next */ 339 const char *ep = luaI_classend(ms, p); /* points to what is next */
347 int m = s<cap->src_end && luaI_singlematch((unsigned char)*s, p, ep); 340 int m = s<ms->src_end && luaI_singlematch((unsigned char)*s, p, ep);
348 switch (*ep) { 341 switch (*ep) {
349 case '?': { /* optional */ 342 case '?': { /* optional */
350 const char *res; 343 const char *res;
351 if (m && ((res=match(L, s+1, ep+1, cap)) != NULL)) 344 if (m && ((res=match(ms, s+1, ep+1)) != NULL))
352 return res; 345 return res;
353 p=ep+1; goto init; /* else return match(L, s, ep+1, cap); */ 346 p=ep+1; goto init; /* else return match(ms, s, ep+1); */
354 } 347 }
355 case '*': /* 0 or more repetitions */ 348 case '*': /* 0 or more repetitions */
356 return max_expand(L, s, p, ep, cap); 349 return max_expand(ms, s, p, ep);
357 case '+': /* 1 or more repetitions */ 350 case '+': /* 1 or more repetitions */
358 return (m ? max_expand(L, s+1, p, ep, cap) : NULL); 351 return (m ? max_expand(ms, s+1, p, ep) : NULL);
359 case '-': /* 0 or more repetitions (minimum) */ 352 case '-': /* 0 or more repetitions (minimum) */
360 return min_expand(L, s, p, ep, cap); 353 return min_expand(ms, s, p, ep);
361 default: 354 default:
362 if (!m) return NULL; 355 if (!m) return NULL;
363 s++; p=ep; goto init; /* else return match(L, s+1, ep, cap); */ 356 s++; p=ep; goto init; /* else return match(ms, s+1, ep); */
364 } 357 }
365 } 358 }
366 } 359 }
@@ -390,15 +383,15 @@ static const char *lmemfind (const char *s1, size_t l1,
390} 383}
391 384
392 385
393static int push_captures (lua_State *L, struct Capture *cap) { 386static int push_captures (MatchState *ms) {
394 int i; 387 int i;
395 luaL_checkstack(L, cap->level, "too many captures"); 388 luaL_checkstack(ms->L, ms->level, "too many captures");
396 for (i=0; i<cap->level; i++) { 389 for (i=0; i<ms->level; i++) {
397 int l = cap->capture[i].len; 390 int l = ms->capture[i].len;
398 if (l == -1) lua_error(L, "unfinished capture"); 391 if (l == -1) lua_error(ms->L, "unfinished capture");
399 lua_pushlstring(L, cap->capture[i].init, l); 392 lua_pushlstring(ms->L, ms->capture[i].init, l);
400 } 393 }
401 return cap->level; /* number of strings pushed */ 394 return ms->level; /* number of strings pushed */
402} 395}
403 396
404 397
@@ -407,7 +400,6 @@ static int str_find (lua_State *L) {
407 const char *s = luaL_check_lstr(L, 1, &l1); 400 const char *s = luaL_check_lstr(L, 1, &l1);
408 const char *p = luaL_check_lstr(L, 2, &l2); 401 const char *p = luaL_check_lstr(L, 2, &l2);
409 long init = posrelat(luaL_opt_long(L, 3, 1), l1) - 1; 402 long init = posrelat(luaL_opt_long(L, 3, 1), l1) - 1;
410 struct Capture cap;
411 luaL_arg_check(L, 0 <= init && (size_t)init <= l1, 3, "out of range"); 403 luaL_arg_check(L, 0 <= init && (size_t)init <= l1, 3, "out of range");
412 if (lua_gettop(L) > 3 || /* extra argument? */ 404 if (lua_gettop(L) > 3 || /* extra argument? */
413 strpbrk(p, SPECIALS) == NULL) { /* or no special characters? */ 405 strpbrk(p, SPECIALS) == NULL) { /* or no special characters? */
@@ -419,25 +411,28 @@ static int str_find (lua_State *L) {
419 } 411 }
420 } 412 }
421 else { 413 else {
414 MatchState ms;
422 int anchor = (*p == '^') ? (p++, 1) : 0; 415 int anchor = (*p == '^') ? (p++, 1) : 0;
423 const char *s1=s+init; 416 const char *s1=s+init;
424 cap.src_end = s+l1; 417 ms.L = L;
418 ms.src_end = s+l1;
425 do { 419 do {
426 const char *res; 420 const char *res;
427 cap.level = 0; 421 ms.level = 0;
428 if ((res=match(L, s1, p, &cap)) != NULL) { 422 if ((res=match(&ms, s1, p)) != NULL) {
429 lua_pushnumber(L, s1-s+1); /* start */ 423 lua_pushnumber(L, s1-s+1); /* start */
430 lua_pushnumber(L, res-s); /* end */ 424 lua_pushnumber(L, res-s); /* end */
431 return push_captures(L, &cap) + 2; 425 return push_captures(&ms) + 2;
432 } 426 }
433 } while (s1++<cap.src_end && !anchor); 427 } while (s1++<ms.src_end && !anchor);
434 } 428 }
435 lua_pushnil(L); /* not found */ 429 lua_pushnil(L); /* not found */
436 return 1; 430 return 1;
437} 431}
438 432
439 433
440static void add_s (lua_State *L, luaL_Buffer *b, struct Capture *cap) { 434static void add_s (MatchState *ms, luaL_Buffer *b) {
435 lua_State *L = ms->L;
441 if (lua_isstring(L, 3)) { 436 if (lua_isstring(L, 3)) {
442 const char *news = lua_tostring(L, 3); 437 const char *news = lua_tostring(L, 3);
443 size_t l = lua_strlen(L, 3); 438 size_t l = lua_strlen(L, 3);
@@ -450,8 +445,8 @@ static void add_s (lua_State *L, luaL_Buffer *b, struct Capture *cap) {
450 if (!isdigit((unsigned char)news[i])) 445 if (!isdigit((unsigned char)news[i]))
451 luaL_putchar(b, news[i]); 446 luaL_putchar(b, news[i]);
452 else { 447 else {
453 int level = check_capture(L, news[i], cap); 448 int level = check_capture(ms, news[i]);
454 luaL_addlstring(b, cap->capture[level].init, cap->capture[level].len); 449 luaL_addlstring(b, ms->capture[level].init, ms->capture[level].len);
455 } 450 }
456 } 451 }
457 } 452 }
@@ -459,7 +454,7 @@ static void add_s (lua_State *L, luaL_Buffer *b, struct Capture *cap) {
459 else { /* is a function */ 454 else { /* is a function */
460 int n; 455 int n;
461 lua_pushvalue(L, 3); 456 lua_pushvalue(L, 3);
462 n = push_captures(L, cap); 457 n = push_captures(ms);
463 lua_rawcall(L, n, 1); 458 lua_rawcall(L, n, 1);
464 if (lua_isstring(L, -1)) 459 if (lua_isstring(L, -1))
465 luaL_addvalue(b); /* add return to accumulated result */ 460 luaL_addvalue(b); /* add return to accumulated result */
@@ -476,29 +471,30 @@ static int str_gsub (lua_State *L) {
476 int max_s = luaL_opt_int(L, 4, srcl+1); 471 int max_s = luaL_opt_int(L, 4, srcl+1);
477 int anchor = (*p == '^') ? (p++, 1) : 0; 472 int anchor = (*p == '^') ? (p++, 1) : 0;
478 int n = 0; 473 int n = 0;
479 struct Capture cap; 474 MatchState ms;
480 luaL_Buffer b; 475 luaL_Buffer b;
481 luaL_arg_check(L, 476 luaL_arg_check(L,
482 lua_gettop(L) >= 3 && (lua_isstring(L, 3) || lua_isfunction(L, 3)), 477 lua_gettop(L) >= 3 && (lua_isstring(L, 3) || lua_isfunction(L, 3)),
483 3, "string or function expected"); 478 3, "string or function expected");
484 luaL_buffinit(L, &b); 479 luaL_buffinit(L, &b);
485 cap.src_end = src+srcl; 480 ms.L = L;
481 ms.src_end = src+srcl;
486 while (n < max_s) { 482 while (n < max_s) {
487 const char *e; 483 const char *e;
488 cap.level = 0; 484 ms.level = 0;
489 e = match(L, src, p, &cap); 485 e = match(&ms, src, p);
490 if (e) { 486 if (e) {
491 n++; 487 n++;
492 add_s(L, &b, &cap); 488 add_s(&ms, &b);
493 } 489 }
494 if (e && e>src) /* non empty match? */ 490 if (e && e>src) /* non empty match? */
495 src = e; /* skip it */ 491 src = e; /* skip it */
496 else if (src < cap.src_end) 492 else if (src < ms.src_end)
497 luaL_putchar(&b, *src++); 493 luaL_putchar(&b, *src++);
498 else break; 494 else break;
499 if (anchor) break; 495 if (anchor) break;
500 } 496 }
501 luaL_addlstring(&b, src, cap.src_end-src); 497 luaL_addlstring(&b, src, ms.src_end-src);
502 luaL_pushresult(&b); 498 luaL_pushresult(&b);
503 lua_pushnumber(L, n); /* number of substitutions */ 499 lua_pushnumber(L, n); /* number of substitutions */
504 return 2; 500 return 2;
@@ -507,6 +503,12 @@ static int str_gsub (lua_State *L) {
507/* }====================================================== */ 503/* }====================================================== */
508 504
509 505
506/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */
507#define MAX_ITEM 512
508/* maximum size of each format specification (such as '%-099.99d') */
509#define MAX_FORMAT 20
510
511
510static void luaI_addquoted (lua_State *L, luaL_Buffer *b, int arg) { 512static void luaI_addquoted (lua_State *L, luaL_Buffer *b, int arg) {
511 size_t l; 513 size_t l;
512 const char *s = luaL_check_lstr(L, arg, &l); 514 const char *s = luaL_check_lstr(L, arg, &l);
@@ -525,10 +527,29 @@ static void luaI_addquoted (lua_State *L, luaL_Buffer *b, int arg) {
525 luaL_putchar(b, '"'); 527 luaL_putchar(b, '"');
526} 528}
527 529
528/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */ 530
529#define MAX_ITEM 512 531static const char *scanformat (lua_State *L, const char *strfrmt, char *form,
530/* maximum size of each format specification (such as '%-099.99d') */ 532 int *hasprecision) {
531#define MAX_FORMAT 20 533 const char *p = strfrmt;
534 while (strchr("-+ #0", *p)) p++; /* skip flags */
535 if (isdigit((unsigned char)*p)) p++; /* skip width */
536 if (isdigit((unsigned char)*p)) p++; /* (2 digits at most) */
537 if (*p == '.') {
538 p++;
539 *hasprecision = 1;
540 if (isdigit((unsigned char)*p)) p++; /* skip precision */
541 if (isdigit((unsigned char)*p)) p++; /* (2 digits at most) */
542 }
543 if (isdigit((unsigned char)*p))
544 lua_error(L, "invalid format (width or precision too long)");
545 if (p-strfrmt+2 > MAX_FORMAT) /* +2 to include `%' and the specifier */
546 lua_error(L, "invalid format (too long)");
547 form[0] = '%';
548 strncpy(form+1, strfrmt, p-strfrmt+1);
549 form[p-strfrmt+2] = 0;
550 return p;
551}
552
532 553
533static int str_format (lua_State *L) { 554static int str_format (lua_State *L) {
534 int arg = 1; 555 int arg = 1;
@@ -541,24 +562,15 @@ static int str_format (lua_State *L) {
541 else if (*++strfrmt == '%') 562 else if (*++strfrmt == '%')
542 luaL_putchar(&b, *strfrmt++); /* %% */ 563 luaL_putchar(&b, *strfrmt++); /* %% */
543 else { /* format item */ 564 else { /* format item */
544 struct Capture cap; 565 char form[MAX_FORMAT]; /* to store the format (`%...') */
545 char form[MAX_FORMAT]; /* to store the format ('%...') */
546 char buff[MAX_ITEM]; /* to store the formatted item */ 566 char buff[MAX_ITEM]; /* to store the formatted item */
547 const char *initf = strfrmt; 567 int hasprecision = 0;
548 form[0] = '%'; 568 if (isdigit((unsigned char)*strfrmt) && *(strfrmt+1) == '$') {
549 if (isdigit((unsigned char)*initf) && *(initf+1) == '$') { 569 arg = *strfrmt - '0';
550 arg = *initf - '0'; 570 strfrmt += 2; /* skip the `n$' */
551 initf += 2; /* skip the 'n$' */
552 } 571 }
553 arg++; 572 arg++;
554 cap.src_end = strfrmt+strlen(strfrmt)+1; 573 strfrmt = scanformat(L, strfrmt, form, &hasprecision);
555 cap.level = 0;
556 strfrmt = match(L, initf, "[-+ #0]*(%d*)%.?(%d*)", &cap);
557 if (cap.capture[0].len > 2 || cap.capture[1].len > 2 || /* < 100? */
558 strfrmt-initf > MAX_FORMAT-2)
559 lua_error(L, "invalid format (width or precision too long)");
560 strncpy(form+1, initf, strfrmt-initf+1); /* +1 to include conversion */
561 form[strfrmt-initf+2] = 0;
562 switch (*strfrmt++) { 574 switch (*strfrmt++) {
563 case 'c': case 'd': case 'i': 575 case 'c': case 'd': case 'i':
564 sprintf(buff, form, luaL_check_int(L, arg)); 576 sprintf(buff, form, luaL_check_int(L, arg));
@@ -575,7 +587,7 @@ static int str_format (lua_State *L) {
575 case 's': { 587 case 's': {
576 size_t l; 588 size_t l;
577 const char *s = luaL_check_lstr(L, arg, &l); 589 const char *s = luaL_check_lstr(L, arg, &l);
578 if (cap.capture[1].len == 0 && l >= 100) { 590 if (!hasprecision && l >= 100) {
579 /* no precision and string is too long to be formatted; 591 /* no precision and string is too long to be formatted;
580 keep original string */ 592 keep original string */
581 lua_pushvalue(L, arg); 593 lua_pushvalue(L, arg);
@@ -587,7 +599,7 @@ static int str_format (lua_State *L) {
587 break; 599 break;
588 } 600 }
589 } 601 }
590 default: /* also treat cases 'pnLlh' */ 602 default: /* also treat cases `pnLlh' */
591 lua_error(L, "invalid option in `format'"); 603 lua_error(L, "invalid option in `format'");
592 } 604 }
593 luaL_addlstring(&b, buff, strlen(buff)); 605 luaL_addlstring(&b, buff, strlen(buff));
@@ -605,7 +617,6 @@ static const struct luaL_reg strlib[] = {
605{"strupper", str_upper}, 617{"strupper", str_upper},
606{"strchar", str_char}, 618{"strchar", str_char},
607{"strrep", str_rep}, 619{"strrep", str_rep},
608{"ascii", str_byte}, /* for compatibility with 3.0 and earlier */
609{"strbyte", str_byte}, 620{"strbyte", str_byte},
610{"format", str_format}, 621{"format", str_format},
611{"strfind", str_find}, 622{"strfind", str_find},
diff --git a/lualib.h b/lualib.h
index d39a71bc..9dfcee5a 100644
--- a/lualib.h
+++ b/lualib.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lualib.h,v 1.13 2000/10/20 16:39:03 roberto Exp roberto $ 2** $Id: lualib.h,v 1.14 2000/10/27 16:15:53 roberto Exp roberto $
3** Lua standard libraries 3** Lua standard libraries
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -25,10 +25,4 @@ LUALIB_API void lua_mathlibopen (lua_State *L);
25LUALIB_API void lua_dblibopen (lua_State *L); 25LUALIB_API void lua_dblibopen (lua_State *L);
26 26
27 27
28
29/* Auxiliary functions (private) */
30
31const char *luaI_classend (lua_State *L, const char *p);
32int luaI_singlematch (int c, const char *p, const char *ep);
33
34#endif 28#endif