version 1.6, 2003/04/06 23:38:07 |
version 1.7, 2003/04/13 18:26:26 |
|
|
/* $OpenBSD$ */ |
|
|
|
/* |
/* |
* regcomp and regexec -- regsub and regerror are elsewhere |
* regcomp and regexec -- regsub and regerror are elsewhere |
* |
* |
|
|
* |
* |
* *** NOTE: this code has been altered slightly for use in Tcl. *** |
* *** NOTE: this code has been altered slightly for use in Tcl. *** |
* Slightly modified by David MacKenzie to undo most of the changes for TCL. |
* Slightly modified by David MacKenzie to undo most of the changes for TCL. |
|
* Added regexec2 with notbol parameter. -- 4/19/99 Mark Nudelman |
*/ |
*/ |
|
|
|
#include "less.h" |
|
#if HAVE_STDIO_H |
#include <stdio.h> |
#include <stdio.h> |
|
#endif |
|
#if HAVE_STDLIB_H |
|
#include <stdlib.h> |
|
#endif |
|
#if HAVE_STRING_H |
|
#include <string.h> |
|
#endif |
#include "regexp.h" |
#include "regexp.h" |
char *strchr(); |
|
|
|
/* |
/* |
* The "internal use only" fields in regexp.h are present to pass info from |
* The "internal use only" fields in regexp.h are present to pass info from |
|
|
*/ |
*/ |
|
|
/* definition number opnd? meaning */ |
/* definition number opnd? meaning */ |
|
#undef EOL |
#define END 0 /* no End of program. */ |
#define END 0 /* no End of program. */ |
#define BOL 1 /* no Match "" at beginning of line. */ |
#define BOL 1 /* no Match "" at beginning of line. */ |
#define EOL 2 /* no Match "" at end of line. */ |
#define EOL 2 /* no Match "" at end of line. */ |
|
|
regcomp(exp) |
regcomp(exp) |
char *exp; |
char *exp; |
{ |
{ |
regexp *r; |
register regexp *r; |
char *scan; |
register char *scan; |
char *longest; |
register char *longest; |
int len; |
register int len; |
int flags; |
int flags; |
|
|
if (exp == NULL) |
if (exp == NULL) |
|
|
int paren; /* Parenthesized? */ |
int paren; /* Parenthesized? */ |
int *flagp; |
int *flagp; |
{ |
{ |
char *ret; |
register char *ret; |
char *br; |
register char *br; |
char *ender; |
register char *ender; |
int parno = 0; |
register int parno = 0; |
int flags; |
int flags; |
|
|
*flagp = HASWIDTH; /* Tentatively. */ |
*flagp = HASWIDTH; /* Tentatively. */ |
|
|
regbranch(flagp) |
regbranch(flagp) |
int *flagp; |
int *flagp; |
{ |
{ |
char *ret; |
register char *ret; |
char *chain; |
register char *chain; |
char *latest; |
register char *latest; |
int flags; |
int flags; |
|
|
*flagp = WORST; /* Tentatively. */ |
*flagp = WORST; /* Tentatively. */ |
|
|
regpiece(flagp) |
regpiece(flagp) |
int *flagp; |
int *flagp; |
{ |
{ |
char *ret; |
register char *ret; |
char op; |
register char op; |
char *next; |
register char *next; |
int flags; |
int flags; |
|
|
ret = regatom(&flags); |
ret = regatom(&flags); |
|
|
regatom(flagp) |
regatom(flagp) |
int *flagp; |
int *flagp; |
{ |
{ |
char *ret; |
register char *ret; |
int flags; |
int flags; |
|
|
*flagp = WORST; /* Tentatively. */ |
*flagp = WORST; /* Tentatively. */ |
|
|
*flagp |= HASWIDTH|SIMPLE; |
*flagp |= HASWIDTH|SIMPLE; |
break; |
break; |
case '[': { |
case '[': { |
int clss; |
register int clss; |
int classend; |
register int classend; |
|
|
if (*regparse == '^') { /* Complement of range. */ |
if (*regparse == '^') { /* Complement of range. */ |
ret = regnode(ANYBUT); |
ret = regnode(ANYBUT); |
|
|
*flagp |= HASWIDTH|SIMPLE; |
*flagp |= HASWIDTH|SIMPLE; |
break; |
break; |
default: { |
default: { |
int len; |
register int len; |
char ender; |
register char ender; |
|
|
regparse--; |
regparse--; |
len = strcspn(regparse, META); |
len = strcspn(regparse, META); |
|
|
regnode(op) |
regnode(op) |
char op; |
char op; |
{ |
{ |
char *ret; |
register char *ret; |
char *ptr; |
register char *ptr; |
|
|
ret = regcode; |
ret = regcode; |
if (ret == ®dummy) { |
if (ret == ®dummy) { |
|
|
char op; |
char op; |
char *opnd; |
char *opnd; |
{ |
{ |
char *src; |
register char *src; |
char *dst; |
register char *dst; |
char *place; |
register char *place; |
|
|
if (regcode == ®dummy) { |
if (regcode == ®dummy) { |
regsize += 3; |
regsize += 3; |
|
|
char *p; |
char *p; |
char *val; |
char *val; |
{ |
{ |
char *scan; |
register char *scan; |
char *temp; |
register char *temp; |
int offset; |
register int offset; |
|
|
if (p == ®dummy) |
if (p == ®dummy) |
return; |
return; |
|
|
- regexec - match a regexp against a string |
- regexec - match a regexp against a string |
*/ |
*/ |
int |
int |
regexec(prog, string) |
regexec2(prog, string, notbol) |
regexp *prog; |
register regexp *prog; |
char *string; |
register char *string; |
|
int notbol; |
{ |
{ |
char *s; |
register char *s; |
|
|
/* Be paranoid... */ |
/* Be paranoid... */ |
if (prog == NULL || string == NULL) { |
if (prog == NULL || string == NULL) { |
|
|
} |
} |
|
|
/* Mark beginning of line for ^ . */ |
/* Mark beginning of line for ^ . */ |
regbol = string; |
if (notbol) |
|
regbol = NULL; |
|
else |
|
regbol = string; |
|
|
/* Simplest case: anchored match need be tried only once. */ |
/* Simplest case: anchored match need be tried only once. */ |
if (prog->reganch) |
if (prog->reganch) |
|
|
return(0); |
return(0); |
} |
} |
|
|
|
int |
|
regexec(prog, string) |
|
register regexp *prog; |
|
register char *string; |
|
{ |
|
return regexec2(prog, string, 0); |
|
} |
|
|
/* |
/* |
- regtry - try match at specific point |
- regtry - try match at specific point |
*/ |
*/ |
|
|
regexp *prog; |
regexp *prog; |
char *string; |
char *string; |
{ |
{ |
int i; |
register int i; |
char **sp; |
register char **sp; |
char **ep; |
register char **ep; |
|
|
reginput = string; |
reginput = string; |
regstartp = prog->startp; |
regstartp = prog->startp; |
|
|
regmatch(prog) |
regmatch(prog) |
char *prog; |
char *prog; |
{ |
{ |
char *scan; /* Current node. */ |
register char *scan; /* Current node. */ |
char *next; /* Next node. */ |
char *next; /* Next node. */ |
|
|
scan = prog; |
scan = prog; |
|
|
reginput++; |
reginput++; |
break; |
break; |
case EXACTLY: { |
case EXACTLY: { |
int len; |
register int len; |
char *opnd; |
register char *opnd; |
|
|
opnd = OPERAND(scan); |
opnd = OPERAND(scan); |
/* Inline the first character, for speed. */ |
/* Inline the first character, for speed. */ |
|
|
case OPEN+7: |
case OPEN+7: |
case OPEN+8: |
case OPEN+8: |
case OPEN+9: { |
case OPEN+9: { |
int no; |
register int no; |
char *save; |
register char *save; |
|
|
no = OP(scan) - OPEN; |
no = OP(scan) - OPEN; |
save = reginput; |
save = reginput; |
|
|
case CLOSE+7: |
case CLOSE+7: |
case CLOSE+8: |
case CLOSE+8: |
case CLOSE+9: { |
case CLOSE+9: { |
int no; |
register int no; |
char *save; |
register char *save; |
|
|
no = OP(scan) - CLOSE; |
no = OP(scan) - CLOSE; |
save = reginput; |
save = reginput; |
|
|
/* NOTREACHED */ |
/* NOTREACHED */ |
break; |
break; |
case BRANCH: { |
case BRANCH: { |
char *save; |
register char *save; |
|
|
if (OP(next) != BRANCH) /* No choice. */ |
if (OP(next) != BRANCH) /* No choice. */ |
next = OPERAND(scan); /* Avoid recursion. */ |
next = OPERAND(scan); /* Avoid recursion. */ |
|
|
break; |
break; |
case STAR: |
case STAR: |
case PLUS: { |
case PLUS: { |
char nextch; |
register char nextch; |
int no; |
register int no; |
char *save; |
register char *save; |
int min; |
register int min; |
|
|
/* |
/* |
* Lookahead to avoid useless match attempts |
* Lookahead to avoid useless match attempts |
|
|
regrepeat(p) |
regrepeat(p) |
char *p; |
char *p; |
{ |
{ |
int count = 0; |
register int count = 0; |
char *scan; |
register char *scan; |
char *opnd; |
register char *opnd; |
|
|
scan = reginput; |
scan = reginput; |
opnd = OPERAND(p); |
opnd = OPERAND(p); |
|
|
*/ |
*/ |
static char * |
static char * |
regnext(p) |
regnext(p) |
char *p; |
register char *p; |
{ |
{ |
int offset; |
register int offset; |
|
|
if (p == ®dummy) |
if (p == ®dummy) |
return(NULL); |
return(NULL); |
|
|
regdump(r) |
regdump(r) |
regexp *r; |
regexp *r; |
{ |
{ |
char *s; |
register char *s; |
char op = EXACTLY; /* Arbitrary non-END op. */ |
register char op = EXACTLY; /* Arbitrary non-END op. */ |
char *next; |
register char *next; |
|
|
|
|
s = r->program + 1; |
s = r->program + 1; |
|
|
regprop(op) |
regprop(op) |
char *op; |
char *op; |
{ |
{ |
char *p; |
register char *p; |
static char buf[50]; |
static char buf[50]; |
|
|
(void) strlcpy(buf, ":", sizeof buf); |
(void) strlcpy(buf, ":", sizeof(buf)); |
|
|
switch (OP(op)) { |
switch (OP(op)) { |
case BOL: |
case BOL: |
|
|
case OPEN+7: |
case OPEN+7: |
case OPEN+8: |
case OPEN+8: |
case OPEN+9: |
case OPEN+9: |
snprintf(buf+strlen(buf), sizeof buf - strlen(buf), |
snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), |
"OPEN%d", OP(op)-OPEN); |
"OPEN%d", OP(op)-OPEN); |
p = NULL; |
p = NULL; |
break; |
break; |
|
|
case CLOSE+7: |
case CLOSE+7: |
case CLOSE+8: |
case CLOSE+8: |
case CLOSE+9: |
case CLOSE+9: |
snprintf(buf+strlen(buf), sizeof buf - strlen(buf), |
snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), |
"CLOSE%d", OP(op)-CLOSE); |
"CLOSE%d", OP(op)-CLOSE); |
p = NULL; |
p = NULL; |
break; |
break; |
|
|
break; |
break; |
} |
} |
if (p != NULL) |
if (p != NULL) |
(void) strlcat(buf, p, sizeof buf); |
(void) strlcat(buf, p, sizeof(buf)); |
return(buf); |
return(buf); |
} |
} |
#endif |
#endif |
|
|
char *s1; |
char *s1; |
char *s2; |
char *s2; |
{ |
{ |
char *scan1; |
register char *scan1; |
char *scan2; |
register char *scan2; |
int count; |
register int count; |
|
|
count = 0; |
count = 0; |
for (scan1 = s1; *scan1 != '\0'; scan1++) { |
for (scan1 = s1; *scan1 != '\0'; scan1++) { |