diff -r 06ecc74a64fb sys/src/libregexp/regexec.c --- a/sys/src/libregexp/regexec.c Sun Feb 23 20:33:27 2020 +0000 +++ b/sys/src/libregexp/regexec.c Thu Feb 27 14:26:58 2020 -0500 @@ -10,14 +10,15 @@ }; int -regexec(Reprog *p, char *str, Resub *sem, int msize) +regexecfn(Reprog *p, char *str, int (*more)(void*, char*, int), void *ctx, Resub *sem, int msize) { RethreadQ lists[2], *clist, *nlist, *tmp; Rethread *t, *next, *pool, *avail; Reinst *ci; Rune r; - char *sp, *ep, endc; - int i, matchgen, gen; + char *sp, *ep, *buf, endc; + int i, matchgen, gen, n; + vlong o; memset(p->threads, 0, sizeof(Rethread)*p->nthr); if(msize > NSUBEXPM) @@ -39,9 +40,11 @@ gen = matchgen = 0; sp = str; + buf = nil; ep = nil; endc = '\0'; - if(sem != nil && msize > 0) { + o = 0; + if(more == nil && sem != nil && msize > 0) { if(sem->sp != nil) sp = sem->sp; if(sem->ep != nil && *sem->ep != '\0') { @@ -50,9 +53,28 @@ *sem->ep = '\0'; } } + if(more != nil){ + if((buf = malloc(BUFSZ + 1)) == nil) + regerror("out of memory"); + buf[0] = 0; + sp = buf; + if(sem != nil && msize > 0){ + sem->so = 0; + sem->eo = 0; + } + } - for(r = L'☺'; r != L'\0'; sp += i) { + for(r = L'☺'; r != L'\0'; sp += i, o += i) { +Gotmore: i = chartorune(&r, sp); + if(r == 0 && more != nil){ + n = more(ctx, buf, BUFSZ); + if(n > 0){ + sp = buf; + sp[n] = 0; + goto Gotmore; + } + } gen++; if(matchgen == 0) { if(avail == nil) { @@ -110,7 +132,7 @@ } goto Done; case OBOL: - if(sp == str || sp[-1] == '\n') { + if(o == 0 || sp[-1] == '\n') { ci++; goto Again; } @@ -141,8 +163,12 @@ ci = ci->a; goto Again; case OSAVE: - if(ci->sub < msize) - t->sem[ci->sub].sp = sp; + if(ci->sub < msize){ + if(more != nil) + t->sem[ci->sub].so = o; + else + t->sem[ci->sub].sp = sp; + } ci++; goto Again; case OUNSAVE: @@ -150,12 +176,19 @@ matchgen = t->gen; if(sem != nil && msize > 0) { memcpy(sem, t->sem, sizeof(Resub)*msize); - sem->ep = sp; + if(more != nil) + sem->eo = o; + else + sem->ep = sp; } goto Done; } - if(ci->sub < msize) - t->sem[ci->sub].ep = sp; + if(ci->sub < msize){ + if(more != nil) + t->sem[ci->sub].eo = o; + else + t->sem[ci->sub].ep = sp; + } ci++; goto Again; Done: @@ -182,5 +215,19 @@ } if(ep != nil) *ep = endc; + if(more != nil) + free(buf); return matchgen > 0 ? 1 : 0; } + +int +regexec(Reprog *p, char *str, Resub *sem, int msize) +{ + return regexecfn(p, str, nil, nil, sem, msize); +} + +int +regexecrd(Reprog *p, int (*more)(void*, char*, int), void *ctx, Resub *sem, int msize) +{ + return regexecfn(p, nil, more, ctx, sem, msize); +} diff -r 06ecc74a64fb sys/src/libregexp/regimpl.h --- a/sys/src/libregexp/regimpl.h Sun Feb 23 20:33:27 2020 +0000 +++ b/sys/src/libregexp/regimpl.h Thu Feb 27 14:26:58 2020 -0500 @@ -24,6 +24,7 @@ TSUB, NSUBEXPM = 32, + BUFSZ = 4096, }; typedef struct Parselex Parselex;