14 #ifdef LREXLIB_WIRESHARK 15 # define WSLUA_TYPEOF_FIELD "__typeof" 16 # define REX_CREATEGLOBALVAR 19 #define REX_VERSION "Lrexlib " VERSION 22 static void gmatch_pushsubject (lua_State *L,
TArgExec *argE);
23 static int findmatch_exec (TUserdata *ud,
TArgExec *argE);
24 static int split_exec (TUserdata *ud,
TArgExec *argE,
int offset);
25 static int compile_regex (lua_State *L,
const TArgComp *argC, TUserdata **pud);
26 static int generate_error (lua_State *L,
const TUserdata *ud,
int errcode);
28 #if LUA_VERSION_NUM == 501 29 # define ALG_ENVIRONINDEX LUA_ENVIRONINDEX 31 # define ALG_ENVIRONINDEX lua_upvalueindex(1) 35 # define ALG_CHARSIZE 1 38 #ifndef BUFFERZ_PUTREPSTRING 39 # define BUFFERZ_PUTREPSTRING bufferZ_putrepstring 43 # define ALG_GETCARGS(a,b,c) 47 # define ALG_GETEFLAGS(L,idx) ((int) luaL_optinteger (L, idx, ALG_EFLAGS_DFLT)) 50 #ifndef DO_NAMED_SUBPATTERNS 51 #define DO_NAMED_SUBPATTERNS(a,b,c) 67 #define SET_RETRY(a,b) (a=b) 68 static int gsub_exec (TUserdata *ud,
TArgExec *argE,
int offset,
int retry);
69 static int gmatch_exec (TUserdata *ud,
TArgExec *argE,
int retry);
70 #define GSUB_EXEC gsub_exec 71 #define GMATCH_EXEC gmatch_exec 73 #define SET_RETRY(a,b) ((void)a) 74 static int gsub_exec (TUserdata *ud,
TArgExec *argE,
int offset);
75 static int gmatch_exec (TUserdata *ud,
TArgExec *argE);
76 #define GSUB_EXEC(a,b,c,d) gsub_exec(a,b,c) 77 #define GMATCH_EXEC(a,b,c) gmatch_exec(a,b) 82 #define METHOD_MATCH 1 84 #define METHOD_TFIND 3 87 static int OptLimit (lua_State *L,
int pos) {
88 if (lua_isnoneornil (L, pos))
89 return GSUB_UNLIMITED;
90 if (lua_isfunction (L, pos))
91 return GSUB_CONDITIONAL;
92 if (lua_isnumber (L, pos)) {
93 int a = (int) lua_tointeger (L, pos);
96 return luaL_typerror (L, pos,
"number or function");
100 static int get_startoffset(lua_State *L,
int stackpos,
size_t len) {
101 int startoffset = (int)luaL_optinteger(L, stackpos, 1);
104 else if(startoffset < 0) {
105 startoffset += (int)(len/ALG_CHARSIZE);
109 return startoffset*ALG_CHARSIZE;
113 static TUserdata* test_ud (lua_State *L,
int pos)
116 if (lua_getmetatable(L, pos) &&
117 lua_rawequal(L, -1, ALG_ENVIRONINDEX) &&
118 (ud = (TUserdata *)lua_touserdata(L, pos)) != NULL) {
126 static TUserdata* check_ud (lua_State *L)
128 TUserdata *ud = test_ud(L, 1);
129 if (ud == NULL) luaL_typerror(L, 1, REX_TYPENAME);
134 static void check_subject (lua_State *L,
int pos,
TArgExec *argE)
137 argE->text = lua_tolstring (L, pos, &argE->textlen);
138 stype = lua_type (L, pos);
139 if (stype != LUA_TSTRING && stype != LUA_TTABLE && stype != LUA_TUSERDATA) {
140 luaL_typerror (L, pos,
"string, table or userdata");
141 }
else if (argE->text == NULL) {
143 lua_getfield (L, pos,
"topointer");
144 if (lua_type (L, -1) != LUA_TFUNCTION)
145 luaL_error (L,
"subject has no topointer method");
146 lua_pushvalue (L, pos);
148 type = lua_type (L, -1);
149 if (type != LUA_TLIGHTUSERDATA)
150 luaL_error (L,
"subject's topointer method returned %s (expected lightuserdata)",
151 lua_typename (L, type));
152 argE->text = (
const char *)lua_touserdata (L, -1);
154 #if LUA_VERSION_NUM == 501 159 type = lua_type (L, -1);
160 if (type != LUA_TNUMBER)
161 luaL_error (L,
"subject's length is %s (expected number)",
162 lua_typename (L, type));
163 argE->textlen = lua_tointeger (L, -1);
168 static void check_pattern (lua_State *L,
int pos,
TArgComp *argC)
170 if (lua_isstring (L, pos)) {
171 argC->pattern = lua_tolstring (L, pos, &argC->patlen);
174 else if ((argC->ud = test_ud (L, pos)) == NULL)
175 luaL_typerror(L, pos,
"string or "REX_TYPENAME);
178 static void checkarg_new (lua_State *L,
TArgComp *argC) {
179 argC->pattern = luaL_checklstring (L, 1, &argC->patlen);
180 argC->cflags = ALG_GETCFLAGS (L, 2);
181 ALG_GETCARGS (L, 3, argC);
187 check_subject (L, 1, argE);
188 check_pattern (L, 2, argC);
190 argE->reptype = lua_type (L, 3);
191 if (argE->reptype != LUA_TSTRING && argE->reptype != LUA_TTABLE &&
192 argE->reptype != LUA_TFUNCTION && argE->reptype != LUA_TNIL &&
193 (argE->reptype != LUA_TBOOLEAN ||
194 (argE->reptype == LUA_TBOOLEAN && lua_toboolean (L, 3)))) {
195 luaL_typerror (L, 3,
"string, table, function, false or nil");
199 argE->maxmatch = OptLimit (L, 4);
200 argC->cflags = ALG_GETCFLAGS (L, 5);
201 argE->eflags = ALG_GETEFLAGS (L, 6);
202 ALG_GETCARGS (L, 7, argC);
208 static void checkarg_find_func (lua_State *L,
TArgComp *argC,
TArgExec *argE) {
209 check_subject (L, 1, argE);
210 check_pattern (L, 2, argC);
211 argE->startoffset = get_startoffset (L, 3, argE->textlen);
212 argC->cflags = ALG_GETCFLAGS (L, 4);
213 argE->eflags = ALG_GETEFLAGS (L, 5);
214 ALG_GETCARGS (L, 6, argC);
220 static void checkarg_gmatch_split (lua_State *L,
TArgComp *argC,
TArgExec *argE) {
221 check_subject (L, 1, argE);
222 check_pattern (L, 2, argC);
223 argC->cflags = ALG_GETCFLAGS (L, 3);
224 argE->eflags = ALG_GETEFLAGS (L, 4);
225 ALG_GETCARGS (L, 5, argC);
233 static void checkarg_find_method (lua_State *L,
TArgExec *argE, TUserdata **ud) {
235 check_subject (L, 2, argE);
236 argE->startoffset = get_startoffset (L, 3, argE->textlen);
237 argE->eflags = ALG_GETEFLAGS (L, 4);
241 static int algf_new (lua_State *L) {
243 checkarg_new (L, &argC);
244 return compile_regex (L, &argC, NULL);
247 static void push_substrings (lua_State *L, TUserdata *ud,
const char *text,
250 if (lua_checkstack (L, ALG_NSUB(ud)) == 0) {
252 freelist_free (freelist);
253 luaL_error (L,
"cannot add %d stack slots", ALG_NSUB(ud));
255 for (i = 1; i <= ALG_NSUB(ud); i++) {
256 ALG_PUSHSUB_OR_FALSE (L, ud, text, i);
260 static int algf_gsub (lua_State *L) {
264 int n_match = 0, n_subst = 0, st = 0, retry;
265 TBuffer BufOut, BufRep, BufTemp, *pBuf = &BufOut;
268 checkarg_gsub (L, &argC, &argE);
270 ud = (TUserdata*) argC.ud;
271 lua_pushvalue (L, 2);
273 else compile_regex (L, &argC, &ud);
274 freelist_init (&freelist);
276 if (argE.reptype == LUA_TSTRING) {
277 buffer_init (&BufRep, 256, L, &freelist);
278 BUFFERZ_PUTREPSTRING (&BufRep, argE.funcpos, ALG_NSUB(ud));
281 if (argE.maxmatch == GSUB_CONDITIONAL) {
282 buffer_init (&BufTemp, 1024, L, &freelist);
286 buffer_init (&BufOut, 1024, L, &freelist);
287 SET_RETRY (retry, 0);
288 while ((argE.maxmatch < 0 || n_match < argE.maxmatch) && st <= (
int)argE.textlen) {
291 res = GSUB_EXEC (ud, &argE, st, retry);
292 if (ALG_NOMATCH (res)) {
295 if (st < (
int)argE.textlen) {
296 buffer_addlstring (&BufOut, argE.text + st, ALG_CHARSIZE);
305 else if (!ALG_ISMATCH (res)) {
306 freelist_free (&freelist);
307 return generate_error (L, ud, res);
310 from = ALG_BASE(st) + ALG_SUBBEG(ud,0);
311 to = ALG_BASE(st) + ALG_SUBEND(ud,0);
313 buffer_addlstring (&BufOut, argE.text + st, from - st);
319 if (argE.reptype == LUA_TSTRING) {
320 size_t iter = 0, num;
322 while (bufferZ_next (&BufRep, &iter, &num, &str)) {
324 buffer_addlstring (pBuf, str, num);
325 else if (num == 0 || ALG_SUBVALID (ud,(
int)num))
326 buffer_addlstring (pBuf, argE.text + ALG_BASE(st) + ALG_SUBBEG(ud,(
int)num), ALG_SUBLEN(ud,(
int)num));
331 else if (argE.reptype == LUA_TTABLE) {
332 if (ALG_NSUB(ud) > 0)
333 ALG_PUSHSUB_OR_FALSE (L, ud, argE.text + ALG_BASE(st), 1)
335 lua_pushlstring (L, argE.text + from, to - from);
336 lua_gettable (L, argE.funcpos);
339 else if (argE.reptype == LUA_TFUNCTION) {
341 lua_pushvalue (L, argE.funcpos);
342 if (ALG_NSUB(ud) > 0) {
343 push_substrings (L, ud, argE.text + ALG_BASE(st), &freelist);
347 lua_pushlstring (L, argE.text + from, to - from);
350 if (0 != lua_pcall (L, narg, 1, 0)) {
351 freelist_free (&freelist);
352 return lua_error (L);
356 else if (argE.reptype == LUA_TNIL || argE.reptype == LUA_TBOOLEAN) {
357 buffer_addlstring (pBuf, argE.text + from, to - from);
360 if (argE.reptype == LUA_TTABLE || argE.reptype == LUA_TFUNCTION) {
361 if (lua_tostring (L, -1)) {
362 buffer_addvalue (pBuf, -1);
365 else if (!lua_toboolean (L, -1))
366 buffer_addlstring (pBuf, argE.text + from, to - from);
368 freelist_free (&freelist);
369 luaL_error (L,
"invalid replacement value (a %s)", luaL_typename (L, -1));
371 if (argE.maxmatch != GSUB_CONDITIONAL)
375 if (argE.maxmatch == GSUB_CONDITIONAL) {
377 lua_pushvalue (L, argE.funcpos2);
378 lua_pushinteger (L, from/ALG_CHARSIZE + 1);
379 lua_pushinteger (L, to/ALG_CHARSIZE);
380 if (argE.reptype == LUA_TSTRING)
381 buffer_pushresult (&BufTemp);
383 lua_pushvalue (L, -4);
386 if (0 != lua_pcall (L, 3, 2, 0)) {
387 freelist_free (&freelist);
391 if (lua_isstring (L, -2)) {
392 buffer_addvalue (&BufOut, -2);
395 else if (lua_toboolean (L, -2))
396 buffer_addbuffer (&BufOut, &BufTemp);
398 buffer_addlstring (&BufOut, argE.text + from, to - from);
402 if (lua_type (L, -1) == LUA_TNUMBER) {
403 int n = (int) lua_tointeger (L, -1);
406 argE.maxmatch = n_match + n;
408 else if (lua_toboolean (L, -1))
409 argE.maxmatch = GSUB_UNLIMITED;
411 buffer_clear (&BufTemp);
414 if (argE.maxmatch != GSUB_CONDITIONAL)
418 n_subst += curr_subst;
421 SET_RETRY (retry, 0);
423 else if (st < (
int)argE.textlen) {
428 buffer_addlstring (&BufOut, argE.text + st, ALG_CHARSIZE);
435 buffer_addlstring (&BufOut, argE.text + st, argE.textlen - st);
436 buffer_pushresult (&BufOut);
437 lua_pushinteger (L, n_match);
438 lua_pushinteger (L, n_subst);
439 freelist_free (&freelist);
444 static int finish_generic_find (lua_State *L, TUserdata *ud,
TArgExec *argE,
447 if (ALG_ISMATCH (res)) {
448 if (method == METHOD_FIND)
449 ALG_PUSHOFFSETS (L, ud, ALG_BASE(argE->startoffset), 0);
451 push_substrings (L, ud, argE->text, NULL);
452 else if (method != METHOD_FIND) {
453 ALG_PUSHSUB (L, ud, argE->text, 0);
456 return (method == METHOD_FIND) ? ALG_NSUB(ud) + 2 : ALG_NSUB(ud);
458 else if (ALG_NOMATCH (res)) {
463 return generate_error (L, ud, res);
467 static int generic_find_func (lua_State *L,
int method) {
473 checkarg_find_func (L, &argC, &argE);
474 if (argE.startoffset > (
int)argE.textlen) {
480 ud = (TUserdata*) argC.ud;
481 lua_pushvalue (L, 2);
483 else compile_regex (L, &argC, &ud);
484 res = findmatch_exec (ud, &argE);
485 return finish_generic_find (L, ud, &argE, method, res);
489 static int algf_find (lua_State *L) {
490 return generic_find_func (L, METHOD_FIND);
494 static int algf_match (lua_State *L) {
495 return generic_find_func (L, METHOD_MATCH);
499 static int gmatch_iter (lua_State *L) {
502 TUserdata *ud = (TUserdata*) lua_touserdata (L, lua_upvalueindex (1));
503 argE.text = lua_tolstring (L, lua_upvalueindex (2), &argE.textlen);
504 argE.eflags = (int) lua_tointeger (L, lua_upvalueindex (3));
505 argE.startoffset = (int) lua_tointeger (L, lua_upvalueindex (4));
507 retry = (int) lua_tointeger (L, lua_upvalueindex (5));
510 if (argE.startoffset > (
int)argE.textlen)
514 int res = GMATCH_EXEC (ud, &argE, retry);
515 if (ALG_ISMATCH (res)) {
517 if (ALG_SUBLEN(ud,0)) {
518 SET_RETRY (retry, 0);
522 SET_RETRY (retry, 1);
527 lua_pushinteger(L, ALG_BASE(argE.startoffset) + incr + ALG_SUBEND(ud,0));
528 lua_replace (L, lua_upvalueindex (4));
530 lua_pushinteger (L, retry);
531 lua_replace (L, lua_upvalueindex (5));
535 push_substrings (L, ud, argE.text, NULL);
539 ALG_PUSHSUB (L, ud, argE.text, 0);
543 else if (ALG_NOMATCH (res)) {
546 if (argE.startoffset < (
int)argE.textlen) {
548 SET_RETRY (retry, 0);
556 return generate_error (L, ud, res);
561 static int split_iter (lua_State *L) {
562 int incr, newoffset, res;
564 TUserdata *ud = (TUserdata*) lua_touserdata (L, lua_upvalueindex (1));
565 argE.text = lua_tolstring (L, lua_upvalueindex (2), &argE.textlen);
566 argE.eflags = (int) lua_tointeger (L, lua_upvalueindex (3));
567 argE.startoffset = (int) lua_tointeger (L, lua_upvalueindex (4));
568 incr = (int) lua_tointeger (L, lua_upvalueindex (5));
570 if (argE.startoffset > (
int)argE.textlen)
573 if ((newoffset = argE.startoffset + incr) > (int)argE.textlen)
576 res = split_exec (ud, &argE, newoffset);
577 if (ALG_ISMATCH (res)) {
578 lua_pushinteger(L, ALG_BASE(newoffset) + ALG_SUBEND(ud,0));
579 lua_replace (L, lua_upvalueindex (4));
580 lua_pushinteger (L, ALG_SUBLEN(ud,0) ? 0 : ALG_CHARSIZE);
581 lua_replace (L, lua_upvalueindex (5));
583 lua_pushlstring (L, argE.text + argE.startoffset,
584 ALG_SUBBEG(ud,0) + ALG_BASE(newoffset) - argE.startoffset);
587 push_substrings (L, ud, argE.text + ALG_BASE(newoffset), NULL);
588 return 1 + ALG_NSUB(ud);
591 ALG_PUSHSUB (L, ud, argE.text + ALG_BASE(newoffset), 0);
595 else if (ALG_NOMATCH (res))
598 return generate_error (L, ud, res);
601 lua_pushinteger (L, argE.textlen + 1);
602 lua_replace (L, lua_upvalueindex (4));
603 lua_pushlstring (L, argE.text+argE.startoffset, argE.textlen-argE.startoffset);
608 static int algf_gmatch (lua_State *L)
613 checkarg_gmatch_split (L, &argC, &argE);
615 ud = (TUserdata*) argC.ud;
616 lua_pushvalue (L, 2);
618 else compile_regex (L, &argC, &ud);
619 gmatch_pushsubject (L, &argE);
620 lua_pushinteger (L, argE.eflags);
621 lua_pushinteger (L, 0);
623 lua_pushinteger (L, 0);
624 lua_pushcclosure (L, gmatch_iter, 5);
626 lua_pushcclosure (L, gmatch_iter, 4);
631 static int algf_split (lua_State *L)
636 checkarg_gmatch_split (L, &argC, &argE);
638 ud = (TUserdata*) argC.ud;
639 lua_pushvalue (L, 2);
641 else compile_regex (L, &argC, &ud);
642 gmatch_pushsubject (L, &argE);
643 lua_pushinteger (L, argE.eflags);
644 lua_pushinteger (L, 0);
645 lua_pushinteger (L, 0);
646 lua_pushcclosure (L, split_iter, 5);
651 static void push_substring_table (lua_State *L, TUserdata *ud,
const char *text) {
654 for (i = 1; i <= ALG_NSUB(ud); i++) {
655 ALG_PUSHSUB_OR_FALSE (L, ud, text, i);
656 lua_rawseti (L, -2, i);
661 static void push_offset_table (lua_State *L, TUserdata *ud,
int startoffset) {
664 for (i=1, j=1; i <= ALG_NSUB(ud); i++) {
665 if (ALG_SUBVALID (ud,i)) {
666 ALG_PUSHSTART (L, ud, startoffset, i);
667 lua_rawseti (L, -2, j++);
668 ALG_PUSHEND (L, ud, startoffset, i);
669 lua_rawseti (L, -2, j++);
672 lua_pushboolean (L, 0);
673 lua_rawseti (L, -2, j++);
674 lua_pushboolean (L, 0);
675 lua_rawseti (L, -2, j++);
681 static int generic_find_method (lua_State *L,
int method) {
686 checkarg_find_method (L, &argE, &ud);
687 if (argE.startoffset > (
int)argE.textlen) {
692 res = findmatch_exec (ud, &argE);
693 if (ALG_ISMATCH (res)) {
696 ALG_PUSHOFFSETS (L, ud, ALG_BASE(argE.startoffset), 0);
697 push_offset_table (L, ud, ALG_BASE(argE.startoffset));
698 DO_NAMED_SUBPATTERNS (L, ud, argE.text);
701 ALG_PUSHOFFSETS (L, ud, ALG_BASE(argE.startoffset), 0);
702 push_substring_table (L, ud, argE.text);
703 DO_NAMED_SUBPATTERNS (L, ud, argE.text);
707 return finish_generic_find (L, ud, &argE, method, res);
711 else if (ALG_NOMATCH (res)) {
716 return generate_error(L, ud, res);
720 static int algm_find (lua_State *L) {
721 return generic_find_method (L, METHOD_FIND);
723 static int algm_match (lua_State *L) {
724 return generic_find_method (L, METHOD_MATCH);
726 static int algm_tfind (lua_State *L) {
727 return generic_find_method (L, METHOD_TFIND);
729 static int algm_exec (lua_State *L) {
730 return generic_find_method (L, METHOD_EXEC);
733 static void alg_register (lua_State *L,
const luaL_Reg *r_methods,
734 const luaL_Reg *r_functions,
const char *name) {
736 #if LUA_VERSION_NUM == 501 738 lua_pushvalue (L, -1);
739 lua_replace (L, LUA_ENVIRONINDEX);
740 luaL_register (L, NULL, r_methods);
742 luaL_newmetatable(L, REX_TYPENAME);
743 lua_pushvalue(L, -1);
744 luaL_setfuncs (L, r_methods, 1);
746 #ifdef LREXLIB_WIRESHARK 747 lua_pushstring(L, REX_LIBNAME);
748 lua_setfield(L, -2, WSLUA_TYPEOF_FIELD);
750 lua_pushvalue(L, -1);
751 lua_setfield(L, -2,
"__index");
754 lua_createtable(L, 0, 8);
755 #if LUA_VERSION_NUM == 501 756 luaL_register (L, NULL, r_functions);
758 lua_pushvalue(L, -2);
759 luaL_setfuncs (L, r_functions, 1);
761 #ifdef REX_CREATEGLOBALVAR 762 lua_pushvalue(L, -1);
763 lua_setglobal(L, REX_LIBNAME);
765 #ifdef LREXLIB_WIRESHARK 766 lua_pushstring(L, REX_LIBNAME);
767 lua_setfield(L, -2, WSLUA_TYPEOF_FIELD);
769 lua_pushfstring (L, REX_VERSION
" (for %s)", name);
770 lua_setfield (L, -2,
"_VERSION");