From bfd0179042b0b02fb88748d54e56e7e208bb117f Mon Sep 17 00:00:00 2001 From: Marcin Bukat Date: Wed, 2 Apr 2014 20:46:06 +0200 Subject: Revert "Update lua plugin to 5.2.3" FILE typedef to *void needs more work to not break sim and application builds. I checked only a few random native builds unfortunately. Sorry for inconvenience. --- apps/plugins/lua/lstrlib.c | 580 +++++++++++++++++---------------------------- 1 file changed, 215 insertions(+), 365 deletions(-) (limited to 'apps/plugins/lua/lstrlib.c') diff --git a/apps/plugins/lua/lstrlib.c b/apps/plugins/lua/lstrlib.c index 04cc2f60d6..3d6103692f 100644 --- a/apps/plugins/lua/lstrlib.c +++ b/apps/plugins/lua/lstrlib.c @@ -1,5 +1,5 @@ /* -** $Id: lstrlib.c,v 1.178.1.1 2013/04/12 18:48:47 roberto Exp $ +** $Id: lstrlib.c,v 1.132.1.4 2008/07/11 17:27:21 roberto Exp $ ** Standard library for string operations and pattern-matching ** See Copyright Notice in lua.h */ @@ -20,58 +20,47 @@ #include "lualib.h" -/* -** maximum number of captures that a pattern can do during -** pattern-matching. This limit is arbitrary. -*/ -#if !defined(LUA_MAXCAPTURES) -#define LUA_MAXCAPTURES 32 -#endif - - /* macro to `unsign' a character */ -#define uchar(c) ((unsigned char)(c)) +#define uchar(c) ((unsigned char)(c)) static int str_len (lua_State *L) { size_t l; luaL_checklstring(L, 1, &l); - lua_pushinteger(L, (lua_Integer)l); + lua_pushinteger(L, l); return 1; } -/* translate a relative string position: negative means back from end */ -static size_t posrelat (ptrdiff_t pos, size_t len) { - if (pos >= 0) return (size_t)pos; - else if (0u - (size_t)pos > len) return 0; - else return len - ((size_t)-pos) + 1; +static ptrdiff_t posrelat (ptrdiff_t pos, size_t len) { + /* relative string position: negative means back from end */ + if (pos < 0) pos += (ptrdiff_t)len + 1; + return (pos >= 0) ? pos : 0; } static int str_sub (lua_State *L) { size_t l; const char *s = luaL_checklstring(L, 1, &l); - size_t start = posrelat(luaL_checkinteger(L, 2), l); - size_t end = posrelat(luaL_optinteger(L, 3, -1), l); + ptrdiff_t start = posrelat(luaL_checkinteger(L, 2), l); + ptrdiff_t end = posrelat(luaL_optinteger(L, 3, -1), l); if (start < 1) start = 1; - if (end > l) end = l; + if (end > (ptrdiff_t)l) end = (ptrdiff_t)l; if (start <= end) - lua_pushlstring(L, s + start - 1, end - start + 1); + lua_pushlstring(L, s+start-1, end-start+1); else lua_pushliteral(L, ""); return 1; } static int str_reverse (lua_State *L) { - size_t l, i; + size_t l; luaL_Buffer b; const char *s = luaL_checklstring(L, 1, &l); - char *p = luaL_buffinitsize(L, &b, l); - for (i = 0; i < l; i++) - p[i] = s[l - i - 1]; - luaL_pushresultsize(&b, l); + luaL_buffinit(L, &b); + while (l--) luaL_addchar(&b, s[l]); + luaL_pushresult(&b); return 1; } @@ -81,10 +70,10 @@ static int str_lower (lua_State *L) { size_t i; luaL_Buffer b; const char *s = luaL_checklstring(L, 1, &l); - char *p = luaL_buffinitsize(L, &b, l); + luaL_buffinit(L, &b); for (i=0; i> 1) - static int str_rep (lua_State *L) { - size_t l, lsep; + size_t l; + luaL_Buffer b; const char *s = luaL_checklstring(L, 1, &l); int n = luaL_checkint(L, 2); - const char *sep = luaL_optlstring(L, 3, "", &lsep); - if (n <= 0) lua_pushliteral(L, ""); - else if (l + lsep < l || l + lsep >= MAXSIZE / n) /* may overflow? */ - return luaL_error(L, "resulting string too large"); - else { - size_t totallen = n * l + (n - 1) * lsep; - luaL_Buffer b; - char *p = luaL_buffinitsize(L, &b, totallen); - while (n-- > 1) { /* first n-1 copies (followed by separator) */ - memcpy(p, s, l * sizeof(char)); p += l; - if (lsep > 0) { /* avoid empty 'memcpy' (may be expensive) */ - memcpy(p, sep, lsep * sizeof(char)); p += lsep; - } - } - memcpy(p, s, l * sizeof(char)); /* last copy (not followed by separator) */ - luaL_pushresultsize(&b, totallen); - } + luaL_buffinit(L, &b); + while (n-- > 0) + luaL_addlstring(&b, s, l); + luaL_pushresult(&b); return 1; } @@ -133,15 +106,15 @@ static int str_rep (lua_State *L) { static int str_byte (lua_State *L) { size_t l; const char *s = luaL_checklstring(L, 1, &l); - size_t posi = posrelat(luaL_optinteger(L, 2, 1), l); - size_t pose = posrelat(luaL_optinteger(L, 3, posi), l); + ptrdiff_t posi = posrelat(luaL_optinteger(L, 2, 1), l); + ptrdiff_t pose = posrelat(luaL_optinteger(L, 3, posi), l); int n, i; - if (posi < 1) posi = 1; - if (pose > l) pose = l; + if (posi <= 0) posi = 1; + if ((size_t)pose > l) pose = l; if (posi > pose) return 0; /* empty interval; return no values */ n = (int)(pose - posi + 1); - if (posi + n <= pose) /* (size_t -> int) overflow? */ - return luaL_error(L, "string slice too long"); + if (posi + n <= pose) /* overflow? */ + luaL_error(L, "string slice too long"); luaL_checkstack(L, n, "string slice too long"); for (i=0; i= ms->level || ms->capture[l].len == CAP_UNFINISHED) - return luaL_error(ms->L, "invalid capture index %%%d", l + 1); + return luaL_error(ms->L, "invalid capture index"); return l; } @@ -242,16 +202,16 @@ static int capture_to_close (MatchState *ms) { static const char *classend (MatchState *ms, const char *p) { switch (*p++) { case L_ESC: { - if (p == ms->p_end) + if (*p == '\0') luaL_error(ms->L, "malformed pattern (ends with " LUA_QL("%%") ")"); return p+1; } case '[': { if (*p == '^') p++; do { /* look for a `]' */ - if (p == ms->p_end) + if (*p == '\0') luaL_error(ms->L, "malformed pattern (missing " LUA_QL("]") ")"); - if (*(p++) == L_ESC && p < ms->p_end) + if (*(p++) == L_ESC && *p != '\0') p++; /* skip escapes (e.g. `%]') */ } while (*p != ']'); return p+1; @@ -269,14 +229,13 @@ static int match_class (int c, int cl) { case 'a' : res = isalpha(c); break; case 'c' : res = iscntrl(c); break; case 'd' : res = isdigit(c); break; - case 'g' : res = isgraph(c); break; case 'l' : res = islower(c); break; case 'p' : res = ispunct(c); break; case 's' : res = isspace(c); break; case 'u' : res = isupper(c); break; case 'w' : res = isalnum(c); break; case 'x' : res = isxdigit(c); break; - case 'z' : res = (c == 0); break; /* deprecated option */ + case 'z' : res = (c == 0); break; default: return (cl == c); } return (islower(cl) ? res : !res); @@ -306,27 +265,23 @@ static int matchbracketclass (int c, const char *p, const char *ec) { } -static int singlematch (MatchState *ms, const char *s, const char *p, - const char *ep) { - if (s >= ms->src_end) - return 0; - else { - int c = uchar(*s); - switch (*p) { - case '.': return 1; /* matches any char */ - case L_ESC: return match_class(c, uchar(*(p+1))); - case '[': return matchbracketclass(c, p, ep-1); - default: return (uchar(*p) == c); - } +static int singlematch (int c, const char *p, const char *ep) { + switch (*p) { + case '.': return 1; /* matches any char */ + case L_ESC: return match_class(c, uchar(*(p+1))); + case '[': return matchbracketclass(c, p, ep-1); + default: return (uchar(*p) == c); } } +static const char *match (MatchState *ms, const char *s, const char *p); + + static const char *matchbalance (MatchState *ms, const char *s, const char *p) { - if (p >= ms->p_end - 1) - luaL_error(ms->L, "malformed pattern " - "(missing arguments to " LUA_QL("%%b") ")"); + if (*p == 0 || *(p+1) == 0) + luaL_error(ms->L, "unbalanced pattern"); if (*s != *p) return NULL; else { int b = *p; @@ -346,7 +301,7 @@ static const char *matchbalance (MatchState *ms, const char *s, static const char *max_expand (MatchState *ms, const char *s, const char *p, const char *ep) { ptrdiff_t i = 0; /* counts maximum expand for item */ - while (singlematch(ms, s + i, p, ep)) + while ((s+i)src_end && singlematch(uchar(*(s+i)), p, ep)) i++; /* keeps trying to match with the maximum repetitions */ while (i>=0) { @@ -364,7 +319,7 @@ static const char *min_expand (MatchState *ms, const char *s, const char *res = match(ms, s, ep+1); if (res != NULL) return res; - else if (singlematch(ms, s, p, ep)) + else if (ssrc_end && singlematch(uchar(*s), p, ep)) s++; /* try with one more repetition */ else return NULL; } @@ -408,105 +363,80 @@ static const char *match_capture (MatchState *ms, const char *s, int l) { static const char *match (MatchState *ms, const char *s, const char *p) { - if (ms->matchdepth-- == 0) - luaL_error(ms->L, "pattern too complex"); init: /* using goto's to optimize tail recursion */ - if (p != ms->p_end) { /* end of pattern? */ - switch (*p) { - case '(': { /* start capture */ - if (*(p + 1) == ')') /* position capture? */ - s = start_capture(ms, s, p + 2, CAP_POSITION); - else - s = start_capture(ms, s, p + 1, CAP_UNFINISHED); - break; - } - case ')': { /* end capture */ - s = end_capture(ms, s, p + 1); - break; - } - case '$': { - if ((p + 1) != ms->p_end) /* is the `$' the last char in pattern? */ - goto dflt; /* no; go to default */ - s = (s == ms->src_end) ? s : NULL; /* check end of string */ - break; - } - case L_ESC: { /* escaped sequences not in the format class[*+?-]? */ - switch (*(p + 1)) { - case 'b': { /* balanced string? */ - s = matchbalance(ms, s, p + 2); - if (s != NULL) { - p += 4; goto init; /* return match(ms, s, p + 4); */ - } /* else fail (s == NULL) */ - break; - } - case 'f': { /* frontier? */ - const char *ep; char previous; - p += 2; - if (*p != '[') - luaL_error(ms->L, "missing " LUA_QL("[") " after " - LUA_QL("%%f") " in pattern"); - ep = classend(ms, p); /* points to what is next */ - previous = (s == ms->src_init) ? '\0' : *(s - 1); - if (!matchbracketclass(uchar(previous), p, ep - 1) && - matchbracketclass(uchar(*s), p, ep - 1)) { - p = ep; goto init; /* return match(ms, s, ep); */ - } - s = NULL; /* match failed */ - break; - } - case '0': case '1': case '2': case '3': - case '4': case '5': case '6': case '7': - case '8': case '9': { /* capture results (%0-%9)? */ - s = match_capture(ms, s, uchar(*(p + 1))); - if (s != NULL) { - p += 2; goto init; /* return match(ms, s, p + 2) */ - } - break; + switch (*p) { + case '(': { /* start capture */ + if (*(p+1) == ')') /* position capture? */ + return start_capture(ms, s, p+2, CAP_POSITION); + else + return start_capture(ms, s, p+1, CAP_UNFINISHED); + } + case ')': { /* end capture */ + return end_capture(ms, s, p+1); + } + case L_ESC: { + switch (*(p+1)) { + case 'b': { /* balanced string? */ + s = matchbalance(ms, s, p+2); + if (s == NULL) return NULL; + p+=4; goto init; /* else return match(ms, s, p+4); */ + } + case 'f': { /* frontier? */ + const char *ep; char previous; + p += 2; + if (*p != '[') + luaL_error(ms->L, "missing " LUA_QL("[") " after " + LUA_QL("%%f") " in pattern"); + ep = classend(ms, p); /* points to what is next */ + previous = (s == ms->src_init) ? '\0' : *(s-1); + if (matchbracketclass(uchar(previous), p, ep-1) || + !matchbracketclass(uchar(*s), p, ep-1)) return NULL; + p=ep; goto init; /* else return match(ms, s, ep); */ + } + default: { + if (isdigit(uchar(*(p+1)))) { /* capture results (%0-%9)? */ + s = match_capture(ms, s, uchar(*(p+1))); + if (s == NULL) return NULL; + p+=2; goto init; /* else return match(ms, s, p+2) */ } - default: goto dflt; + goto dflt; /* case default */ } - break; } - default: dflt: { /* pattern class plus optional suffix */ - const char *ep = classend(ms, p); /* points to optional suffix */ - /* does not match at least once? */ - if (!singlematch(ms, s, p, ep)) { - if (*ep == '*' || *ep == '?' || *ep == '-') { /* accept empty? */ - p = ep + 1; goto init; /* return match(ms, s, ep + 1); */ - } - else /* '+' or no suffix */ - s = NULL; /* fail */ + } + case '\0': { /* end of pattern */ + return s; /* match succeeded */ + } + case '$': { + if (*(p+1) == '\0') /* is the `$' the last char in pattern? */ + return (s == ms->src_end) ? s : NULL; /* check end of string */ + else goto dflt; + } + default: dflt: { /* it is a pattern item */ + const char *ep = classend(ms, p); /* points to what is next */ + int m = ssrc_end && singlematch(uchar(*s), p, ep); + switch (*ep) { + case '?': { /* optional */ + const char *res; + if (m && ((res=match(ms, s+1, ep+1)) != NULL)) + return res; + p=ep+1; goto init; /* else return match(ms, s, ep+1); */ } - else { /* matched once */ - switch (*ep) { /* handle optional suffix */ - case '?': { /* optional */ - const char *res; - if ((res = match(ms, s + 1, ep + 1)) != NULL) - s = res; - else { - p = ep + 1; goto init; /* else return match(ms, s, ep + 1); */ - } - break; - } - case '+': /* 1 or more repetitions */ - s++; /* 1 match already done */ - /* go through */ - case '*': /* 0 or more repetitions */ - s = max_expand(ms, s, p, ep); - break; - case '-': /* 0 or more repetitions (minimum) */ - s = min_expand(ms, s, p, ep); - break; - default: /* no suffix */ - s++; p = ep; goto init; /* return match(ms, s + 1, ep); */ - } + case '*': { /* 0 or more repetitions */ + return max_expand(ms, s, p, ep); + } + case '+': { /* 1 or more repetitions */ + return (m ? max_expand(ms, s+1, p, ep) : NULL); + } + case '-': { /* 0 or more repetitions (minimum) */ + return min_expand(ms, s, p, ep); + } + default: { + if (!m) return NULL; + s++; p=ep; goto init; /* else return match(ms, s+1, ep); */ } - break; } } } - ms->matchdepth++; - return s; } @@ -562,58 +492,37 @@ static int push_captures (MatchState *ms, const char *s, const char *e) { } -/* check whether pattern has no special characters */ -static int nospecials (const char *p, size_t l) { - size_t upto = 0; - do { - if (strpbrk(p + upto, SPECIALS)) - return 0; /* pattern has a special character */ - upto += strlen(p + upto) + 1; /* may have more after \0 */ - } while (upto <= l); - return 1; /* no special chars found */ -} - - static int str_find_aux (lua_State *L, int find) { - size_t ls, lp; - const char *s = luaL_checklstring(L, 1, &ls); - const char *p = luaL_checklstring(L, 2, &lp); - size_t init = posrelat(luaL_optinteger(L, 3, 1), ls); - if (init < 1) init = 1; - else if (init > ls + 1) { /* start after string's end? */ - lua_pushnil(L); /* cannot find anything */ - return 1; - } - /* explicit request or no special characters? */ - if (find && (lua_toboolean(L, 4) || nospecials(p, lp))) { + size_t l1, l2; + const char *s = luaL_checklstring(L, 1, &l1); + const char *p = luaL_checklstring(L, 2, &l2); + ptrdiff_t init = posrelat(luaL_optinteger(L, 3, 1), l1) - 1; + if (init < 0) init = 0; + else if ((size_t)(init) > l1) init = (ptrdiff_t)l1; + if (find && (lua_toboolean(L, 4) || /* explicit request? */ + strpbrk(p, SPECIALS) == NULL)) { /* or no special characters? */ /* do a plain search */ - const char *s2 = lmemfind(s + init - 1, ls - init + 1, p, lp); + const char *s2 = lmemfind(s+init, l1-init, p, l2); if (s2) { - lua_pushinteger(L, s2 - s + 1); - lua_pushinteger(L, s2 - s + lp); + lua_pushinteger(L, s2-s+1); + lua_pushinteger(L, s2-s+l2); return 2; } } else { MatchState ms; - const char *s1 = s + init - 1; - int anchor = (*p == '^'); - if (anchor) { - p++; lp--; /* skip anchor character */ - } + int anchor = (*p == '^') ? (p++, 1) : 0; + const char *s1=s+init; ms.L = L; - ms.matchdepth = MAXCCALLS; ms.src_init = s; - ms.src_end = s + ls; - ms.p_end = p + lp; + ms.src_end = s+l1; do { const char *res; ms.level = 0; - lua_assert(ms.matchdepth == MAXCCALLS); if ((res=match(&ms, s1, p)) != NULL) { if (find) { - lua_pushinteger(L, s1 - s + 1); /* start */ - lua_pushinteger(L, res - s); /* end */ + lua_pushinteger(L, s1-s+1); /* start */ + lua_pushinteger(L, res-s); /* end */ return push_captures(&ms, NULL, 0) + 2; } else @@ -638,21 +547,18 @@ static int str_match (lua_State *L) { static int gmatch_aux (lua_State *L) { MatchState ms; - size_t ls, lp; + size_t ls; const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls); - const char *p = lua_tolstring(L, lua_upvalueindex(2), &lp); + const char *p = lua_tostring(L, lua_upvalueindex(2)); const char *src; ms.L = L; - ms.matchdepth = MAXCCALLS; ms.src_init = s; ms.src_end = s+ls; - ms.p_end = p + lp; for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3)); src <= ms.src_end; src++) { const char *e; ms.level = 0; - lua_assert(ms.matchdepth == MAXCCALLS); if ((e = match(&ms, src, p)) != NULL) { lua_Integer newstart = e-s; if (e == src) newstart++; /* empty match? go at least one position */ @@ -675,6 +581,12 @@ static int gmatch (lua_State *L) { } +static int gfind_nodef (lua_State *L) { + return luaL_error(L, LUA_QL("string.gfind") " was renamed to " + LUA_QL("string.gmatch")); +} + + static void add_s (MatchState *ms, luaL_Buffer *b, const char *s, const char *e) { size_t l, i; @@ -684,12 +596,8 @@ static void add_s (MatchState *ms, luaL_Buffer *b, const char *s, luaL_addchar(b, news[i]); else { i++; /* skip ESC */ - if (!isdigit(uchar(news[i]))) { - if (news[i] != L_ESC) - luaL_error(ms->L, "invalid use of " LUA_QL("%c") - " in replacement string", L_ESC); + if (!isdigit(uchar(news[i]))) luaL_addchar(b, news[i]); - } else if (news[i] == '0') luaL_addlstring(b, s, e - s); else { @@ -702,9 +610,14 @@ static void add_s (MatchState *ms, luaL_Buffer *b, const char *s, static void add_value (MatchState *ms, luaL_Buffer *b, const char *s, - const char *e, int tr) { + const char *e) { lua_State *L = ms->L; - switch (tr) { + switch (lua_type(L, 3)) { + case LUA_TNUMBER: + case LUA_TSTRING: { + add_s(ms, b, s, e); + return; + } case LUA_TFUNCTION: { int n; lua_pushvalue(L, 3); @@ -717,51 +630,41 @@ static void add_value (MatchState *ms, luaL_Buffer *b, const char *s, lua_gettable(L, 3); break; } - default: { /* LUA_TNUMBER or LUA_TSTRING */ - add_s(ms, b, s, e); - return; - } } if (!lua_toboolean(L, -1)) { /* nil or false? */ lua_pop(L, 1); lua_pushlstring(L, s, e - s); /* keep original text */ } else if (!lua_isstring(L, -1)) - luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1)); + luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1)); luaL_addvalue(b); /* add result to accumulator */ } static int str_gsub (lua_State *L) { - size_t srcl, lp; + size_t srcl; const char *src = luaL_checklstring(L, 1, &srcl); - const char *p = luaL_checklstring(L, 2, &lp); - int tr = lua_type(L, 3); - size_t max_s = luaL_optinteger(L, 4, srcl+1); - int anchor = (*p == '^'); - size_t n = 0; + const char *p = luaL_checkstring(L, 2); + int tr = lua_type(L, 3); + int max_s = luaL_optint(L, 4, srcl+1); + int anchor = (*p == '^') ? (p++, 1) : 0; + int n = 0; MatchState ms; luaL_Buffer b; luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING || tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3, "string/function/table expected"); luaL_buffinit(L, &b); - if (anchor) { - p++; lp--; /* skip anchor character */ - } ms.L = L; - ms.matchdepth = MAXCCALLS; ms.src_init = src; ms.src_end = src+srcl; - ms.p_end = p + lp; while (n < max_s) { const char *e; ms.level = 0; - lua_assert(ms.matchdepth == MAXCCALLS); e = match(&ms, src, p); if (e) { n++; - add_value(&ms, &b, src, e, tr); + add_value(&ms, &b, src, e); } if (e && e>src) /* non empty match? */ src = e; /* skip it */ @@ -779,46 +682,6 @@ static int str_gsub (lua_State *L) { /* }====================================================== */ - -/* -** {====================================================== -** STRING FORMAT -** ======================================================= -*/ - -/* -** LUA_INTFRMLEN is the length modifier for integer conversions in -** 'string.format'; LUA_INTFRM_T is the integer type corresponding to -** the previous length -*/ -#if !defined(LUA_INTFRMLEN) /* { */ -#if defined(LUA_USE_LONGLONG) - -#define LUA_INTFRMLEN "ll" -#define LUA_INTFRM_T long long - -#else - -#define LUA_INTFRMLEN "l" -#define LUA_INTFRM_T long - -#endif -#endif /* } */ - - -/* -** LUA_FLTFRMLEN is the length modifier for float conversions in -** 'string.format'; LUA_FLTFRM_T is the float type corresponding to -** the previous length -*/ -#if !defined(LUA_FLTFRMLEN) - -#define LUA_FLTFRMLEN "" -#define LUA_FLTFRM_T double - -#endif - - /* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */ #define MAX_ITEM 512 /* valid flags in a format specification */ @@ -835,20 +698,25 @@ static void addquoted (lua_State *L, luaL_Buffer *b, int arg) { const char *s = luaL_checklstring(L, arg, &l); luaL_addchar(b, '"'); while (l--) { - if (*s == '"' || *s == '\\' || *s == '\n') { - luaL_addchar(b, '\\'); - luaL_addchar(b, *s); - } - else if (*s == '\0' || iscntrl(uchar(*s))) { - char buff[10]; - if (!isdigit(uchar(*(s+1)))) - snprintf(buff, sizeof(buff), "\\%d", (int)uchar(*s)); - else - snprintf(buff, sizeof(buff), "\\%03d", (int)uchar(*s)); - luaL_addstring(b, buff); + switch (*s) { + case '"': case '\\': case '\n': { + luaL_addchar(b, '\\'); + luaL_addchar(b, *s); + break; + } + case '\r': { + luaL_addlstring(b, "\\r", 2); + break; + } + case '\0': { + luaL_addlstring(b, "\\000", 4); + break; + } + default: { + luaL_addchar(b, *s); + break; + } } - else - luaL_addchar(b, *s); s++; } luaL_addchar(b, '"'); @@ -857,7 +725,7 @@ static void addquoted (lua_State *L, luaL_Buffer *b, int arg) { static const char *scanformat (lua_State *L, const char *strfrmt, char *form) { const char *p = strfrmt; while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */ - if ((size_t)(p - strfrmt) >= sizeof(FLAGS)/sizeof(char)) + if ((size_t)(p - strfrmt) >= sizeof(FLAGS)) luaL_error(L, "invalid format (repeated flags)"); if (isdigit(uchar(*p))) p++; /* skip width */ if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ @@ -869,28 +737,23 @@ static const char *scanformat (lua_State *L, const char *strfrmt, char *form) { if (isdigit(uchar(*p))) luaL_error(L, "invalid format (width or precision too long)"); *(form++) = '%'; - memcpy(form, strfrmt, (p - strfrmt + 1) * sizeof(char)); + strncpy(form, strfrmt, p - strfrmt + 1); form += p - strfrmt + 1; *form = '\0'; return p; } -/* -** add length modifier into formats -*/ -static void addlenmod (char *form, const char *lenmod) { +static void addintlen (char *form) { size_t l = strlen(form); - size_t lm = strlen(lenmod); char spec = form[l - 1]; - strcpy(form + l - 1, lenmod); - form[l + lm - 1] = spec; - form[l + lm] = '\0'; + strcpy(form + l - 1, LUA_INTFRMLEN); + form[l + sizeof(LUA_INTFRMLEN) - 2] = spec; + form[l + sizeof(LUA_INTFRMLEN) - 1] = '\0'; } static int str_format (lua_State *L) { - int top = lua_gettop(L); int arg = 1; size_t sfl; const char *strfrmt = luaL_checklstring(L, arg, &sfl); @@ -904,61 +767,45 @@ static int str_format (lua_State *L) { luaL_addchar(&b, *strfrmt++); /* %% */ else { /* format item */ char form[MAX_FORMAT]; /* to store the format (`%...') */ - char *buff = luaL_prepbuffsize(&b, MAX_ITEM); /* to put formatted item */ - int nb = 0; /* number of bytes in added item */ - if (++arg > top) - luaL_argerror(L, arg, "no value"); + char buff[MAX_ITEM]; /* to store the formatted item */ + arg++; strfrmt = scanformat(L, strfrmt, form); switch (*strfrmt++) { case 'c': { - nb = snprintf(buff, MAX_ITEM, form, luaL_checkint(L, arg)); + snprintf(buff, MAX_ITEM, form, (int)luaL_checknumber(L, arg)); break; } - case 'd': case 'i': { - lua_Number n = luaL_checknumber(L, arg); - LUA_INTFRM_T ni = (LUA_INTFRM_T)n; - lua_Number diff = n - (lua_Number)ni; - luaL_argcheck(L, -1 < diff && diff < 1, arg, - "not a number in proper range"); - addlenmod(form, LUA_INTFRMLEN); - nb = snprintf(buff, MAX_ITEM, form, ni); + case 'd': case 'i': { + addintlen(form); + snprintf(buff, MAX_ITEM, form, (LUA_INTFRM_T)luaL_checknumber(L, arg)); break; } - case 'o': case 'u': case 'x': case 'X': { - lua_Number n = luaL_checknumber(L, arg); - unsigned LUA_INTFRM_T ni = (unsigned LUA_INTFRM_T)n; - lua_Number diff = n - (lua_Number)ni; - luaL_argcheck(L, -1 < diff && diff < 1, arg, - "not a non-negative number in proper range"); - addlenmod(form, LUA_INTFRMLEN); - nb = snprintf(buff, MAX_ITEM, form, ni); + case 'o': case 'u': case 'x': case 'X': { + addintlen(form); + snprintf(buff, MAX_ITEM, form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg)); break; } - case 'e': case 'E': case 'f': -#if defined(LUA_USE_AFORMAT) - case 'a': case 'A': -#endif + case 'e': case 'E': case 'f': case 'g': case 'G': { - addlenmod(form, LUA_FLTFRMLEN); - nb = snprintf(buff, MAX_ITEM, form, (LUA_FLTFRM_T)luaL_checknumber(L, arg)); + snprintf(buff, MAX_ITEM, form, (double)luaL_checknumber(L, arg)); break; } case 'q': { addquoted(L, &b, arg); - break; + continue; /* skip the 'addsize' at the end */ } case 's': { size_t l; - const char *s = luaL_tolstring(L, arg, &l); + const char *s = luaL_checklstring(L, arg, &l); if (!strchr(form, '.') && l >= 100) { /* no precision and string is too long to be formatted; keep original string */ + lua_pushvalue(L, arg); luaL_addvalue(&b); - break; + continue; /* skip the `addsize' at the end */ } else { - nb = snprintf(buff, MAX_ITEM, form, s); - lua_pop(L, 1); /* remove result from 'luaL_tolstring' */ + snprintf(buff, MAX_ITEM, form, s); break; } } @@ -967,15 +814,13 @@ static int str_format (lua_State *L) { LUA_QL("format"), *(strfrmt - 1)); } } - luaL_addsize(&b, nb); + luaL_addlstring(&b, buff, strlen(buff)); } } luaL_pushresult(&b); return 1; } -/* }====================================================== */ - static const luaL_Reg strlib[] = { {"byte", str_byte}, @@ -983,6 +828,7 @@ static const luaL_Reg strlib[] = { {"dump", str_dump}, {"find", str_find}, {"format", str_format}, + {"gfind", gfind_nodef}, {"gmatch", gmatch}, {"gsub", str_gsub}, {"len", str_len}, @@ -997,13 +843,13 @@ static const luaL_Reg strlib[] = { static void createmetatable (lua_State *L) { - lua_createtable(L, 0, 1); /* table to be metatable for strings */ + lua_createtable(L, 0, 1); /* create metatable for strings */ lua_pushliteral(L, ""); /* dummy string */ - lua_pushvalue(L, -2); /* copy table */ - lua_setmetatable(L, -2); /* set table as metatable for strings */ + lua_pushvalue(L, -2); + lua_setmetatable(L, -2); /* set string metatable */ lua_pop(L, 1); /* pop dummy string */ - lua_pushvalue(L, -2); /* get string library */ - lua_setfield(L, -2, "__index"); /* metatable.__index = string */ + lua_pushvalue(L, -2); /* string library... */ + lua_setfield(L, -2, "__index"); /* ...is the __index metamethod */ lua_pop(L, 1); /* pop metatable */ } @@ -1011,8 +857,12 @@ static void createmetatable (lua_State *L) { /* ** Open string library */ -LUAMOD_API int luaopen_string (lua_State *L) { - luaL_newlib(L, strlib); +LUALIB_API int luaopen_string (lua_State *L) { + luaL_register(L, LUA_STRLIBNAME, strlib); +#if defined(LUA_COMPAT_GFIND) + lua_getfield(L, -1, "gmatch"); + lua_setfield(L, -2, "gfind"); +#endif createmetatable(L); return 1; } -- cgit v1.2.3