From 35a8612f217f25a37caaed08b31be754cfe584b1 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Thu, 13 Nov 2008 21:18:14 +0000 Subject: 26042 with some fixes from 26043 (Mikael): allow <(...) and >(...) to occur in the middle of strings and =(...) to have extra text following --- Src/exec.c | 18 +++++++------ Src/lex.c | 17 ++++-------- Src/subst.c | 90 +++++++++++++++++++++++++++++++++++-------------------------- 3 files changed, 67 insertions(+), 58 deletions(-) (limited to 'Src') diff --git a/Src/exec.c b/Src/exec.c index 47c0184aa..a398211d3 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -3560,7 +3560,7 @@ readoutput(int in, int qt) /**/ static Eprog -parsecmd(char *cmd) +parsecmd(char *cmd, char **eptr) { char *str; Eprog prog; @@ -3571,7 +3571,9 @@ parsecmd(char *cmd) return NULL; } *str = '\0'; - if (str[1] || !(prog = parse_string(cmd + 2, 0))) { + if (eptr) + *eptr = str+1; + if (!(prog = parse_string(cmd + 2, 0))) { zerr("parse error in process substitution"); return NULL; } @@ -3582,7 +3584,7 @@ parsecmd(char *cmd) /**/ char * -getoutputfile(char *cmd) +getoutputfile(char *cmd, char **eptr) { pid_t pid; char *nam; @@ -3592,7 +3594,7 @@ getoutputfile(char *cmd) if (thisjob == -1) return NULL; - if (!(prog = parsecmd(cmd))) + if (!(prog = parsecmd(cmd, eptr))) return NULL; if (!(nam = gettempname(NULL, 0))) return NULL; @@ -3677,7 +3679,7 @@ namedpipe(void) /**/ char * -getproc(char *cmd) +getproc(char *cmd, char **eptr) { #if !defined(HAVE_FIFOS) && !defined(PATH_DEV_FD) zerr("doesn't look like your system supports FIFOs."); @@ -3696,7 +3698,7 @@ getproc(char *cmd) return NULL; if (!(pnam = namedpipe())) return NULL; - if (!(prog = parsecmd(cmd))) + if (!(prog = parsecmd(cmd, eptr))) return NULL; if (!jobtab[thisjob].filelist) jobtab[thisjob].filelist = znewlinklist(); @@ -3723,7 +3725,7 @@ getproc(char *cmd) if (thisjob == -1) return NULL; pnam = hcalloc(strlen(PATH_DEV_FD) + 6); - if (!(prog = parsecmd(cmd))) + if (!(prog = parsecmd(cmd, eptr))) return NULL; mpipe(pipes); if ((pid = zfork(&bgtime))) { @@ -3772,7 +3774,7 @@ getpipe(char *cmd, int nullexec) pid_t pid; struct timeval bgtime; - if (!(prog = parsecmd(cmd))) + if (!(prog = parsecmd(cmd, NULL))) return -1; mpipe(pipes); if ((pid = zfork(&bgtime))) { diff --git a/Src/lex.c b/Src/lex.c index 025387ca1..f5999d798 100644 --- a/Src/lex.c +++ b/Src/lex.c @@ -835,7 +835,7 @@ gettok(void) return OUTPAR; case LX1_INANG: d = hgetc(); - if (!incmdpos && d == '(') { + if (d == '(') { hungetc(d); lexstop = 0; unpeekfd: @@ -1152,20 +1152,13 @@ gettokstr(int c, int sub) c = Comma; break; case LX2_OUTANG: - if (!intpos) { - if (in_brace_param || sub) - break; - else - goto brk; - } + if (in_brace_param || sub) + break; e = hgetc(); if (e != '(') { hungetc(e); lexstop = 0; - if (in_brace_param || sub) - break; - else - goto brk; + goto brk; } add(Outang); if (skipcomm()) { @@ -1178,7 +1171,7 @@ gettokstr(int c, int sub) if (isset(SHGLOB) && sub) break; e = hgetc(); - if(e == '(' && intpos) { + if (!(in_brace_param || sub) && e == '(') { add(Inang); if (skipcomm()) { peek = LEXERR; diff --git a/Src/subst.c b/Src/subst.c index d76215838..5cc4748b8 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -56,43 +56,27 @@ prefork(LinkList list, int flags) queue_signals(); for (node = firstnode(list); node; incnode(node)) { - char *str, c; - - str = (char *)getdata(node); - if (((c = *str) == Inang || c == Outang || c == Equals) && - str[1] == Inpar) { - if (c == Inang || c == Outang) - setdata(node, (void *) getproc(str)); /* <(...) or >(...) */ - else - setdata(node, (void *) getoutputfile(str)); /* =(...) */ - if (!getdata(node)) { - setdata(node, dupstring("")); - unqueue_signals(); - return; - } - } else { - if (isset(SHFILEEXPANSION)) { - /* - * Here and below we avoid taking the address - * of a void * and then pretending it's a char ** - * instead of a void ** by a little inefficiency. - * This could be avoided with some extra linked list - * machinery, but that would need quite a lot of work - * to ensure consistency. What we really need is - * templates... - */ - char *cptr = (char *)getdata(node); - filesub(&cptr, flags & (PF_TYPESET|PF_ASSIGN)); - /* - * The assignment is so simple it's not worth - * testing if cptr changed... - */ - setdata(node, cptr); - } - if (!(node = stringsubst(list, node, flags & PF_SINGLE, asssub))) { - unqueue_signals(); - return; - } + if (isset(SHFILEEXPANSION)) { + /* + * Here and below we avoid taking the address + * of a void * and then pretending it's a char ** + * instead of a void ** by a little inefficiency. + * This could be avoided with some extra linked list + * machinery, but that would need quite a lot of work + * to ensure consistency. What we really need is + * templates... + */ + char *cptr = (char *)getdata(node); + filesub(&cptr, flags & (PF_TYPESET|PF_ASSIGN)); + /* + * The assignment is so simple it's not worth + * testing if cptr changed... + */ + setdata(node, cptr); + } + if (!(node = stringsubst(list, node, flags & PF_SINGLE, asssub))) { + unqueue_signals(); + return; } } for (node = firstnode(list); node; incnode(node)) { @@ -168,7 +152,37 @@ stringsubst(LinkList list, LinkNode node, int ssub, int asssub) char *str = str3, c; while (!errflag && (c = *str)) { - if ((qt = c == Qstring) || c == String) { + if ((c == Inang || c == Outang || (str == str3 && c == Equals)) && + str[1] == Inpar) { + char *subst, *rest, *snew, *sptr; + int str3len = str - str3, sublen, restlen; + + if (c == Inang || c == Outang) + subst = getproc(str, &rest); /* <(...) or >(...) */ + else + subst = getoutputfile(str, &rest); /* =(...) */ + if (!subst) + subst = ""; + + sublen = strlen(subst); + restlen = strlen(rest); + sptr = snew = hcalloc(str3len + sublen + restlen + 1); + if (str3len) { + memcpy(sptr, str3, str3len); + sptr += str3len; + } + if (sublen) { + memcpy(sptr, subst, sublen); + sptr += sublen; + } + if (restlen) + memcpy(sptr, rest, restlen); + sptr[restlen] = '\0'; + str3 = snew; + str = snew + str3len + sublen; + setdata(node, str3); + continue; + } else if ((qt = c == Qstring) || c == String) { if ((c = str[1]) == Inpar) { if (!qt) list->list.flags |= LF_ARRAY; -- cgit 1.4.1