aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>1997-12-15 15:58:49 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>1997-12-15 15:58:49 -0200
commit82d09fbf0dbd5aee890f033b25b09dc48ce58a48 (patch)
tree7a77947d7efc3e8d1a128590588249278eb57d77
parent9be85d164855e74140b9da0c55568d7b7bf49d8a (diff)
downloadlua-82d09fbf0dbd5aee890f033b25b09dc48ce58a48.tar.gz
lua-82d09fbf0dbd5aee890f033b25b09dc48ce58a48.tar.bz2
lua-82d09fbf0dbd5aee890f033b25b09dc48ce58a48.zip
new structure for closures, without static variables.
-rw-r--r--lstrlib.c112
1 files changed, 62 insertions, 50 deletions
diff --git a/lstrlib.c b/lstrlib.c
index e5b87598..9f1ae82d 100644
--- a/lstrlib.c
+++ b/lstrlib.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstrlib.c,v 1.2 1997/11/26 18:53:45 roberto Exp roberto $ 2** $Id: lstrlib.c,v 1.3 1997/12/09 13:35:19 roberto Exp roberto $
3** Standard library for strings and pattern-matching 3** Standard library for strings and pattern-matching
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -145,45 +145,47 @@ static void str_ascii (void)
145 145
146#define MAX_CAPT 9 146#define MAX_CAPT 9
147 147
148static struct { 148struct Capture {
149 char *init; 149 struct {
150 int len; /* -1 signals unfinished capture */ 150 char *init;
151} capture[MAX_CAPT]; 151 int len; /* -1 signals unfinished capture */
152 152 } capture[MAX_CAPT];
153static int num_captures; /* only valid after a sucessful call to match */ 153 int level; /* total number of captures (finished or unfinished) */
154};
154 155
155 156
156#define ESC '%' 157#define ESC '%'
157#define SPECIALS "^$*?.([%-" 158#define SPECIALS "^$*?.([%-"
158 159
159 160
160static void push_captures (void) 161static void push_captures (struct Capture *cap)
161{ 162{
162 int i; 163 int i;
163 for (i=0; i<num_captures; i++) { 164 for (i=0; i<cap->level; i++) {
164 int l = capture[i].len; 165 int l = cap->capture[i].len;
165 char *buff = openspace(l+1); 166 char *buff = openspace(l+1);
166 if (l == -1) lua_error("unfinished capture"); 167 if (l == -1) lua_error("unfinished capture");
167 strncpy(buff, capture[i].init, l); 168 strncpy(buff, cap->capture[i].init, l);
168 buff[l] = 0; 169 buff[l] = 0;
169 lua_pushstring(buff); 170 lua_pushstring(buff);
170 } 171 }
171} 172}
172 173
173 174
174static int check_cap (int l, int level) 175static int check_cap (int l, struct Capture *cap)
175{ 176{
176 l -= '1'; 177 l -= '1';
177 if (!(0 <= l && l < level && capture[l].len != -1)) 178 if (!(0 <= l && l < cap->level && cap->capture[l].len != -1))
178 lua_error("invalid capture index"); 179 lua_error("invalid capture index");
179 return l; 180 return l;
180} 181}
181 182
182 183
183static int capture_to_close (int level) 184static int capture_to_close (struct Capture *cap)
184{ 185{
186 int level = cap->level;
185 for (level--; level>=0; level--) 187 for (level--; level>=0; level--)
186 if (capture[level].len == -1) return level; 188 if (cap->capture[level].len == -1) return level;
187 lua_error("invalid pattern capture"); 189 lua_error("invalid pattern capture");
188 return 0; /* to avoid warnings */ 190 return 0; /* to avoid warnings */
189} 191}
@@ -269,15 +271,15 @@ static char *matchbalance (char *s, int b, int e)
269} 271}
270 272
271 273
272static char *matchitem (char *s, char *p, int level, char **ep) 274static char *matchitem (char *s, char *p, struct Capture *cap, char **ep)
273{ 275{
274 if (*p == ESC) { 276 if (*p == ESC) {
275 p++; 277 p++;
276 if (isdigit((unsigned char)*p)) { /* capture */ 278 if (isdigit((unsigned char)*p)) { /* capture */
277 int l = check_cap(*p, level); 279 int l = check_cap(*p, cap);
278 *ep = p+1; 280 *ep = p+1;
279 if (strncmp(capture[l].init, s, capture[l].len) == 0) 281 if (strncmp(cap->capture[l].init, s, cap->capture[l].len) == 0)
280 return s+capture[l].len; 282 return s+cap->capture[l].len;
281 else return NULL; 283 else return NULL;
282 } 284 }
283 else if (*p == 'b') { /* balanced string */ 285 else if (*p == 'b') { /* balanced string */
@@ -293,58 +295,61 @@ static char *matchitem (char *s, char *p, int level, char **ep)
293} 295}
294 296
295 297
296static char *match (char *s, char *p, int level) 298static char *match (char *s, char *p, struct Capture *cap)
297{ 299{
298 init: /* using goto's to optimize tail recursion */ 300 init: /* using goto's to optimize tail recursion */
299 switch (*p) { 301 switch (*p) {
300 case '(': /* start capture */ 302 case '(': { /* start capture */
301 if (level >= MAX_CAPT) lua_error("too many captures"); 303 char *res;
302 capture[level].init = s; 304 if (cap->level >= MAX_CAPT) lua_error("too many captures");
303 capture[level].len = -1; 305 cap->capture[cap->level].init = s;
304 level++; p++; goto init; /* return match(s, p+1, level); */ 306 cap->capture[cap->level].len = -1;
307 cap->level++;
308 if ((res=match(s, p+1, cap)) == NULL) /* match failed? */
309 cap->level--; /* undo capture */
310 return res;
311 }
305 case ')': { /* end capture */ 312 case ')': { /* end capture */
306 int l = capture_to_close(level); 313 int l = capture_to_close(cap);
307 char *res; 314 char *res;
308 capture[l].len = s - capture[l].init; /* close capture */ 315 cap->capture[l].len = s - cap->capture[l].init; /* close capture */
309 if ((res = match(s, p+1, level)) == NULL) /* match failed? */ 316 if ((res = match(s, p+1, cap)) == NULL) /* match failed? */
310 capture[l].len = -1; /* undo capture */ 317 cap->capture[l].len = -1; /* undo capture */
311 return res; 318 return res;
312 } 319 }
313 case '\0': case '$': /* (possibly) end of pattern */ 320 case '\0': case '$': /* (possibly) end of pattern */
314 if (*p == 0 || (*(p+1) == 0 && *s == 0)) { 321 if (*p == 0 || (*(p+1) == 0 && *s == 0))
315 num_captures = level;
316 return s; 322 return s;
317 }
318 /* else go through */ 323 /* else go through */
319 default: { /* it is a pattern item */ 324 default: { /* it is a pattern item */
320 char *ep; /* get what is next */ 325 char *ep; /* get what is next */
321 char *s1 = matchitem(s, p, level, &ep); 326 char *s1 = matchitem(s, p, cap, &ep);
322 switch (*ep) { 327 switch (*ep) {
323 case '*': { /* repetition */ 328 case '*': { /* repetition */
324 char *res; 329 char *res;
325 if (s1 && (res = match(s1, p, level))) 330 if (s1 && (res = match(s1, p, cap)))
326 return res; 331 return res;
327 p=ep+1; goto init; /* else return match(s, ep+1, level); */ 332 p=ep+1; goto init; /* else return match(s, ep+1, cap); */
328 } 333 }
329 case '-': { /* repetition */ 334 case '-': { /* repetition */
330 char *res; 335 char *res;
331 if ((res = match(s, ep+1, level)) != 0) 336 if ((res = match(s, ep+1, cap)) != 0)
332 return res; 337 return res;
333 else if (s1) { 338 else if (s1) {
334 s = s1; 339 s = s1;
335 goto init; /* return match(s1, p, level); */ 340 goto init; /* return match(s1, p, cap); */
336 } 341 }
337 else 342 else
338 return NULL; 343 return NULL;
339 } 344 }
340 case '?': { /* optional */ 345 case '?': { /* optional */
341 char *res; 346 char *res;
342 if (s1 && (res = match(s1, ep+1, level))) 347 if (s1 && (res = match(s1, ep+1, cap)))
343 return res; 348 return res;
344 p=ep+1; goto init; /* else return match(s, ep+1, level); */ 349 p=ep+1; goto init; /* else return match(s, ep+1, cap); */
345 } 350 }
346 default: 351 default:
347 if (s1) { s=s1; p=ep; goto init; } /* return match(s1, ep, level); */ 352 if (s1) { s=s1; p=ep; goto init; } /* return match(s1, ep, cap); */
348 else return NULL; 353 else return NULL;
349 } 354 }
350 } 355 }
@@ -370,11 +375,13 @@ static void str_find (void)
370 int anchor = (*p == '^') ? (p++, 1) : 0; 375 int anchor = (*p == '^') ? (p++, 1) : 0;
371 char *s1=s+init; 376 char *s1=s+init;
372 do { 377 do {
378 struct Capture cap;
373 char *res; 379 char *res;
374 if ((res=match(s1, p, 0)) != NULL) { 380 cap.level = 0;
381 if ((res=match(s1, p, &cap)) != NULL) {
375 lua_pushnumber(s1-s+1); /* start */ 382 lua_pushnumber(s1-s+1); /* start */
376 lua_pushnumber(res-s); /* end */ 383 lua_pushnumber(res-s); /* end */
377 push_captures(); 384 push_captures(&cap);
378 return; 385 return;
379 } 386 }
380 } while (*s1++ && !anchor); 387 } while (*s1++ && !anchor);
@@ -382,7 +389,7 @@ static void str_find (void)
382} 389}
383 390
384 391
385static void add_s (lua_Object newp) 392static void add_s (lua_Object newp, struct Capture *cap)
386{ 393{
387 if (lua_isstring(newp)) { 394 if (lua_isstring(newp)) {
388 char *news = lua_getstring(newp); 395 char *news = lua_getstring(newp);
@@ -390,8 +397,8 @@ static void add_s (lua_Object newp)
390 if (*news != ESC || !isdigit((unsigned char)*++news)) 397 if (*news != ESC || !isdigit((unsigned char)*++news))
391 luaI_addchar(*news++); 398 luaI_addchar(*news++);
392 else { 399 else {
393 int l = check_cap(*news++, num_captures); 400 int l = check_cap(*news++, cap);
394 addnchar(capture[l].init, capture[l].len); 401 addnchar(cap->capture[l].init, cap->capture[l].len);
395 } 402 }
396 } 403 }
397 } 404 }
@@ -400,7 +407,7 @@ static void add_s (lua_Object newp)
400 struct lbuff oldbuff; 407 struct lbuff oldbuff;
401 int status; 408 int status;
402 lua_beginblock(); 409 lua_beginblock();
403 push_captures(); 410 push_captures(cap);
404 /* function may use lbuffer, so save it and create a luaM_new one */ 411 /* function may use lbuffer, so save it and create a luaM_new one */
405 oldbuff = lbuffer; 412 oldbuff = lbuffer;
406 lbuffer.b = NULL; lbuffer.max = lbuffer.size = 0; 413 lbuffer.b = NULL; lbuffer.max = lbuffer.size = 0;
@@ -428,10 +435,13 @@ static void str_gsub (void)
428 int n = 0; 435 int n = 0;
429 luaI_emptybuff(); 436 luaI_emptybuff();
430 while (n < max_s) { 437 while (n < max_s) {
431 char *e = match(src, p, 0); 438 struct Capture cap;
439 char *e;
440 cap.level = 0;
441 e = match(src, p, &cap);
432 if (e) { 442 if (e) {
433 n++; 443 n++;
434 add_s(newp); 444 add_s(newp, &cap);
435 } 445 }
436 if (e && e>src) /* non empty match? */ 446 if (e && e>src) /* non empty match? */
437 src = e; /* skip it */ 447 src = e; /* skip it */
@@ -471,11 +481,13 @@ static void str_format (void)
471 luaI_addchar(*strfrmt++); /* %% */ 481 luaI_addchar(*strfrmt++); /* %% */
472 else { /* format item */ 482 else { /* format item */
473 char form[MAX_FORMAT]; /* store the format ('%...') */ 483 char form[MAX_FORMAT]; /* store the format ('%...') */
484 struct Capture cap;
474 char *buff; 485 char *buff;
475 char *initf = strfrmt; 486 char *initf = strfrmt;
476 form[0] = '%'; 487 form[0] = '%';
477 strfrmt = match(strfrmt, "%d?%$?[-+ #]*(%d*)%.?(%d*)", 0); 488 cap.level = 0;
478 if (capture[0].len > 3 || capture[1].len > 3) /* < 1000? */ 489 strfrmt = match(strfrmt, "%d?%$?[-+ #]*(%d*)%.?(%d*)", &cap);
490 if (cap.capture[0].len > 3 || cap.capture[1].len > 3) /* < 1000? */
479 lua_error("invalid format (width or precision too long)"); 491 lua_error("invalid format (width or precision too long)");
480 if (isdigit((unsigned char)initf[0]) && initf[1] == '$') { 492 if (isdigit((unsigned char)initf[0]) && initf[1] == '$') {
481 arg = initf[0] - '0'; 493 arg = initf[0] - '0';