summaryrefslogtreecommitdiff
path: root/src/lstrlib.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lstrlib.c')
-rw-r--r--src/lstrlib.c62
1 files changed, 38 insertions, 24 deletions
diff --git a/src/lstrlib.c b/src/lstrlib.c
index a9c002fb..4929a27c 100644
--- a/src/lstrlib.c
+++ b/src/lstrlib.c
@@ -1,5 +1,5 @@
/*
-** $Id: lstrlib.c,v 1.109 2004/12/01 15:46:06 roberto Exp $
+** $Id: lstrlib.c,v 1.115 2005/05/17 19:49:15 roberto Exp $
** Standard library for string operations and pattern-matching
** See Copyright Notice in lua.h
*/
@@ -172,11 +172,11 @@ typedef struct MatchState {
struct {
const char *init;
ptrdiff_t len;
- } capture[MAX_CAPTURES];
+ } capture[LUA_MAXCAPTURES];
} MatchState;
-#define ESC '%'
+#define L_ESC '%'
#define SPECIALS "^$*+?.([%-"
@@ -198,17 +198,17 @@ static int capture_to_close (MatchState *ms) {
static const char *classend (MatchState *ms, const char *p) {
switch (*p++) {
- case ESC: {
+ case L_ESC: {
if (*p == '\0')
- luaL_error(ms->L, "malformed pattern (ends with `%%')");
+ luaL_error(ms->L, "malformed pattern (ends with " LUA_QL("%%") ")");
return p+1;
}
case '[': {
if (*p == '^') p++;
do { /* look for a `]' */
if (*p == '\0')
- luaL_error(ms->L, "malformed pattern (missing `]')");
- if (*(p++) == ESC && *p != '\0')
+ luaL_error(ms->L, "malformed pattern (missing " LUA_QL("]") ")");
+ if (*(p++) == L_ESC && *p != '\0')
p++; /* skip escapes (e.g. `%]') */
} while (*p != ']');
return p+1;
@@ -246,7 +246,7 @@ static int matchbracketclass (int c, const char *p, const char *ec) {
p++; /* skip the `^' */
}
while (++p < ec) {
- if (*p == ESC) {
+ if (*p == L_ESC) {
p++;
if (match_class(c, uchar(*p)))
return sig;
@@ -265,7 +265,7 @@ static int matchbracketclass (int c, const char *p, const char *ec) {
static int singlematch (int c, const char *p, const char *ep) {
switch (*p) {
case '.': return 1; /* matches any char */
- case ESC: return match_class(c, uchar(*(p+1)));
+ case L_ESC: return match_class(c, uchar(*(p+1)));
case '[': return matchbracketclass(c, p, ep-1);
default: return (uchar(*p) == c);
}
@@ -327,7 +327,7 @@ static const char *start_capture (MatchState *ms, const char *s,
const char *p, int what) {
const char *res;
int level = ms->level;
- if (level >= MAX_CAPTURES) luaL_error(ms->L, "too many captures");
+ if (level >= LUA_MAXCAPTURES) luaL_error(ms->L, "too many captures");
ms->capture[level].init = s;
ms->capture[level].len = what;
ms->level = level+1;
@@ -371,7 +371,7 @@ static const char *match (MatchState *ms, const char *s, const char *p) {
case ')': { /* end capture */
return end_capture(ms, s, p+1);
}
- case ESC: {
+ case L_ESC: {
switch (*(p+1)) {
case 'b': { /* balanced string? */
s = matchbalance(ms, s, p+2);
@@ -382,7 +382,8 @@ static const char *match (MatchState *ms, const char *s, const char *p) {
const char *ep; char previous;
p += 2;
if (*p != '[')
- luaL_error(ms->L, "missing `[' after `%%f' in pattern");
+ 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) ||
@@ -525,8 +526,8 @@ static int str_find (lua_State *L) {
static int gfind_aux (lua_State *L) {
MatchState ms;
- const char *s = lua_tostring(L, lua_upvalueindex(1));
- size_t ls = lua_strlen(L, lua_upvalueindex(1));
+ size_t ls;
+ const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls);
const char *p = lua_tostring(L, lua_upvalueindex(2));
const char *src;
ms.L = L;
@@ -563,11 +564,11 @@ static void add_s (MatchState *ms, luaL_Buffer *b,
const char *s, const char *e) {
lua_State *L = ms->L;
if (lua_isstring(L, 3)) {
- const char *news = lua_tostring(L, 3);
- size_t l = lua_strlen(L, 3);
+ size_t l;
+ const char *news = lua_tolstring(L, 3, &l);
size_t i;
for (i=0; i<l; i++) {
- if (news[i] != ESC)
+ if (news[i] != L_ESC)
luaL_putchar(b, news[i]);
else {
i++; /* skip ESC */
@@ -682,7 +683,7 @@ static const char *scanformat (lua_State *L, const char *strfrmt,
luaL_error(L, "invalid format (width or precision too long)");
if (p-strfrmt+2 > MAX_FORMAT) /* +2 to include `%' and the specifier */
luaL_error(L, "invalid format (too long)");
- form[0] = ESC;
+ form[0] = L_ESC;
strncpy(form+1, strfrmt, p-strfrmt+1);
form[p-strfrmt+2] = 0;
return p;
@@ -697,16 +698,14 @@ static int str_format (lua_State *L) {
luaL_Buffer b;
luaL_buffinit(L, &b);
while (strfrmt < strfrmt_end) {
- if (*strfrmt != ESC)
+ if (*strfrmt != L_ESC)
luaL_putchar(&b, *strfrmt++);
- else if (*++strfrmt == ESC)
+ else if (*++strfrmt == L_ESC)
luaL_putchar(&b, *strfrmt++); /* %% */
else { /* format item */
char form[MAX_FORMAT]; /* to store the format (`%...') */
char buff[MAX_ITEM]; /* to store the formatted item */
int hasprecision = 0;
- if (isdigit(uchar(*strfrmt)) && *(strfrmt+1) == '$')
- return luaL_error(L, "obsolete option (d$) to `format'");
arg++;
strfrmt = scanformat(L, strfrmt, form, &hasprecision);
switch (*strfrmt++) {
@@ -725,7 +724,7 @@ static int str_format (lua_State *L) {
}
case 'q': {
addquoted(L, &b, arg);
- continue; /* skip the `addsize' at the end */
+ continue; /* skip the 'addsize' at the end */
}
case 's': {
size_t l;
@@ -743,7 +742,7 @@ static int str_format (lua_State *L) {
}
}
default: { /* also treat cases `pnLlh' */
- return luaL_error(L, "invalid option to `format'");
+ return luaL_error(L, "invalid option to " LUA_QL("format"));
}
}
luaL_addlstring(&b, buff, strlen(buff));
@@ -772,11 +771,26 @@ static const luaL_reg strlib[] = {
};
+static void createmetatable (lua_State *L) {
+ lua_newtable(L); /* create metatable for strings */
+ lua_pushliteral(L, ""); /* dummy string */
+ lua_pushvalue(L, -2);
+ lua_setmetatable(L, -2); /* set string metatable */
+ lua_pop(L, 1); /* pop dummy string */
+ lua_pushvalue(L, -2); /* string library... */
+ lua_setfield(L, -2, "__index"); /* ...is the __index metamethod */
+ lua_getfield(L, -2, "len");
+ lua_setfield(L, -2, "__siz");
+ lua_pop(L, 1); /* pop metatable */
+}
+
+
/*
** Open string library
*/
LUALIB_API int luaopen_string (lua_State *L) {
luaL_openlib(L, LUA_STRLIBNAME, strlib, 0);
+ createmetatable(L);
return 1;
}