static void add_value (MatchState *ms, luaL_Buffer *b, const char *s, const char *e) { lua_State *L = ms->L; 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); n = push_captures(ms, s, e); lua_call(L, n, 1); break; } case LUA_TTABLE: { push_onecapture(ms, 0, s, e); lua_gettable(L, 3); break; } default: { luaL_argerror(L, 3, "string/function/table expected"); 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_addvalue(b); /* add result to accumulator */ }
static void add_s (MatchState *ms, luaL_Buffer *b, const lua_WChar *s, const lua_WChar *e) { lua_State *L = ms->L; if (lua_iswstring(L, 3)) { const lua_WChar *news = lua_towstring(L, 3); size_t l = lua_strlen(L, 3); size_t i; for (i=0; i<l; i++) { if (news[i] != ESC) luaL_putwchar(b, news[i]); else { i++; /* skip ESC */ if (!iswdigit(news[i])) luaL_putwchar(b, news[i]); else { int level = check_capture(ms, news[i]); push_onecapture(ms, level); luaL_addvalue(b); /* add capture to accumulated result */ } } } } else { /* is a function */ int n; lua_pushvalue(L, 3); n = push_captures(ms, s, e); lua_call(L, n, 1); if (lua_iswstring(L, -1)) luaL_addvalue(b); /* add return to accumulated result */ else lua_pop(L, 1); /* function result is not a string: pop it */ } }
static void add_s (MatchState *ms, luaL_Buffer *b, const char *s, const char *e) { size_t l, i; lua_State *L = ms->L; const char *news = lua_tolstring(L, 3, &l); for (i = 0; i < l; i++) { if (news[i] != L_ESC) luaL_addchar(b, news[i]); else { i++; /* skip ESC */ if (!isdigit(uchar(news[i]))) { if (news[i] != L_ESC) luaL_error(L, "invalid use of '%c' in replacement string", L_ESC); luaL_addchar(b, news[i]); } else if (news[i] == '0') luaL_addlstring(b, s, e - s); else { push_onecapture(ms, news[i] - '1', s, e); luaL_tolstring(L, -1, NULL); /* if number, convert it to string */ lua_remove(L, -2); /* remove original value */ luaL_addvalue(b); /* add capture to accumulated result */ } } } }
static void add_value (MatchState *ms, luaL_Buffer *b, const char *s, const char *e, int tr, int table) { lua_State *L = ms->L; switch (tr) { case LUA_TFUNCTION: { int n; lua_pushvalue(L, 3); if (table) n = build_result_table(ms, s, e); /* EXT */ else n = push_captures(ms, s, e); lua_call(L, n, 1); break; } case LUA_TTABLE: { push_onecapture(ms, 0, s, e); 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_addvalue(b); /* add result to accumulator */ }
/* EXT - entirely new function */ static int build_result_table(MatchState *ms, const char *s, const char *e) { lua_State *L = ms->L; int i; lua_newtable(L); /* actual results table; stack -3 (-4 with value) */ lua_newtable(L); /* match/capture starts; stack -2 (-3 with value) */ lua_newtable(L); /* match/capture ends; stack -1 (-2 with value) */ lua_pushlstring(L, s, e - s); lua_rawseti(L, -4, 0); lua_pushinteger(L, s - ms->src_init + 1); lua_rawseti(L, -3, 0); lua_pushinteger(L, e - ms->src_init); lua_rawseti(L, -2, 0); for (i = 1; i <= ms->level; i++) { ptrdiff_t cap_start = ms->capture[i-1].init - ms->src_init; push_onecapture(ms, i - 1, s, e); lua_rawseti(L, -4, i); lua_pushinteger(L, cap_start + 1); lua_rawseti(L, -3, i); if (ms->capture[i-1].len == CAP_POSITION) lua_pushinteger(L, cap_start + 1); else lua_pushinteger(L, cap_start + ms->capture[i-1].len); lua_rawseti(L, -2, i); } lua_setfield(L, -3, "endpos"); lua_setfield(L, -2, "startpos"); lua_pushlstring(L, ms->p_init, ms->p_end - ms->p_init); lua_setfield(L, -2, "pattern"); lua_pushlstring(L, ms->src_init, ms->src_end - ms->src_init); lua_setfield(L, -2, "source"); luaL_getmetatable(L, MATCHOBJNAME); lua_setmetatable(L, -2); return 1; }
static int push_captures (MatchState *ms, const char *s, const char *e) { int i; int nlevels = (ms->level == 0 && s) ? 1 : ms->level; luaL_checkstack(ms->L, nlevels, "too many captures"); for (i = 0; i < nlevels; i++) push_onecapture(ms, i, s, e); return nlevels; /* number of strings pushed */ }
static int push_captures (MatchState *ms, const lua_WChar *s, const lua_WChar *e) { int i; luaL_checkstack(ms->L, ms->level, "too many captures"); if (ms->level == 0 && s) { /* no explicit captures? */ lua_pushlwstring(ms->L, s, e-s); /* return whole match */ return 1; } else { /* return all captures */ for (i=0; i<ms->level; i++) push_onecapture(ms, i); return ms->level; /* number of strings pushed */ } }
static int push_captures(struct match_state *ms, const char *s, const char *e, struct str_find *sm, size_t nsm) { int i; int nlevels = (ms->level <= 0 && s) ? 1 : ms->level; if (nlevels > (int)nsm) nlevels = (int)nsm; for (i = 0; i < nlevels; i++) if (push_onecapture(ms, i, s, e, sm + i) == -1) break; /* number of strings pushed */ return (nlevels); }
static void add_s (MatchState *ms, const char *s, const char *e, const char *news, size_t l) { size_t i; for (i = 0; i < l; i++) { if (news[i] != L_ESC) { buffer_addchar(ms->buff, news[i]); } else { i++; /* skip ESC */ if (!isdigit(uchar(news[i]))) { buffer_addchar(ms->buff, news[i]); } else if (news[i] == '0') { buffer_addstring(ms->buff, s, e - s); } else { push_onecapture(ms, news[i] - '1', s, e); // luaL_addvalue(b); /* add capture to accumulated result */ } } } }
static void add_s (MatchState *ms, luaL_Buffer *b, const char *s, const char *e) { size_t l, i; const char *news = lua_tolstring(ms->L, 3, &l); for (i = 0; i < l; i++) { if (news[i] != L_ESC) luaL_addchar(b, news[i]); else { i++; /* skip ESC */ if (!isdigit(uchar(news[i]))) luaL_addchar(b, news[i]); else if (news[i] == '0') luaL_addlstring(b, s, e - s); else { push_onecapture(ms, news[i] - '1', s, e); luaL_addvalue(b); /* add capture to accumulated result */ } } } }