mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-09-03 10:21:46 +02:00
zsh-workers/8319
This commit is contained in:
parent
2246999a84
commit
910dc80a58
6 changed files with 155 additions and 39 deletions
31
Src/cond.c
31
Src/cond.c
|
@ -107,16 +107,15 @@ evalcond(Cond c)
|
|||
left = dupstring((char *) c->left);
|
||||
singsub(&left);
|
||||
untokenize(left);
|
||||
if (c->right) {
|
||||
if (c->right && c->type != COND_STREQ && c->type != COND_STRNEQ) {
|
||||
right = dupstring((char *) c->right);
|
||||
singsub(&right);
|
||||
if (c->type != COND_STREQ && c->type != COND_STRNEQ)
|
||||
untokenize(right);
|
||||
untokenize(right);
|
||||
}
|
||||
|
||||
if (tracingcond) {
|
||||
if (c->type < COND_MOD) {
|
||||
char *rt = (char *)right;
|
||||
char *rt = (char *) right;
|
||||
if (c->type == COND_STREQ || c->type == COND_STRNEQ) {
|
||||
rt = dupstring(rt);
|
||||
untokenize(rt);
|
||||
|
@ -168,9 +167,29 @@ evalcond(Cond c)
|
|||
|
||||
switch (c->type) {
|
||||
case COND_STREQ:
|
||||
return matchpat(left, right);
|
||||
case COND_STRNEQ:
|
||||
return !matchpat(left, right);
|
||||
{
|
||||
Patprog pprog = c->prog;
|
||||
int test;
|
||||
|
||||
if (pprog == dummy_patprog1 || pprog == dummy_patprog2) {
|
||||
char *opat;
|
||||
int save;
|
||||
|
||||
right = opat = dupstring((char *) c->right);
|
||||
singsub(&right);
|
||||
save = (!strcmp(opat, right) && pprog != dummy_patprog2);
|
||||
|
||||
if (!(pprog = patcompile(right, (save ? PAT_ZDUP : PAT_STATIC),
|
||||
NULL)))
|
||||
zerr("bad pattern: %s", right, 0);
|
||||
else if (save)
|
||||
c->prog = pprog;
|
||||
}
|
||||
test = (pprog && pattry(pprog, left));
|
||||
|
||||
return (c->type == COND_STREQ ? test : !test);
|
||||
}
|
||||
case COND_STRLT:
|
||||
return strcmp(left, right) < 0;
|
||||
case COND_STRGTR:
|
||||
|
|
36
Src/loop.c
36
Src/loop.c
|
@ -422,10 +422,13 @@ execcase(Cmd cmd, LinkList args, int flags)
|
|||
char *word;
|
||||
List *l;
|
||||
char **p;
|
||||
Patprog *pp, pprog;
|
||||
int save;
|
||||
|
||||
node = cmd->u.casecmd;
|
||||
l = node->lists;
|
||||
p = node->pats;
|
||||
pp = node->progs;
|
||||
|
||||
word = dupstring(*p++);
|
||||
singsub(&word);
|
||||
|
@ -435,22 +438,47 @@ execcase(Cmd cmd, LinkList args, int flags)
|
|||
if (node) {
|
||||
cmdpush(CS_CASE);
|
||||
while (*p) {
|
||||
char *pat = dupstring(*p + 1);
|
||||
singsub(&pat);
|
||||
char *pat = NULL, *opat;
|
||||
|
||||
pprog = NULL;
|
||||
save = 0;
|
||||
|
||||
if (isset(XTRACE)) {
|
||||
char *pat2 = dupstring(pat);
|
||||
char *pat2;
|
||||
|
||||
opat = pat = dupstring(*p + 1);
|
||||
singsub(&pat);
|
||||
save = (!strcmp(pat, opat) && *pp != dummy_patprog2);
|
||||
|
||||
pat2 = dupstring(pat);
|
||||
untokenize(pat2);
|
||||
printprompt4();
|
||||
fprintf(stderr, "case %s (%s)\n", word, pat2);
|
||||
fflush(stderr);
|
||||
}
|
||||
if (matchpat(word, pat)) {
|
||||
if (*pp != dummy_patprog1 && *pp != dummy_patprog2)
|
||||
pprog = *pp;
|
||||
|
||||
if (!pprog) {
|
||||
if (!pat) {
|
||||
opat = pat = dupstring(*p + 1);
|
||||
singsub(&pat);
|
||||
save = (!strcmp(pat, opat) && *pp != dummy_patprog2);
|
||||
}
|
||||
if (!(pprog = patcompile(pat, (save ? PAT_ZDUP : PAT_STATIC),
|
||||
NULL)))
|
||||
zerr("bad pattern: %s", pat, 0);
|
||||
else if (save)
|
||||
*pp = pprog;
|
||||
}
|
||||
if (pprog && pattry(pprog, word)) {
|
||||
do {
|
||||
execlist(*l++, 1, **p == ';' && (flags & CFLAG_EXEC));
|
||||
} while(**p++ == '&' && *p);
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
pp++;
|
||||
l++;
|
||||
}
|
||||
cmdpop();
|
||||
|
|
26
Src/parse.c
26
Src/parse.c
|
@ -539,6 +539,7 @@ par_case(Cmd c)
|
|||
LinkList pats, lists;
|
||||
int n = 1;
|
||||
char **pp;
|
||||
Patprog *ppp;
|
||||
List *ll;
|
||||
LinkNode no;
|
||||
struct casecmd *cc;
|
||||
|
@ -659,11 +660,17 @@ par_case(Cmd c)
|
|||
incmdpos = 1;
|
||||
yylex();
|
||||
|
||||
cc->pats = (char **)alloc((n + 1) * sizeof(char *));
|
||||
cc->pats = (char **) alloc((n + 1) * sizeof(char *));
|
||||
cc->progs = (Patprog *) alloc((n + 1) * sizeof(Patprog));
|
||||
|
||||
for (pp = cc->pats, no = firstnode(pats); no; incnode(no))
|
||||
for (pp = cc->pats, ppp = cc->progs, no = firstnode(pats);
|
||||
no; incnode(no)) {
|
||||
*pp++ = (char *)getdata(no);
|
||||
*ppp++ = dummy_patprog1;
|
||||
}
|
||||
*pp = NULL;
|
||||
*ppp = NULL;
|
||||
|
||||
cc->lists = (List *) alloc((n + 1) * sizeof(List));
|
||||
for (ll = cc->lists, no = firstnode(lists); no; incnode(no), ll++)
|
||||
if (!(*ll = (List) getdata(no)))
|
||||
|
@ -1438,18 +1445,21 @@ par_cond_triple(char *a, char *b, char *c)
|
|||
Cond n = (Cond) make_cond();
|
||||
int t0;
|
||||
|
||||
n->ntype = NT_SET(N_COND, NT_STR, NT_STR, 0, 0);
|
||||
n->left = (void *) a;
|
||||
n->right = (void *) c;
|
||||
n->prog = dummy_patprog1;
|
||||
if ((b[0] == Equals || b[0] == '=') &&
|
||||
(!b[1] || ((b[1] == Equals || b[1] == '=') && !b[2])))
|
||||
(!b[1] || ((b[1] == Equals || b[1] == '=') && !b[2]))) {
|
||||
n->ntype = NT_SET(N_COND, NT_STR, NT_STR, NT_PAT, 0);
|
||||
n->type = COND_STREQ;
|
||||
else if (b[0] == '!' && (b[1] == Equals || b[1] == '=') && !b[2])
|
||||
} else if (b[0] == '!' && (b[1] == Equals || b[1] == '=') && !b[2]) {
|
||||
n->ntype = NT_SET(N_COND, NT_STR, NT_STR, NT_PAT, 0);
|
||||
n->type = COND_STRNEQ;
|
||||
else if (b[0] == '-') {
|
||||
if ((t0 = get_cond_num(b + 1)) > -1)
|
||||
} else if (b[0] == '-') {
|
||||
if ((t0 = get_cond_num(b + 1)) > -1) {
|
||||
n->ntype = NT_SET(N_COND, NT_STR, NT_STR, 0, 0);
|
||||
n->type = t0 + COND_NT;
|
||||
else {
|
||||
} else {
|
||||
char *d[3];
|
||||
|
||||
n->ntype = NT_SET(N_COND, NT_STR, NT_STR | NT_ARR, 0, 0);
|
||||
|
|
|
@ -427,8 +427,13 @@ patcompile(char *exp, int inflags, char **endexp)
|
|||
* The pattern was compiled in a fixed buffer: unless told otherwise,
|
||||
* we stick the compiled pattern on the heap. This is necessary
|
||||
* for files where we will often be compiling multiple segments at once.
|
||||
* But if we get the ZDUP flag w always put it in zalloc()ed memory.
|
||||
*/
|
||||
if (!(patflags & PAT_STATIC)) {
|
||||
if (patflags & PAT_ZDUP) {
|
||||
Patprog newp = (Patprog)zalloc(patsize);
|
||||
memcpy((char *)newp, (char *)p, patsize);
|
||||
p = newp;
|
||||
} else if (!(patflags & PAT_STATIC)) {
|
||||
Patprog newp = (Patprog)zhalloc(patsize);
|
||||
memcpy((char *)newp, (char *)p, patsize);
|
||||
p = newp;
|
||||
|
@ -2188,6 +2193,32 @@ static int patrepeat(Upat p)
|
|||
return count;
|
||||
}
|
||||
|
||||
/* Duplicate a patprog. */
|
||||
|
||||
/**/
|
||||
Patprog
|
||||
duppatprog(Patprog prog)
|
||||
{
|
||||
if (prog && prog != dummy_patprog1 && prog != dummy_patprog2) {
|
||||
Patprog ret = (Patprog) alloc(prog->size);
|
||||
|
||||
memcpy(ret, prog, prog->size);
|
||||
|
||||
return ret;
|
||||
}
|
||||
return prog;
|
||||
}
|
||||
|
||||
/* Free a patprog. */
|
||||
|
||||
/**/
|
||||
void
|
||||
freepatprog(Patprog prog)
|
||||
{
|
||||
if (prog && prog != dummy_patprog1 && prog != dummy_patprog2)
|
||||
zfree(prog, prog->size);
|
||||
}
|
||||
|
||||
/**/
|
||||
#ifdef ZSH_PAT_DEBUG
|
||||
|
||||
|
|
48
Src/utils.c
48
Src/utils.c
|
@ -1933,9 +1933,9 @@ static int flagtab[N_COUNT] = {
|
|||
NT_SET(N_PLINE, NT_NODE, NT_NODE, 0, 0),
|
||||
NT_SET(N_CMD, NT_NODE, NT_STR | NT_LIST, NT_NODE | NT_LIST, NT_NODE | NT_LIST),
|
||||
NT_SET(N_REDIR, NT_STR, 0, 0, 0),
|
||||
NT_SET(N_COND, NT_NODE, NT_NODE, 0, 0),
|
||||
NT_SET(N_COND, NT_NODE, NT_NODE, NT_PAT, 0),
|
||||
NT_SET(N_FOR, NT_STR, NT_STR, NT_STR, NT_NODE),
|
||||
NT_SET(N_CASE, NT_STR | NT_ARR, NT_NODE | NT_ARR, 0, 0),
|
||||
NT_SET(N_CASE, NT_STR | NT_ARR, NT_PAT | NT_ARR, NT_NODE | NT_ARR, 0),
|
||||
NT_SET(N_IF, NT_NODE | NT_ARR, NT_NODE | NT_ARR, 0, 0),
|
||||
NT_SET(N_WHILE, NT_NODE, NT_NODE, 0, 0),
|
||||
NT_SET(N_VARASG, NT_STR, NT_STR, NT_STR | NT_LIST, 0),
|
||||
|
@ -1983,18 +1983,27 @@ dupstruct(void *a)
|
|||
case NT_STR:
|
||||
n = dupstring(on);
|
||||
break;
|
||||
case NT_PAT:
|
||||
n = duppatprog(on);
|
||||
break;
|
||||
case NT_LIST | NT_NODE:
|
||||
n = duplist(on, (VFunc) dupstruct);
|
||||
break;
|
||||
case NT_LIST | NT_STR:
|
||||
n = duplist(on, (VFunc) (useheap ? dupstring : ztrdup));
|
||||
break;
|
||||
case NT_LIST | NT_PAT:
|
||||
n = duplist(on, (VFunc) duppatprog);
|
||||
break;
|
||||
case NT_NODE | NT_ARR:
|
||||
n = duparray(on, (VFunc) dupstruct);
|
||||
break;
|
||||
case NT_STR | NT_ARR:
|
||||
n = duparray(on, (VFunc) (useheap ? dupstring : ztrdup));
|
||||
break;
|
||||
case NT_PAT | NT_ARR:
|
||||
n = duparray(on, (VFunc) duppatprog);
|
||||
break;
|
||||
default:
|
||||
DPUTS(1, "BUG: bad node type in dupstruct()");
|
||||
abort();
|
||||
|
@ -2055,32 +2064,49 @@ ifreestruct(void *a)
|
|||
case NT_STR:
|
||||
zsfree((char *) n);
|
||||
break;
|
||||
case NT_PAT:
|
||||
freepatprog((Patprog) n);
|
||||
break;
|
||||
case NT_LIST | NT_NODE:
|
||||
freelinklist((LinkList) n, (FreeFunc) freestruct);
|
||||
break;
|
||||
case NT_NODE | NT_ARR:
|
||||
{
|
||||
void **p = (void **) n;
|
||||
|
||||
while (*p)
|
||||
freestruct(*p++);
|
||||
zfree(n, sizeof(void *) * (p + 1 - (void **) n));
|
||||
break;
|
||||
}
|
||||
case NT_LIST | NT_STR:
|
||||
freelinklist((LinkList) n, (FreeFunc) zsfree);
|
||||
break;
|
||||
case NT_LIST | NT_PAT:
|
||||
freelinklist((LinkList) n, (FreeFunc) freepatprog);
|
||||
break;
|
||||
case NT_NODE | NT_ARR:
|
||||
{
|
||||
void **p = (void **) n;
|
||||
|
||||
while (*p)
|
||||
freestruct(*p++);
|
||||
zfree(n, sizeof(void *) * (p + 1 - (void **) n));
|
||||
break;
|
||||
}
|
||||
case NT_STR | NT_ARR:
|
||||
freearray((char **) n);
|
||||
break;
|
||||
case NT_PAT | NT_ARR:
|
||||
{
|
||||
Patprog *p = (Patprog *) n;
|
||||
|
||||
while (*p)
|
||||
freepatprog(*p++);
|
||||
zfree(n, sizeof(void *) * ((void **) p + 1 - (void **) n));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
DPUTS(1, "BUG: bad node type in freenode()");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
DPUTS(size != ((char *) nodes) - ((char *) a),
|
||||
"BUG: size wrong in freenode()");
|
||||
#endif
|
||||
zfree(a, size);
|
||||
}
|
||||
|
||||
|
|
20
Src/zsh.h
20
Src/zsh.h
|
@ -392,6 +392,7 @@ struct node {
|
|||
#define NT_EMPTY 0
|
||||
#define NT_NODE 1
|
||||
#define NT_STR 2
|
||||
#define NT_PAT 3
|
||||
#define NT_LIST 4
|
||||
#define NT_ARR 8
|
||||
|
||||
|
@ -502,6 +503,7 @@ struct cond {
|
|||
int type; /* can be cond_type, or a single */
|
||||
/* letter (-a, -b, ...) */
|
||||
void *left, *right;
|
||||
Patprog prog; /* compiled pattern for `==' and `!=' */
|
||||
};
|
||||
|
||||
#define COND_NOT 0
|
||||
|
@ -555,18 +557,11 @@ struct forcmd { /* for/select */
|
|||
struct casecmd {
|
||||
/* Cmd->args contains word to test */
|
||||
int ntype; /* node type */
|
||||
char **pats;
|
||||
char **pats; /* pattern strings */
|
||||
Patprog *progs; /* compiled patterns (on demand) */
|
||||
List *lists; /* list to execute */
|
||||
};
|
||||
|
||||
|
||||
/* A command like "if foo then bar elif baz then fubar else fooble" */
|
||||
/* generates a tree like: */
|
||||
/* */
|
||||
/* struct ifcmd a = { next = &b, ifl = "foo", thenl = "bar" } */
|
||||
/* struct ifcmd b = { next = &c, ifl = "baz", thenl = "fubar" } */
|
||||
/* struct ifcmd c = { next = NULL, ifl = NULL, thenl = "fooble" } */
|
||||
|
||||
struct ifcmd {
|
||||
int ntype; /* node type */
|
||||
List *ifls;
|
||||
|
@ -974,6 +969,7 @@ struct patprog {
|
|||
#define PAT_PURES 0x0020 /* Pattern is a pure string: set internally */
|
||||
#define PAT_STATIC 0x0040 /* Don't copy pattern to heap as per default */
|
||||
#define PAT_SCAN 0x0080 /* Scanning, so don't try must-match test */
|
||||
#define PAT_ZDUP 0x0100 /* Copy pattern in real memory */
|
||||
|
||||
/* Globbing flags: lower 8 bits gives approx count */
|
||||
#define GF_LCMATCHUC 0x0100
|
||||
|
@ -981,6 +977,12 @@ struct patprog {
|
|||
#define GF_BACKREF 0x0400
|
||||
#define GF_MATCHREF 0x0800
|
||||
|
||||
/* Dummy Patprog pointers. Used mainly in executions trees, but the
|
||||
* pattern code needs to knwo about it, too. */
|
||||
|
||||
#define dummy_patprog1 ((Patprog) 1)
|
||||
#define dummy_patprog2 ((Patprog) 2)
|
||||
|
||||
/* node used in parameter hash table (paramtab) */
|
||||
|
||||
struct param {
|
||||
|
|
Loading…
Reference in a new issue