1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-10-28 05:00:59 +01:00

10547: (#s) and (#e) pattern assertions

This commit is contained in:
Peter Stephenson 2000-04-06 18:44:01 +00:00
parent 181811bf80
commit d2330ba055
7 changed files with 875 additions and 276 deletions

View file

@ -83,6 +83,8 @@ typedef union upat *Upat;
#define P_ONEHASH 0x06 /* node Match this (simple) thing 0 or more times. */
#define P_TWOHASH 0x07 /* node Match this (simple) thing 1 or more times. */
#define P_GFLAGS 0x08 /* long Match nothing and set globbing flags */
#define P_ISSTART 0x09 /* no Match start of string. */
#define P_ISEND 0x0a /* no Match end of string. */
/* numbered so we can test bit 5 for a branch */
#define P_BRANCH 0x20 /* node Match this alternative, or the next... */
#define P_WBRANCH 0x21 /* uc* node P_BRANCH, but match at least 1 char */
@ -645,34 +647,44 @@ patcompbranch(int *flagp)
/* Globbing flags. */
char *pp1 = patparse;
int oldglobflags = patglobflags;
long assert;
patparse += (*patparse == '@') ? 3 : 2;
if (!patgetglobflags(&patparse))
return 0;
if (pp1 == patstart) {
/* Right at start of pattern, the simplest case.
* Put them into the flags and don't emit anything.
if (!patgetglobflags(&patparse, &assert))
return 0;
if (assert) {
/*
* Start/end assertion looking like flags, but
* actually handled as a normal node
*/
((Patprog)patout)->globflags = patglobflags;
continue;
} else if (!*patparse) {
/* Right at the end, so just leave the flags for
* the next Patprog in the chain to pick up.
*/
break;
}
/*
* Otherwise, we have to stick them in as a pattern
* matching nothing.
*/
if (oldglobflags != patglobflags) {
/* Flags changed */
union upat up;
latest = patnode(P_GFLAGS);
up.l = patglobflags;
patadd((char *)&up, 0, sizeof(union upat), 0);
latest = patnode(assert);
flags = 0;
} else {
/* No effect. */
continue;
if (pp1 == patstart) {
/* Right at start of pattern, the simplest case.
* Put them into the flags and don't emit anything.
*/
((Patprog)patout)->globflags = patglobflags;
continue;
} else if (!*patparse) {
/* Right at the end, so just leave the flags for
* the next Patprog in the chain to pick up.
*/
break;
}
/*
* Otherwise, we have to stick them in as a pattern
* matching nothing.
*/
if (oldglobflags != patglobflags) {
/* Flags changed */
union upat up;
latest = patnode(P_GFLAGS);
up.l = patglobflags;
patadd((char *)&up, 0, sizeof(union upat), 0);
} else {
/* No effect. */
continue;
}
}
} else if (isset(EXTENDEDGLOB) && *patparse == Hat) {
/*
@ -707,10 +719,12 @@ patcompbranch(int *flagp)
/**/
int
patgetglobflags(char **strp)
patgetglobflags(char **strp, long *assertp)
{
char *nptr, *ptr = *strp;
zlong ret;
*assertp = 0;
/* (#X): assumes we are still positioned on the first X */
for (; *ptr && *ptr != Outpar; ptr++) {
switch (*ptr) {
@ -763,12 +777,23 @@ patgetglobflags(char **strp)
patglobflags &= ~GF_MATCHREF;
break;
case 's':
*assertp = P_ISSTART;
break;
case 'e':
*assertp = P_ISEND;
break;
default:
return 0;
}
}
if (*ptr != Outpar)
return 0;
/* Start/end assertions must appear on their own. */
if (*assertp && (*strp)[1] != Outpar)
return 0;
*strp = ptr + 1;
return 1;
}
@ -1989,6 +2014,14 @@ patmatch(Upat prog)
* anything here.
*/
return 0;
case P_ISSTART:
if (patinput != patinstart)
fail = 1;
break;
case P_ISEND:
if (*patinput)
fail = 1;
break;
case P_END:
if (!(fail = (*patinput && !(patflags & PAT_NOANCH))))
return 1;
@ -2387,6 +2420,12 @@ patprop(Upat op)
case P_GFLAGS:
p = "GFLAGS";
break;
case P_ISSTART:
p = "ISSTART";
break;
case P_ISEND:
p = "ISEND";
break;
case P_NOTHING:
p = "NOTHING";
break;