31 #define REX_VERSION "Lrexlib " VERSION
34 static void gmatch_pushsubject (lua_State *L,
TArgExec *argE);
35 static int findmatch_exec (TUserdata *ud,
TArgExec *argE);
36 static int split_exec (TUserdata *ud,
TArgExec *argE,
int offset);
37 static int gsub_exec (TUserdata *ud,
TArgExec *argE,
int offset);
38 static int gmatch_exec (TUserdata *ud,
TArgExec *argE);
39 static int compile_regex (lua_State *L,
const TArgComp *argC, TUserdata **pud);
40 static int generate_error (lua_State *L,
const TUserdata *ud,
int errcode);
42 #if LUA_VERSION_NUM == 501
43 # define ALG_ENVIRONINDEX LUA_ENVIRONINDEX
45 # define ALG_ENVIRONINDEX lua_upvalueindex(1)
49 # define ALG_CHARSIZE 1
52 #ifndef BUFFERZ_PUTREPSTRING
53 # define BUFFERZ_PUTREPSTRING bufferZ_putrepstring
57 # define ALG_GETCARGS(a,b,c)
60 #ifndef DO_NAMED_SUBPATTERNS
61 #define DO_NAMED_SUBPATTERNS(a,b,c)
65 #define METHOD_MATCH 1
67 #define METHOD_TFIND 3
70 static int OptLimit (lua_State *L,
int pos) {
71 if (lua_isnoneornil (L, pos))
72 return GSUB_UNLIMITED;
73 if (lua_isfunction (L, pos))
74 return GSUB_CONDITIONAL;
75 if (lua_isnumber (L, pos)) {
76 int a = lua_tointeger (L, pos);
79 return luaL_typerror (L, pos,
"number or function");
83 static int get_startoffset(lua_State *L,
int stackpos,
size_t len) {
84 int startoffset = (int)luaL_optinteger(L, stackpos, 1);
87 else if(startoffset < 0) {
88 startoffset += len/ALG_CHARSIZE;
92 return startoffset*ALG_CHARSIZE;
96 static TUserdata* test_ud (lua_State *L,
int pos)
99 if (lua_getmetatable(L, pos) &&
100 lua_rawequal(L, -1, ALG_ENVIRONINDEX) &&
101 (ud = (TUserdata *)lua_touserdata(L, pos)) != NULL) {
109 static TUserdata* check_ud (lua_State *L)
111 TUserdata *ud = test_ud(L, 1);
112 if (ud == NULL) luaL_typerror(L, 1, REX_TYPENAME);
117 static void check_subject (lua_State *L,
int pos,
TArgExec *argE)
120 argE->text = lua_tolstring (L, pos, &argE->textlen);
121 stype = lua_type (L, pos);
122 if (stype != LUA_TSTRING && stype != LUA_TTABLE && stype != LUA_TUSERDATA) {
123 luaL_typerror (L, pos,
"string, table or userdata");
124 }
else if (argE->text == NULL) {
126 lua_getfield (L, pos,
"topointer");
127 if (lua_type (L, -1) != LUA_TFUNCTION)
128 luaL_error (L,
"subject has no topointer method");
129 lua_pushvalue (L, pos);
131 type = lua_type (L, -1);
132 if (type != LUA_TLIGHTUSERDATA)
133 luaL_error (L,
"subject's topointer method returned %s (expected lightuserdata)",
134 lua_typename (L, type));
135 argE->text = (
const char*) lua_touserdata (L, -1);
137 #if LUA_VERSION_NUM == 501
138 if (luaL_callmeta (L, pos,
"__len")) {
139 if (lua_type (L, -1) != LUA_TNUMBER)
140 luaL_argerror (L, pos,
"subject's length is not a number");
141 argE->textlen = lua_tointeger (L, -1);
145 argE->textlen = lua_objlen (L, pos);
147 argE->textlen = luaL_len (L, pos);
152 static void check_pattern (lua_State *L,
int pos,
TArgComp *argC)
154 if (lua_isstring (L, pos)) {
155 argC->pattern = lua_tolstring (L, pos, &argC->patlen);
158 else if ((argC->ud = test_ud (L, pos)) == NULL)
159 luaL_typerror(L, pos,
"string or " REX_TYPENAME);
162 static void checkarg_new (lua_State *L,
TArgComp *argC) {
163 argC->pattern = luaL_checklstring (L, 1, &argC->patlen);
164 argC->cflags = ALG_GETCFLAGS (L, 2);
165 ALG_GETCARGS (L, 3, argC);
171 check_subject (L, 1, argE);
172 check_pattern (L, 2, argC);
174 argE->reptype = lua_type (L, 3);
175 if (argE->reptype != LUA_TSTRING && argE->reptype != LUA_TTABLE &&
176 argE->reptype != LUA_TFUNCTION) {
177 luaL_typerror (L, 3,
"string, table or function");
181 argE->maxmatch = OptLimit (L, 4);
182 argC->cflags = ALG_GETCFLAGS (L, 5);
183 argE->eflags = (int)luaL_optinteger (L, 6, ALG_EFLAGS_DFLT);
184 ALG_GETCARGS (L, 7, argC);
190 check_subject (L, 1, argE);
191 check_pattern (L, 2, argC);
192 argC->cflags = ALG_GETCFLAGS (L, 3);
193 argE->eflags = (int)luaL_optinteger (L, 4, ALG_EFLAGS_DFLT);
194 ALG_GETCARGS (L, 5, argC);
200 static void checkarg_find_func (lua_State *L,
TArgComp *argC,
TArgExec *argE) {
201 check_subject (L, 1, argE);
202 check_pattern (L, 2, argC);
203 argE->startoffset = get_startoffset (L, 3, argE->textlen);
204 argC->cflags = ALG_GETCFLAGS (L, 4);
205 argE->eflags = (int)luaL_optinteger (L, 5, ALG_EFLAGS_DFLT);
206 ALG_GETCARGS (L, 6, argC);
212 static void checkarg_gmatch_split (lua_State *L,
TArgComp *argC,
TArgExec *argE) {
213 check_subject (L, 1, argE);
214 check_pattern (L, 2, argC);
215 argC->cflags = ALG_GETCFLAGS (L, 3);
216 argE->eflags = (int)luaL_optinteger (L, 4, ALG_EFLAGS_DFLT);
217 ALG_GETCARGS (L, 5, argC);
225 static void checkarg_find_method (lua_State *L,
TArgExec *argE, TUserdata **ud) {
227 check_subject (L, 2, argE);
228 argE->startoffset = get_startoffset (L, 3, argE->textlen);
229 argE->eflags = (int)luaL_optinteger (L, 4, ALG_EFLAGS_DFLT);
233 static int algf_new (lua_State *L) {
235 checkarg_new (L, &argC);
236 return compile_regex (L, &argC, NULL);
239 static void push_substrings (lua_State *L, TUserdata *ud,
const char *text,
242 if (lua_checkstack (L, ALG_NSUB(ud)) == 0) {
244 freelist_free (freelist);
245 luaL_error (L,
"cannot add %d stack slots", ALG_NSUB(ud));
247 for (i = 1; i <= ALG_NSUB(ud); i++) {
248 ALG_PUSHSUB_OR_FALSE (L, ud, text, i);
252 static int algf_gsub (lua_State *L) {
256 int n_match = 0, n_subst = 0, st = 0, last_to = -1;
257 TBuffer BufOut, BufRep, BufTemp, *pBuf = &BufOut;
260 checkarg_gsub (L, &argC, &argE);
262 ud = (TUserdata*) argC.ud;
263 lua_pushvalue (L, 2);
265 else compile_regex (L, &argC, &ud);
266 freelist_init (&freelist);
268 if (argE.reptype == LUA_TSTRING) {
269 buffer_init (&BufRep, 256, L, &freelist);
270 BUFFERZ_PUTREPSTRING (&BufRep, argE.funcpos, ALG_NSUB(ud));
273 if (argE.maxmatch == GSUB_CONDITIONAL) {
274 buffer_init (&BufTemp, 1024, L, &freelist);
278 buffer_init (&BufOut, 1024, L, &freelist);
279 while ((argE.maxmatch < 0 || n_match < argE.maxmatch) && st <= (
int)argE.textlen) {
282 res = gsub_exec (ud, &argE, st);
283 if (ALG_NOMATCH (res)) {
286 else if (!ALG_ISMATCH (res)) {
287 freelist_free (&freelist);
288 return generate_error (L, ud, res);
290 from = ALG_BASE(st) + ALG_SUBBEG(ud,0);
291 to = ALG_BASE(st) + ALG_SUBEND(ud,0);
293 if (st < (
int)argE.textlen) {
294 buffer_addlstring (&BufOut, argE.text + st, ALG_CHARSIZE);
303 buffer_addlstring (&BufOut, argE.text + st, from - st);
309 if (argE.reptype == LUA_TSTRING) {
310 size_t iter = 0, num;
312 while (bufferZ_next (&BufRep, &iter, &num, &str)) {
314 buffer_addlstring (pBuf, str, num);
315 else if (num == 0 || ALG_SUBVALID (ud,num))
316 buffer_addlstring (pBuf, argE.text + ALG_BASE(st) + ALG_SUBBEG(ud,num), ALG_SUBLEN(ud,num));
321 else if (argE.reptype == LUA_TTABLE) {
322 if (ALG_NSUB(ud) > 0)
323 ALG_PUSHSUB_OR_FALSE (L, ud, argE.text + ALG_BASE(st), 1);
325 lua_pushlstring (L, argE.text + from, to - from);
326 lua_gettable (L, argE.funcpos);
329 else if (argE.reptype == LUA_TFUNCTION) {
331 lua_pushvalue (L, argE.funcpos);
332 if (ALG_NSUB(ud) > 0) {
333 push_substrings (L, ud, argE.text + ALG_BASE(st), &freelist);
337 lua_pushlstring (L, argE.text + from, to - from);
340 if (0 != lua_pcall (L, narg, 1, 0)) {
341 freelist_free (&freelist);
342 return lua_error (L);
346 if (argE.reptype == LUA_TTABLE || argE.reptype == LUA_TFUNCTION) {
347 if (lua_tostring (L, -1)) {
348 buffer_addvalue (pBuf, -1);
351 else if (!lua_toboolean (L, -1))
352 buffer_addlstring (pBuf, argE.text + from, to - from);
354 freelist_free (&freelist);
355 luaL_error (L,
"invalid replacement value (a %s)", luaL_typename (L, -1));
357 if (argE.maxmatch != GSUB_CONDITIONAL)
361 if (argE.maxmatch == GSUB_CONDITIONAL) {
363 lua_pushvalue (L, argE.funcpos2);
364 lua_pushinteger (L, from/ALG_CHARSIZE + 1);
365 lua_pushinteger (L, to/ALG_CHARSIZE);
366 if (argE.reptype == LUA_TSTRING)
367 buffer_pushresult (&BufTemp);
369 lua_pushvalue (L, -4);
372 if (0 != lua_pcall (L, 3, 2, 0)) {
373 freelist_free (&freelist);
377 if (lua_isstring (L, -2)) {
378 buffer_addvalue (&BufOut, -2);
381 else if (lua_toboolean (L, -2))
382 buffer_addbuffer (&BufOut, &BufTemp);
384 buffer_addlstring (&BufOut, argE.text + from, to - from);
388 if (lua_type (L, -1) == LUA_TNUMBER) {
389 int n = lua_tointeger (L, -1);
392 argE.maxmatch = n_match + n;
394 else if (lua_toboolean (L, -1))
395 argE.maxmatch = GSUB_UNLIMITED;
397 buffer_clear (&BufTemp);
400 if (argE.maxmatch != GSUB_CONDITIONAL)
404 n_subst += curr_subst;
408 else if (st < (
int)argE.textlen) {
410 buffer_addlstring (&BufOut, argE.text + st, ALG_CHARSIZE);
416 buffer_addlstring (&BufOut, argE.text + st, argE.textlen - st);
417 buffer_pushresult (&BufOut);
418 lua_pushinteger (L, n_match);
419 lua_pushinteger (L, n_subst);
420 freelist_free (&freelist);
425 static int algf_count (lua_State *L) {
429 int n_match = 0, st = 0, last_to = -1;
431 checkarg_count (L, &argC, &argE);
433 ud = (TUserdata*) argC.ud;
434 lua_pushvalue (L, 2);
436 else compile_regex (L, &argC, &ud);
438 while (st <= (
int)argE.textlen) {
440 res = gsub_exec (ud, &argE, st);
441 if (ALG_NOMATCH (res)) {
444 else if (!ALG_ISMATCH (res)) {
445 return generate_error (L, ud, res);
447 to = ALG_BASE(st) + ALG_SUBEND(ud,0);
449 if (st < (
int)argE.textlen) {
459 int from = ALG_BASE(st) + ALG_SUBBEG(ud,0);
468 else if (st < (
int)argE.textlen) {
475 lua_pushinteger (L, n_match);
480 static int finish_generic_find (lua_State *L, TUserdata *ud,
TArgExec *argE,
483 if (ALG_ISMATCH (res)) {
484 if (method == METHOD_FIND)
485 ALG_PUSHOFFSETS (L, ud, ALG_BASE(argE->startoffset), 0);
487 push_substrings (L, ud, argE->text, NULL);
488 else if (method != METHOD_FIND) {
489 ALG_PUSHSUB (L, ud, argE->text, 0);
492 return (method == METHOD_FIND) ? ALG_NSUB(ud) + 2 : ALG_NSUB(ud);
494 else if (ALG_NOMATCH (res))
495 return lua_pushnil (L), 1;
497 return generate_error (L, ud, res);
501 static int generic_find_func (lua_State *L,
int method) {
507 checkarg_find_func (L, &argC, &argE);
508 if (argE.startoffset > (
int)argE.textlen)
509 return lua_pushnil (L), 1;
512 ud = (TUserdata*) argC.ud;
513 lua_pushvalue (L, 2);
515 else compile_regex (L, &argC, &ud);
516 res = findmatch_exec (ud, &argE);
517 return finish_generic_find (L, ud, &argE, method, res);
521 static int algf_find (lua_State *L) {
522 return generic_find_func (L, METHOD_FIND);
526 static int algf_match (lua_State *L) {
527 return generic_find_func (L, METHOD_MATCH);
531 static int gmatch_iter (lua_State *L) {
534 TUserdata *ud = (TUserdata*) lua_touserdata (L, lua_upvalueindex (1));
535 argE.text = lua_tolstring (L, lua_upvalueindex (2), &argE.textlen);
536 argE.eflags = lua_tointeger (L, lua_upvalueindex (3));
537 argE.startoffset = lua_tointeger (L, lua_upvalueindex (4));
538 last_end = lua_tointeger (L, lua_upvalueindex (5));
541 if (argE.startoffset > (
int)argE.textlen)
543 res = gmatch_exec (ud, &argE);
544 if (ALG_ISMATCH (res)) {
546 if (!ALG_SUBLEN(ud,0)) {
547 if (last_end == ALG_BASE(argE.startoffset) + ALG_SUBEND(ud,0)) {
548 argE.startoffset += ALG_CHARSIZE;
553 last_end = ALG_BASE(argE.startoffset) + ALG_SUBEND(ud,0);
554 lua_pushinteger(L, last_end + incr);
555 lua_replace (L, lua_upvalueindex (4));
556 lua_pushinteger(L, last_end);
557 lua_replace (L, lua_upvalueindex (5));
560 push_substrings (L, ud, argE.text, NULL);
564 ALG_PUSHSUB (L, ud, argE.text, 0);
568 else if (ALG_NOMATCH (res))
571 return generate_error (L, ud, res);
576 static int split_iter (lua_State *L) {
577 int incr, last_end, newoffset, res;
579 TUserdata *ud = (TUserdata*) lua_touserdata (L, lua_upvalueindex (1));
580 argE.text = lua_tolstring (L, lua_upvalueindex (2), &argE.textlen);
581 argE.eflags = lua_tointeger (L, lua_upvalueindex (3));
582 argE.startoffset = lua_tointeger (L, lua_upvalueindex (4));
583 incr = lua_tointeger (L, lua_upvalueindex (5));
584 last_end = lua_tointeger (L, lua_upvalueindex (6));
590 if ((newoffset = argE.startoffset + incr) > (
int)argE.textlen)
592 res = split_exec (ud, &argE, newoffset);
593 if (ALG_ISMATCH (res)) {
594 if (!ALG_SUBLEN(ud,0)) {
595 if (last_end == ALG_BASE(argE.startoffset) + ALG_SUBEND(ud,0)) {
596 incr += ALG_CHARSIZE;
600 lua_pushinteger(L, ALG_BASE(newoffset) + ALG_SUBEND(ud,0));
601 lua_pushvalue (L, -1);
602 lua_replace (L, lua_upvalueindex (4));
603 lua_replace (L, lua_upvalueindex (6));
604 lua_pushinteger (L, ALG_SUBLEN(ud,0) ? 0 : ALG_CHARSIZE);
605 lua_replace (L, lua_upvalueindex (5));
607 lua_pushlstring (L, argE.text + argE.startoffset,
608 ALG_SUBBEG(ud,0) + ALG_BASE(newoffset) - argE.startoffset);
611 push_substrings (L, ud, argE.text + ALG_BASE(newoffset), NULL);
612 return 1 + ALG_NSUB(ud);
615 ALG_PUSHSUB (L, ud, argE.text + ALG_BASE(newoffset), 0);
619 else if (ALG_NOMATCH (res))
622 return generate_error (L, ud, res);
624 lua_pushinteger (L, -1);
625 lua_replace (L, lua_upvalueindex (5));
626 lua_pushlstring (L, argE.text+argE.startoffset, argE.textlen-argE.startoffset);
631 static int algf_gmatch (lua_State *L)
635 checkarg_gmatch_split (L, &argC, &argE);
637 lua_pushvalue (L, 2);
639 compile_regex (L, &argC, NULL);
640 gmatch_pushsubject (L, &argE);
641 lua_pushinteger (L, argE.eflags);
642 lua_pushinteger (L, 0);
643 lua_pushinteger (L, -1);
644 lua_pushcclosure (L, gmatch_iter, 5);
648 static int algf_split (lua_State *L)
652 checkarg_gmatch_split (L, &argC, &argE);
654 lua_pushvalue (L, 2);
656 compile_regex (L, &argC, NULL);
657 gmatch_pushsubject (L, &argE);
658 lua_pushinteger (L, argE.eflags);
659 lua_pushinteger (L, 0);
660 lua_pushinteger (L, 0);
661 lua_pushinteger (L, -1);
662 lua_pushcclosure (L, split_iter, 6);
667 static void push_substring_table (lua_State *L, TUserdata *ud,
const char *text) {
670 for (i = 1; i <= ALG_NSUB(ud); i++) {
671 ALG_PUSHSUB_OR_FALSE (L, ud, text, i);
672 lua_rawseti (L, -2, i);
677 static void push_offset_table (lua_State *L, TUserdata *ud,
int startoffset) {
680 for (i=1, j=1; i <= ALG_NSUB(ud); i++) {
681 if (ALG_SUBVALID (ud,i)) {
682 ALG_PUSHSTART (L, ud, startoffset, i);
683 lua_rawseti (L, -2, j++);
684 ALG_PUSHEND (L, ud, startoffset, i);
685 lua_rawseti (L, -2, j++);
688 lua_pushboolean (L, 0);
689 lua_rawseti (L, -2, j++);
690 lua_pushboolean (L, 0);
691 lua_rawseti (L, -2, j++);
697 static int generic_find_method (lua_State *L,
int method) {
702 checkarg_find_method (L, &argE, &ud);
703 if (argE.startoffset > (
int)argE.textlen)
704 return lua_pushnil(L), 1;
706 res = findmatch_exec (ud, &argE);
707 if (ALG_ISMATCH (res)) {
710 ALG_PUSHOFFSETS (L, ud, ALG_BASE(argE.startoffset), 0);
711 push_offset_table (L, ud, ALG_BASE(argE.startoffset));
712 DO_NAMED_SUBPATTERNS (L, ud, argE.text);
715 ALG_PUSHOFFSETS (L, ud, ALG_BASE(argE.startoffset), 0);
716 push_substring_table (L, ud, argE.text);
717 DO_NAMED_SUBPATTERNS (L, ud, argE.text);
721 return finish_generic_find (L, ud, &argE, method, res);
725 else if (ALG_NOMATCH (res))
726 return lua_pushnil (L), 1;
728 return generate_error(L, ud, res);
732 static int algm_find (lua_State *L) {
733 return generic_find_method (L, METHOD_FIND);
735 static int algm_match (lua_State *L) {
736 return generic_find_method (L, METHOD_MATCH);
738 static int algm_tfind (lua_State *L) {
739 return generic_find_method (L, METHOD_TFIND);
741 static int algm_exec (lua_State *L) {
742 return generic_find_method (L, METHOD_EXEC);
745 static void alg_register (lua_State *L,
const luaL_Reg *r_methods,
746 const luaL_Reg *r_functions,
const char *name) {
748 #if LUA_VERSION_NUM == 501
750 lua_pushvalue (L, -1);
751 lua_replace (L, LUA_ENVIRONINDEX);
752 luaL_register (L, NULL, r_methods);
754 luaL_newmetatable(L, REX_TYPENAME);
755 lua_pushvalue(L, -1);
756 luaL_setfuncs (L, r_methods, 1);
758 lua_pushvalue(L, -1);
759 lua_setfield(L, -2,
"__index");
762 lua_createtable(L, 0, 8);
763 #if LUA_VERSION_NUM == 501
764 luaL_register (L, NULL, r_functions);
766 lua_pushvalue(L, -2);
767 luaL_setfuncs (L, r_functions, 1);
769 #ifdef REX_CREATEGLOBALVAR
770 lua_pushvalue(L, -1);
771 lua_setglobal(L, REX_LIBNAME);
773 lua_pushfstring (L, REX_VERSION
" (for %s)", name);
774 lua_setfield (L, -2,
"_VERSION");
775 #ifndef REX_NOEMBEDDEDTEST
776 lua_pushcfunction (L, newmembuffer);
777 lua_setfield (L, -2,
"_newmembuffer");