|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "global.h" |
#include <ctype.h> |
#ifdef HAVE_STRING_H |
#include <string.h> |
#endif /* HAVE_STRING_H */ |
#include "pike_regexp.h" |
#include "pike_memory.h" |
#include "pike_error.h" |
#include "interpret.h" |
|
#undef NOTHING |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define END 0 /* no End of program. */ |
#define BOL 1 /* no Match "" at beginning of line. */ |
#define EOL 2 /* no Match "" at end of line. */ |
#define ANY 3 /* no Match any one character. */ |
#define ANYOF 4 /* str Match any character in this string. */ |
#define ANYBUT 5 /* str Match any character not in this |
* string. */ |
#define BRANCH 6 /* node Match this alternative, or the |
* nxt... */ |
#define BACK 7 /* no Match "", "nxt" ptr points backward. */ |
#define EXACTLY 8 /* str Match this string. */ |
#define NOTHING 9 /* no Match empty string. */ |
#define STAR 10 /* node Match this (simple) thing 0 or more |
* times. */ |
#define WORDSTART 11 /* node matching a start of a word */ |
#define WORDEND 12 /* node matching an end of a word */ |
#define KPLUS 13 /* node Match this (simple) thing 1 or more |
* times. */ |
#define OPEN 20 /* no Mark this point in input as start of |
* #n. */ |
|
#define CLOSE (OPEN+NSUBEXP) /* no Analogous to OPEN. */ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define OP(p) (*(p)) |
#define NEXT(p) (((*((p)+1)&0377)<<8) + (*((p)+2)&0377)) |
#define OPERAND(p) ((p) + 3) |
|
|
|
|
|
#define regerror(X) Pike_error("Regexp: %s\n",X); |
#define SPECIAL 0x100 |
#define LBRAC ('('|SPECIAL) |
#define RBRAC (')'|SPECIAL) |
#define ASTERIX ('*'|SPECIAL) |
#define PLUS ('+'|SPECIAL) |
#define OR_OP ('|'|SPECIAL) |
#define DOLLAR ('$'|SPECIAL) |
#define DOT ('.'|SPECIAL) |
#define CARET ('^'|SPECIAL) |
#define LSQBRAC ('['|SPECIAL) |
#define RSQBRAC (']'|SPECIAL) |
#define LSHBRAC ('<'|SPECIAL) |
#define RSHBRAC ('>'|SPECIAL) |
#define FAIL(m) { regerror(m); return(NULL); } |
#define ISMULT(c) ((c) == ASTERIX || (c)==PLUS) |
#define META "^$.[()|*+\\" |
#ifndef CHARBITS |
#define CHARBITS 0xff |
#define UCHARAT(p) ((int)*(unsigned char *)(p)) |
#else |
#define UCHARAT(p) ((int)*(p)&CHARBITS) |
#endif |
#define ISWORDPART(c) ( isalnum(c) || (c) == '_' ) |
|
|
|
|
#define HASWIDTH 01 /* Known never to match null string. */ |
#define SIMPLE 02 /* Simple enough to be STAR or KPLUS operand. */ |
#define SPSTART 04 /* Starts with * */ |
#define WORST 0 /* Worst case. */ |
|
|
|
|
static short *regparse; |
static int regnpar; |
static char *regcode; |
static long regsize; |
static char regdummy; |
|
|
|
|
static char *reg(int, int *); |
static char *regbranch(int *); |
static char *regpiece(int *); |
static char *regatom(int *); |
static char *regnode(char); |
static char *regnext(register char *); |
static void regc(char b); |
static void reginsert(char, char *); |
static void regtail(char *, char *); |
static void regoptail(char *, char *); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
regexp *pike_regcomp(char *exp,int excompat) |
{ |
register regexp *r = NULL; |
register char *scan; |
register char *longest; |
register ptrdiff_t len; |
int flags; |
short *exp2,*dest,c; |
|
if (exp == NULL) |
FAIL("NULL argument"); |
|
exp2=xcalloc( (strlen(exp)+1), sizeof(short) ); |
for ( scan=exp,dest=exp2;( c= UCHARAT(scan++)); ) { |
switch (c) { |
case '(': |
case ')': |
*dest++ = excompat ? c : c | SPECIAL; |
break; |
case '.': |
case '*': |
case '+': |
case '|': |
case '$': |
case '^': |
case '[': |
case ']': |
*dest++ = c | SPECIAL; |
break; |
case '\\': |
switch ( c = *scan++ ) { |
case '(': |
case ')': |
*dest++ = excompat ? c | SPECIAL : c; |
break; |
case '<': |
case '>': |
*dest++ = c | SPECIAL; |
break; |
case '{': |
case '}': |
FAIL("sorry, unimplemented operator"); |
case 'b': *dest++ = '\b'; break; |
case 't': *dest++ = '\t'; break; |
case 'r': *dest++ = '\r'; break; |
default: |
*dest++ = c; |
} |
break; |
default: |
*dest++ = c; |
} |
} |
|
|
regparse = exp2; |
regnpar = 1; |
regsize = 0L; |
regcode = ®dummy; |
if (reg(0, &flags) == NULL) |
goto exit_regcomp; |
|
|
if (regsize >= 32767L) |
{ |
free(exp2); |
FAIL("regexp too big"); |
} |
|
|
r = malloc(sizeof(regexp) + (unsigned) regsize); |
if(!r) |
{ |
free(exp2); |
Pike_error(msg_out_of_mem); |
} |
|
|
regparse = exp2; |
regnpar = 1; |
regcode = r->program; |
if (reg(0, &flags) == NULL) |
{ |
free(r); |
r = NULL; |
goto exit_regcomp; |
} |
|
|
r->regstart = '\0'; |
r->reganch = 0; |
r->regmust = NULL; |
r->regmlen = 0; |
scan = r->program; |
if (OP(regnext(scan)) == END) { |
scan = OPERAND(scan); |
|
|
if (OP(scan) == EXACTLY) |
r->regstart = *OPERAND(scan); |
else if (OP(scan) == BOL) |
r->reganch++; |
|
|
|
|
|
|
|
|
|
if (flags & SPSTART) { |
longest = NULL; |
len = 0; |
for (; scan != NULL; scan = regnext(scan)) |
if (OP(scan) == EXACTLY && |
strlen(OPERAND(scan)) >= (size_t)len) { |
longest = OPERAND(scan); |
len = strlen(OPERAND(scan)); |
} |
r->regmust = longest; |
r->regmlen = len; |
} |
} |
|
exit_regcomp: |
free(exp2); |
return (r); |
} |
|
|
|
|
|
|
|
|
|
|
static char *reg(int paren,int *flagp) |
{ |
register char *ret; |
register char *br; |
register char *ender; |
register int parno=0; |
int flags; |
|
*flagp = HASWIDTH; |
|
|
if (paren) { |
if (regnpar >= NSUBEXP) |
FAIL("too many ()"); |
parno = regnpar; |
regnpar++; |
ret = regnode((char)(OPEN + parno)); |
} else |
ret = NULL; |
|
|
br = regbranch(&flags); |
if (br == NULL) |
return (NULL); |
if (ret != NULL) |
regtail(ret, br); |
else |
ret = br; |
if (!(flags & HASWIDTH)) |
*flagp &= ~HASWIDTH; |
*flagp |= flags & SPSTART; |
while (*regparse == OR_OP) { |
regparse++; |
br = regbranch(&flags); |
if (br == NULL) |
return (NULL); |
regtail(ret, br); |
if (!(flags & HASWIDTH)) |
*flagp &= ~HASWIDTH; |
*flagp |= flags & SPSTART; |
} |
|
|
ender = regnode((char)((paren) ? (CLOSE + parno) : END)); |
regtail(ret, ender); |
|
|
for (br = ret; br != NULL; br = regnext(br)) |
regoptail(br, ender); |
|
|
if (paren && *regparse++ != RBRAC) { |
FAIL("unmatched ()"); |
} else if (!paren && *regparse != '\0') { |
if (*regparse == RBRAC) { |
FAIL("unmatched ()"); |
} else |
FAIL("junk on end"); |
|
} |
return (ret); |
} |
|
|
|
|
|
|
static char *regbranch(int *flagp) |
{ |
register char *ret; |
register char *chain; |
register char *latest; |
int flags; |
|
*flagp = WORST; |
|
ret = regnode(BRANCH); |
chain = NULL; |
while (*regparse != '\0' && *regparse != OR_OP && *regparse != RBRAC) { |
latest = regpiece(&flags); |
if (latest == NULL) |
return (NULL); |
*flagp |= flags & HASWIDTH; |
if (chain == NULL) |
*flagp |= flags & SPSTART; |
else |
regtail(chain, latest); |
chain = latest; |
} |
if (chain == NULL) |
regnode(NOTHING); |
|
return (ret); |
} |
|
|
|
|
|
|
|
|
|
static char *regpiece(int *flagp) |
{ |
register char *ret; |
register short op; |
|
int flags; |
|
ret = regatom(&flags); |
if (ret == NULL) |
return (NULL); |
|
op = *regparse; |
if (!ISMULT(op)) { |
*flagp = flags; |
return (ret); |
} |
if (!(flags & HASWIDTH)) |
FAIL("* or + operand could be empty"); |
*flagp = (WORST | SPSTART); |
|
if(op == ASTERIX) |
{ |
if (flags & SIMPLE) |
{ |
reginsert(STAR, ret); |
} |
else |
{ |
|
reginsert(BRANCH, ret); |
regoptail(ret, regnode(BACK)); |
regoptail(ret, ret); |
regtail(ret, regnode(BRANCH)); |
regtail(ret, regnode(NOTHING)); |
} |
} |
else if(op == PLUS) |
{ |
if (flags & SIMPLE) |
{ |
reginsert(KPLUS, ret); |
} |
else |
{ |
|
|
|
|
|
|
char *tmp; |
tmp=regnode(BACK); |
reginsert(BRANCH, tmp); |
regtail(ret, tmp); |
regoptail(tmp, ret); |
regtail(ret, regnode(BRANCH)); |
regtail(ret, regnode(NOTHING)); |
} |
} |
|
regparse++; |
if (ISMULT(*regparse)) |
FAIL("nested * or +"); |
|
return (ret); |
} |
|
|
|
|
|
|
|
|
|
static char *regatom(int *flagp) |
{ |
register char *ret; |
int flags; |
|
*flagp = WORST; |
|
switch (*regparse++) { |
case CARET: |
ret = regnode(BOL); |
break; |
case DOLLAR: |
ret = regnode(EOL); |
break; |
case DOT: |
ret = regnode(ANY); |
*flagp |= HASWIDTH | SIMPLE; |
break; |
case LSHBRAC: |
ret = regnode(WORDSTART); |
break; |
case RSHBRAC: |
ret = regnode(WORDEND); |
break; |
case LSQBRAC:{ |
register int class; |
register int classend; |
|
if (*regparse == CARET) { |
ret = regnode(ANYBUT); |
regparse++; |
} else |
ret = regnode(ANYOF); |
if (*regparse == RSQBRAC || *regparse == '-') |
regc((char)(*regparse++)); |
while (*regparse != '\0' && *regparse != RSQBRAC) { |
if (*regparse == '-') { |
regparse++; |
if (*regparse == RSQBRAC || *regparse == '\0') |
regc('-'); |
else { |
class = (CHARBITS & *(regparse - 2)) + 1; |
classend = (CHARBITS & *(regparse)); |
if (class > classend + 1) |
FAIL("invalid [] range"); |
for (; class <= classend; class++) |
regc((char)class); |
regparse++; |
} |
} else |
regc((char)(*regparse++)); |
} |
regc('\0'); |
if (*regparse != RSQBRAC) |
FAIL("unmatched []"); |
regparse++; |
*flagp |= HASWIDTH | SIMPLE; |
} |
break; |
case LBRAC: |
ret = reg(1, &flags); |
if (ret == NULL) |
return (NULL); |
*flagp |= flags & (HASWIDTH | SPSTART); |
break; |
case '\0': |
case OR_OP: |
case RBRAC: |
FAIL("internal urp"); |
|
case ASTERIX: |
FAIL("* follows nothing\n"); |
|
default:{ |
register int len; |
register short ender; |
|
regparse--; |
for (len=0; regparse[len] && |
!(regparse[len]&SPECIAL) && regparse[len] != RSQBRAC; len++) ; |
if (len <= 0) |
{ |
FAIL("internal disaster"); |
} |
ender = *(regparse + len); |
if (len > 1 && ISMULT(ender)) |
len--; |
*flagp |= HASWIDTH; |
if (len == 1) |
*flagp |= SIMPLE; |
ret = regnode(EXACTLY); |
while (len > 0) { |
regc((char)(*regparse++)); |
len--; |
} |
regc('\0'); |
} |
break; |
} |
|
return (ret); |
} |
|
|
|
|
static char *regnode(char op) |
{ |
register char *ret; |
register char *ptr; |
|
ret = regcode; |
if (ret == ®dummy) { |
regsize += 3; |
return (ret); |
} |
ptr = ret; |
*ptr++ = op; |
*ptr++ = '\0'; |
*ptr++ = '\0'; |
regcode = ptr; |
|
return (ret); |
} |
|
|
|
|
static void regc(char b) |
{ |
if (regcode != ®dummy) |
*regcode++ = b; |
else |
regsize++; |
} |
|
|
|
|
|
|
static void reginsert(char op, char *opnd) |
{ |
register char *src; |
register char *dst; |
register char *place; |
|
if (regcode == ®dummy) { |
regsize += 3; |
return; |
} |
|
memmove(opnd+3, opnd, (size_t)(regcode - opnd)); |
regcode += 3; |
|
place = opnd; |
*place++ = op; |
*place++ = '\0'; |
*place++ = '\0'; |
} |
|
|
|
|
static void regtail(char *p, char *val) |
{ |
register char *scan; |
register char *temp; |
register ptrdiff_t offset; |
|
if (p == ®dummy) |
return; |
|
|
scan = p; |
for (;;) { |
temp = regnext(scan); |
if (temp == NULL) |
break; |
scan = temp; |
} |
|
if (OP(scan) == BACK) |
offset = scan - val; |
else |
offset = val - scan; |
*(scan + 1) = DO_NOT_WARN((offset >> 8) & 0377); |
*(scan + 2) = DO_NOT_WARN(offset & 0377); |
} |
|
|
|
|
static void regoptail(char *p, char *val) |
{ |
|
if (p == NULL || p == ®dummy || OP(p) != BRANCH) |
return; |
regtail(OPERAND(p), val); |
} |
|
|
|
|
|
|
|
|
static char *reginput; |
static char *regbol; |
static char **regstartp; |
static char **regendp; |
|
|
|
|
static int regtry(regexp *, char *); |
static int regmatch(char *); |
static size_t regrepeat(char *); |
|
#ifdef PIKE_DEBUG |
int regnarrate = 0; |
void regdump(regexp *); |
static char *regprop(char *op); |
#endif |
|
|
|
|
int pike_regexec(regexp *prog, char *string) |
{ |
register char *s; |
|
|
if (prog == NULL || string == NULL) { |
regerror("NULL parameter"); |
return (0); |
} |
|
|
if (prog->regmust != NULL && strstr(string, prog->regmust) == NULL) |
return(0); |
|
|
regbol = string; |
|
|
if (prog->reganch) |
return (regtry(prog, string)); |
|
|
s = string; |
if (prog->regstart != '\0') |
|
while ((s = strchr(s, prog->regstart)) != NULL) { |
if (regtry(prog, s)) |
return (1); |
s++; |
} |
else |
|
do { |
if (regtry(prog, s)) |
return (1); |
} while (*s++ != '\0'); |
|
|
return (0); |
} |
|
|
|
|
static int regtry(regexp *prog, char *string) |
{ |
register int i; |
register char **sp; |
register char **ep; |
|
reginput = string; |
regstartp = prog->startp; |
regendp = prog->endp; |
|
sp = prog->startp; |
ep = prog->endp; |
for (i = NSUBEXP; i > 0; i--) { |
*sp++ = NULL; |
*ep++ = NULL; |
} |
if (regmatch(prog->program)) { |
prog->startp[0] = string; |
prog->endp[0] = reginput; |
return (1); |
} else |
return (0); |
} |
|
|
|
|
|
|
|
|
|
|
|
static int regmatch(char *prog) |
{ |
register char *scan; |
char *nxt; |
|
check_c_stack (4 * sizeof (void *)); |
|
scan = prog; |
#ifdef PIKE_DEBUG |
if (scan != NULL && regnarrate) |
fprintf(stderr, "%s(\n", regprop(scan)); |
#endif |
while (scan != NULL) { |
#ifdef PIKE_DEBUG |
if (regnarrate) |
fprintf(stderr, "%s...\n", regprop(scan)); |
#endif |
nxt = regnext(scan); |
|
switch (OP(scan)) { |
case BOL: |
if (reginput != regbol) |
return (0); |
break; |
case EOL: |
if (*reginput != '\0') |
return (0); |
break; |
case ANY: |
if (*reginput == '\0') |
return (0); |
reginput++; |
break; |
case WORDSTART: |
if (reginput == regbol) |
break; |
if (*reginput == '\0' || |
ISWORDPART( *((unsigned char *)reginput-1) ) || |
!ISWORDPART( *((unsigned char *)reginput) ) ) |
return (0); |
break; |
case WORDEND: |
if (*reginput == '\0') |
break; |
if ( reginput == regbol || |
!ISWORDPART( *((unsigned char *)reginput-1) ) || |
ISWORDPART( *((unsigned char *)reginput) ) ) |
return (0); |
break; |
case EXACTLY:{ |
register ptrdiff_t len; |
register char *opnd; |
|
opnd = OPERAND(scan); |
|
if (*opnd != *reginput) |
return (0); |
len = strlen(opnd); |
if (len > 1 && strncmp(opnd, reginput, len) != 0) |
return (0); |
reginput += len; |
} |
break; |
case ANYOF: |
if (*reginput == '\0' || |
strchr(OPERAND(scan), *reginput) == NULL) |
return (0); |
reginput++; |
break; |
case ANYBUT: |
if (*reginput == '\0' || |
strchr(OPERAND(scan), *reginput) != NULL) |
return (0); |
reginput++; |
break; |
case NOTHING: |
break; |
case BACK: |
break; |
|
case BRANCH:{ |
register char *save; |
|
if (OP(nxt) != BRANCH) |
nxt = OPERAND(scan); |
else { |
do { |
save = reginput; |
if (regmatch(OPERAND(scan))) |
return (1); |
reginput = save; |
scan = regnext(scan); |
} while (scan != NULL && OP(scan) == BRANCH); |
return (0); |
|
} |
} |
break; |
case KPLUS: |
case STAR:{ |
register char nextch = |
(OP(nxt) == EXACTLY) ? *OPERAND(nxt) : '\0'; |
register size_t no; |
register char *save = reginput; |
register size_t minimum = (OP(scan) == STAR) ? 0 : 1; |
|
for(no = regrepeat(OPERAND(scan)) + 1; no > minimum; no--) { |
reginput = save + no -1; |
|
if (nextch == '\0' || *reginput == nextch) |
if (regmatch(nxt)) |
return (1); |
} |
return (0); |
} |
|
case END: |
return (1); |
|
default: |
if(OP(scan) >= OPEN && OP(scan)<OPEN+NSUBEXP) |
{ |
register int no; |
register char *save; |
|
no = OP(scan) - OPEN; |
save = reginput; |
|
if (regmatch(nxt)) { |
|
|
|
|
if (regstartp[no] == NULL) |
regstartp[no] = save; |
return (1); |
} else |
return (0); |
} |
|
if(OP(scan) >= CLOSE && OP(scan)<CLOSE+NSUBEXP) |
{ |
register int no; |
register char *save; |
|
no = OP(scan) - CLOSE; |
save = reginput; |
|
if (regmatch(nxt)) { |
|
|
|
|
if (regendp[no] == NULL) |
regendp[no] = save; |
return (1); |
} else |
return (0); |
} |
regerror("memory corruption"); |
return (0); |
|
} |
|
scan = nxt; |
} |
|
|
|
|
|
regerror("corrupted pointers"); |
return (0); |
} |
|
|
|
|
static size_t regrepeat(char *node) |
{ |
register size_t count = 0; |
register char *scan; |
register char ch; |
|
switch (OP(node)) { |
case ANY: |
return(strlen(reginput)); |
break; |
case EXACTLY: |
ch = *OPERAND(node); |
count = 0; |
for (scan = reginput; *scan == ch; scan++) |
count++; |
return(count); |
break; |
case ANYOF: |
return(strspn(reginput, OPERAND(node))); |
break; |
case ANYBUT: |
return(strcspn(reginput, OPERAND(node))); |
break; |
default: |
regerror("internal foulup"); |
return(0); |
break; |
} |
|
} |
|
|
|
|
|
static char *regnext(register char *p) |
{ |
register int offset; |
|
if (p == ®dummy) |
return (NULL); |
|
offset = NEXT(p); |
if (offset == 0) |
return (NULL); |
|
if (OP(p) == BACK) |
return (p - offset); |
else |
return (p + offset); |
} |
|
#ifdef PIKE_DEBUG |
|
static char *regprop(char *); |
|
|
|
|
void regdump(regexp *r) |
{ |
register char *s; |
register char op = EXACTLY; |
register char *nxt; |
|
s = r->program; |
while (op != END) { |
op = OP(s); |
printf("%2ld%s", |
DO_NOT_WARN((long)(s - r->program)), |
regprop(s)); |
nxt = regnext(s); |
if (nxt == NULL) |
printf("(0)"); |
else |
printf("(%ld)", |
DO_NOT_WARN((long)( (s - r->program) + (nxt - s)))); |
s += 3; |
if (op == ANYOF || op == ANYBUT || op == EXACTLY) { |
|
while (*s != '\0') { |
putchar(*s); |
s++; |
} |
s++; |
} |
putchar('\n'); |
} |
|
|
if (r->regstart != '\0') |
printf("start `%c' ", r->regstart); |
if (r->reganch) |
printf("anchored "); |
if (r->regmust != NULL) |
printf("must have \"%s\"", r->regmust); |
printf("\n"); |
} |
|
|
|
|
static char *regprop(char *op) |
{ |
register char *p; |
static char buf[50]; |
|
strcpy(buf, ":"); |
|
switch (OP(op)) { |
case BOL: |
p = "BOL"; |
break; |
case EOL: |
p = "EOL"; |
break; |
case ANY: |
p = "ANY"; |
break; |
case ANYOF: |
p = "ANYOF"; |
break; |
case ANYBUT: |
p = "ANYBUT"; |
break; |
case BRANCH: |
p = "BRANCH"; |
break; |
case EXACTLY: |
p = "EXACTLY"; |
break; |
case NOTHING: |
p = "NOTHING"; |
break; |
case BACK: |
p = "BACK"; |
break; |
case END: |
p = "END"; |
break; |
|
case STAR: |
p = "STAR"; |
break; |
|
case KPLUS: |
p = "KPLUS"; |
break; |
|
default: |
if(OP(op) >= OPEN && OP(op) < OPEN+NSUBEXP) |
{ |
sprintf(buf + strlen(buf), "OPEN%d", OP(op) - OPEN); |
p = NULL; |
break; |
} |
if(OP(op) >= CLOSE && OP(op) < CLOSE+NSUBEXP) |
{ |
sprintf(buf + strlen(buf), "CLOSE%d", OP(op) - CLOSE); |
p = NULL; |
break; |
} |
regerror("corrupted opcode"); |
p=NULL; |
break; |
} |
if (p != NULL) |
strcat(buf, p); |
return (buf); |
} |
#endif |
|
|
|
|
|
char *pike_regsub(regexp *prog, char *source, char *dest, int n) |
{ |
register char *src; |
register char *dst; |
register char c; |
register int no; |
register ptrdiff_t len; |
|
if (prog == NULL || |
source == NULL || dest == NULL) { |
regerror("NULL parm to regsub"); |
return NULL; |
} |
|
src = source; |
dst = dest; |
while ((c = *src++) != '\0') { |
if (c == '&') |
no = 0; |
else if (c == '\\' && '0' <= *src && *src <= '9') |
no = *src++ - '0'; |
else |
no = -1; |
|
if (no < 0) { |
if (c == '\\' && (*src == '\\' || *src == '&')) |
c = *src++; |
if (--n < 0) { |
regerror("line too long"); |
return NULL; |
} |
*dst++ = c; |
} else if (prog->startp[no] != NULL && |
prog->endp[no] != NULL) { |
len = prog->endp[no] - prog->startp[no]; |
if ( (n-=len) < 0 ) { |
regerror("line too long"); |
return NULL; |
} |
strncpy(dst, prog->startp[no], len); |
dst += len; |
if (len != 0 && *(dst - 1) == '\0') { |
regerror("damaged match string"); |
return NULL; |
} |
} |
} |
if (--n < 0) { |
regerror("line too long"); |
return NULL; |
} |
*dst = '\0'; |
return dst; |
} |
|
|