diff --git a/sh.decls.h b/sh.decls.h index a863fede..15b72bb4 100644 --- a/sh.decls.h +++ b/sh.decls.h @@ -300,6 +300,9 @@ extern int xopen (const char *, int, ...); extern ssize_t xread (int, void *, size_t); extern int xtcsetattr (int, int, const struct termios *); extern ssize_t xwrite (int, const void *, size_t); +extern int blkcmp (Char **, Char **); +extern void blkcmpfree (Char **, Char **); +extern void blkcmp_cleanup(void *); /* * sh.parse.c diff --git a/sh.dol.c b/sh.dol.c index b083b54d..345d1733 100644 --- a/sh.dol.c +++ b/sh.dol.c @@ -54,8 +54,6 @@ static Char *Dcp, *const *Dvp; /* Input vector for Dreadc */ #define unDgetC(c) Dpeekc = c -#define QUOTES (_QF|_QB|_ESC) /* \ ' " ` */ - /* * The following variables give the information about the current * $ expansion, recording the current word position, the remaining diff --git a/sh.exp.c b/sh.exp.c index f291a59d..084ac2b3 100644 --- a/sh.exp.c +++ b/sh.exp.c @@ -180,7 +180,40 @@ sh_access(const Char *fname, int mode) tcsh_number_t expr(Char ***vp) { - return (exp0(vp, 0)); + Char **vpi, **vpc, *nblk[2], **blks[2]; + tcsh_number_t i; + int len; + + *blks = blks[1] = NULL; + cleanup_push(blks, blkcmp_cleanup); + len = blklen(*vp) + 1; + vpi = *vp; + vpc = *blks = xmalloc(sizeof **blks * len); + nblk[1] = NULL; + while (*vpi) { + *nblk = Strsave(*vpi++); + (void) blkcpy(vpc++, nblk); + } + blks[1] = blkcpy(xmalloc(sizeof *blks[1] * len), vpc = *blks); + i = exp0(&vpc, 0); + *vp += --len - blklen(vpc); + { + Char **nvp; + + len -= blklen(vpc); + vpi = *blks; + cleanup_push(nvp = xmalloc(sizeof *nvp * (len + 1)), xfree); + while (vpi != vpc) { + *nblk = *vpi++; + (void) blkcpy(nvp++, nblk); + } + nvp -= len; + xechoit(nvp); + cleanup_until(nvp); + } + cleanup_until(blks); + + return i; } tcsh_number_t @@ -579,6 +612,19 @@ exp6(Char ***vp, int ignore) etraci("exp6 {} status", getstatus(), vp); return putn(getstatus() == 0); } + for (cp = **vp; *cp; cp++) + if (cmap(*cp, _DOL | QUOTES)) { + Char *buf; + + if (ignore & TEXP_IGNORE) { + (*vp)++; + return Strsave(STRNULL); + } + cleanup_push(cp = Dfix1(**vp), xfree); + *(*vp)++ = Strsave(buf = globone(cp, G_ERROR)); + cleanup_until(cp); + return buf; + } if (isa(**vp, ANYOP)) return (Strsave(STRNULL)); cp = *(*vp)++; diff --git a/sh.func.c b/sh.func.c index a9c0dd6f..eae51639 100644 --- a/sh.func.c +++ b/sh.func.c @@ -131,7 +131,11 @@ func(struct command *t, const struct biltins *bp) { int i; - xechoit(t->t_dcom); + if (bp->bfunct != doexit && + bp->bfunct != dolet && + bp->bfunct != doif && + bp->bfunct != dowhile) + xechoit(t->t_dcom); setname(bp->bname); i = blklen(t->t_dcom) - 1; if (i < bp->minargs) diff --git a/sh.h b/sh.h index 19bf10d6..6feaf5ec 100644 --- a/sh.h +++ b/sh.h @@ -1305,5 +1305,6 @@ extern int filec; #define TEXP_IGNORE 1 /* in ignore, it means to ignore value, just parse */ #define TEXP_NOGLOB 2 /* in ignore, it means not to globone */ +#define QUOTES (_QB|_QF|_ESC) /* \ " ' ` */ #endif /* _h_sh */ diff --git a/sh.misc.c b/sh.misc.c index 0b6b3370..fa35edea 100644 --- a/sh.misc.c +++ b/sh.misc.c @@ -721,3 +721,55 @@ xwrite(int fildes, const void *buf, size_t nbyte) while ((res = write(fildes, buf, nbyte)) == -1 && errno == EINTR); return res; } + +int +blkcmp(Char **fb, Char **sb) +{ + if (blklen(fb) != blklen(sb)) + return 1; + while (*fb == *sb++) + if (*fb++ == NULL) + return 0; + return 1; +} + +void +blkcmpfree(Char **fb, Char **sb) +{ + if (fb == NULL) + fb = xcalloc(1, sizeof *fb); + if (sb == NULL) + sb = xcalloc(1, sizeof *sb); + if (blkcmp(fb, sb)) { + Char **ofb, **osb; + + for (ofb = fb, osb = sb; *fb && *sb; fb++, sb++) { + if (*fb != *sb) + xfree(*sb); + xfree(*fb); + } + + while (*fb) + xfree(*fb++); + if (ofb != osb) + xfree(ofb); + while (*sb) + xfree(*sb++); + xfree(osb); + + return; + } + + if (fb != sb) + xfree(sb); + blkfree(fb); +} + +void +blkcmp_cleanup(void *xblks) +{ + Char **(*blks)[2]; + + blks = xblks; + blkcmpfree(**blks, (*blks)[1]); +} diff --git a/sh.sem.c b/sh.sem.c index 0674a2e3..f3e60add 100644 --- a/sh.sem.c +++ b/sh.sem.c @@ -83,7 +83,7 @@ void execute(struct command *t, volatile int wanttty, int *pipein, int *pipeout, int do_glob) { - int forked = 0; + int expr, forked = 0; const struct biltins * volatile bifunc; pid_t pid = 0; int pv[2]; @@ -188,7 +188,11 @@ execute(struct command *t, volatile int wanttty, int *pipein, int *pipeout, if ((t->t_dcom[0][0] & (QUOTE | TRIM)) == QUOTE) memmove(t->t_dcom[0], t->t_dcom[0] + 1, (Strlen(t->t_dcom[0] + 1) + 1) * sizeof (*t->t_dcom[0])); - if ((t->t_dflg & F_REPEAT) == 0) + if (!(expr = ((bifunc = isbfunc(t)) && + (bifunc->bfunct == doexit || + bifunc->bfunct == dolet || + bifunc->bfunct == doif || + bifunc->bfunct == dowhile)))) Dfix(t); /* $ " ' \ */ if (t->t_dcom[0] == 0) { return; @@ -290,10 +294,6 @@ execute(struct command *t, volatile int wanttty, int *pipein, int *pipeout, /* is it a command */ if (t->t_dtyp == NODE_COMMAND) { - /* - * Check if we have a builtin function and remember which one. - */ - bifunc = isbfunc(t); if (noexec) { /* * Continue for builtins that are part of the scripting language