From 82d09fbf0dbd5aee890f033b25b09dc48ce58a48 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Mon, 15 Dec 1997 15:58:49 -0200 Subject: new structure for closures, without static variables. --- lstrlib.c | 112 ++++++++++++++++++++++++++++++++++---------------------------- 1 file 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 @@ /* -** $Id: lstrlib.c,v 1.2 1997/11/26 18:53:45 roberto Exp roberto $ +** $Id: lstrlib.c,v 1.3 1997/12/09 13:35:19 roberto Exp roberto $ ** Standard library for strings and pattern-matching ** See Copyright Notice in lua.h */ @@ -145,45 +145,47 @@ static void str_ascii (void) #define MAX_CAPT 9 -static struct { - char *init; - int len; /* -1 signals unfinished capture */ -} capture[MAX_CAPT]; - -static int num_captures; /* only valid after a sucessful call to match */ +struct Capture { + struct { + char *init; + int len; /* -1 signals unfinished capture */ + } capture[MAX_CAPT]; + int level; /* total number of captures (finished or unfinished) */ +}; #define ESC '%' #define SPECIALS "^$*?.([%-" -static void push_captures (void) +static void push_captures (struct Capture *cap) { int i; - for (i=0; ilevel; i++) { + int l = cap->capture[i].len; char *buff = openspace(l+1); if (l == -1) lua_error("unfinished capture"); - strncpy(buff, capture[i].init, l); + strncpy(buff, cap->capture[i].init, l); buff[l] = 0; lua_pushstring(buff); } } -static int check_cap (int l, int level) +static int check_cap (int l, struct Capture *cap) { l -= '1'; - if (!(0 <= l && l < level && capture[l].len != -1)) + if (!(0 <= l && l < cap->level && cap->capture[l].len != -1)) lua_error("invalid capture index"); return l; } -static int capture_to_close (int level) +static int capture_to_close (struct Capture *cap) { + int level = cap->level; for (level--; level>=0; level--) - if (capture[level].len == -1) return level; + if (cap->capture[level].len == -1) return level; lua_error("invalid pattern capture"); return 0; /* to avoid warnings */ } @@ -269,15 +271,15 @@ static char *matchbalance (char *s, int b, int e) } -static char *matchitem (char *s, char *p, int level, char **ep) +static char *matchitem (char *s, char *p, struct Capture *cap, char **ep) { if (*p == ESC) { p++; if (isdigit((unsigned char)*p)) { /* capture */ - int l = check_cap(*p, level); + int l = check_cap(*p, cap); *ep = p+1; - if (strncmp(capture[l].init, s, capture[l].len) == 0) - return s+capture[l].len; + if (strncmp(cap->capture[l].init, s, cap->capture[l].len) == 0) + return s+cap->capture[l].len; else return NULL; } else if (*p == 'b') { /* balanced string */ @@ -293,58 +295,61 @@ static char *matchitem (char *s, char *p, int level, char **ep) } -static char *match (char *s, char *p, int level) +static char *match (char *s, char *p, struct Capture *cap) { init: /* using goto's to optimize tail recursion */ switch (*p) { - case '(': /* start capture */ - if (level >= MAX_CAPT) lua_error("too many captures"); - capture[level].init = s; - capture[level].len = -1; - level++; p++; goto init; /* return match(s, p+1, level); */ + case '(': { /* start capture */ + char *res; + if (cap->level >= MAX_CAPT) lua_error("too many captures"); + cap->capture[cap->level].init = s; + cap->capture[cap->level].len = -1; + cap->level++; + if ((res=match(s, p+1, cap)) == NULL) /* match failed? */ + cap->level--; /* undo capture */ + return res; + } case ')': { /* end capture */ - int l = capture_to_close(level); + int l = capture_to_close(cap); char *res; - capture[l].len = s - capture[l].init; /* close capture */ - if ((res = match(s, p+1, level)) == NULL) /* match failed? */ - capture[l].len = -1; /* undo capture */ + cap->capture[l].len = s - cap->capture[l].init; /* close capture */ + if ((res = match(s, p+1, cap)) == NULL) /* match failed? */ + cap->capture[l].len = -1; /* undo capture */ return res; } case '\0': case '$': /* (possibly) end of pattern */ - if (*p == 0 || (*(p+1) == 0 && *s == 0)) { - num_captures = level; + if (*p == 0 || (*(p+1) == 0 && *s == 0)) return s; - } /* else go through */ default: { /* it is a pattern item */ char *ep; /* get what is next */ - char *s1 = matchitem(s, p, level, &ep); + char *s1 = matchitem(s, p, cap, &ep); switch (*ep) { case '*': { /* repetition */ char *res; - if (s1 && (res = match(s1, p, level))) + if (s1 && (res = match(s1, p, cap))) return res; - p=ep+1; goto init; /* else return match(s, ep+1, level); */ + p=ep+1; goto init; /* else return match(s, ep+1, cap); */ } case '-': { /* repetition */ char *res; - if ((res = match(s, ep+1, level)) != 0) + if ((res = match(s, ep+1, cap)) != 0) return res; else if (s1) { s = s1; - goto init; /* return match(s1, p, level); */ + goto init; /* return match(s1, p, cap); */ } else return NULL; } case '?': { /* optional */ char *res; - if (s1 && (res = match(s1, ep+1, level))) + if (s1 && (res = match(s1, ep+1, cap))) return res; - p=ep+1; goto init; /* else return match(s, ep+1, level); */ + p=ep+1; goto init; /* else return match(s, ep+1, cap); */ } default: - if (s1) { s=s1; p=ep; goto init; } /* return match(s1, ep, level); */ + if (s1) { s=s1; p=ep; goto init; } /* return match(s1, ep, cap); */ else return NULL; } } @@ -370,11 +375,13 @@ static void str_find (void) int anchor = (*p == '^') ? (p++, 1) : 0; char *s1=s+init; do { + struct Capture cap; char *res; - if ((res=match(s1, p, 0)) != NULL) { + cap.level = 0; + if ((res=match(s1, p, &cap)) != NULL) { lua_pushnumber(s1-s+1); /* start */ lua_pushnumber(res-s); /* end */ - push_captures(); + push_captures(&cap); return; } } while (*s1++ && !anchor); @@ -382,7 +389,7 @@ static void str_find (void) } -static void add_s (lua_Object newp) +static void add_s (lua_Object newp, struct Capture *cap) { if (lua_isstring(newp)) { char *news = lua_getstring(newp); @@ -390,8 +397,8 @@ static void add_s (lua_Object newp) if (*news != ESC || !isdigit((unsigned char)*++news)) luaI_addchar(*news++); else { - int l = check_cap(*news++, num_captures); - addnchar(capture[l].init, capture[l].len); + int l = check_cap(*news++, cap); + addnchar(cap->capture[l].init, cap->capture[l].len); } } } @@ -400,7 +407,7 @@ static void add_s (lua_Object newp) struct lbuff oldbuff; int status; lua_beginblock(); - push_captures(); + push_captures(cap); /* function may use lbuffer, so save it and create a luaM_new one */ oldbuff = lbuffer; lbuffer.b = NULL; lbuffer.max = lbuffer.size = 0; @@ -428,10 +435,13 @@ static void str_gsub (void) int n = 0; luaI_emptybuff(); while (n < max_s) { - char *e = match(src, p, 0); + struct Capture cap; + char *e; + cap.level = 0; + e = match(src, p, &cap); if (e) { n++; - add_s(newp); + add_s(newp, &cap); } if (e && e>src) /* non empty match? */ src = e; /* skip it */ @@ -471,11 +481,13 @@ static void str_format (void) luaI_addchar(*strfrmt++); /* %% */ else { /* format item */ char form[MAX_FORMAT]; /* store the format ('%...') */ + struct Capture cap; char *buff; char *initf = strfrmt; form[0] = '%'; - strfrmt = match(strfrmt, "%d?%$?[-+ #]*(%d*)%.?(%d*)", 0); - if (capture[0].len > 3 || capture[1].len > 3) /* < 1000? */ + cap.level = 0; + strfrmt = match(strfrmt, "%d?%$?[-+ #]*(%d*)%.?(%d*)", &cap); + if (cap.capture[0].len > 3 || cap.capture[1].len > 3) /* < 1000? */ lua_error("invalid format (width or precision too long)"); if (isdigit((unsigned char)initf[0]) && initf[1] == '$') { arg = initf[0] - '0'; -- cgit v1.2.3-55-g6feb