void singsub(char **s) { LinkList foo; foo = newlinklist(); addlinknode(foo, *s); prefork(foo, 4); if (errflag) return; *s = (char *) ugetnode(foo); DPUTS(nonempty(foo), "BUG: singsub() produced more than one word!"); }
int multsub(char **s, char ***a, int *isarr, char *sep) { LinkList foo; int l; char **r, **p; foo = newlinklist(); addlinknode(foo, *s); prefork(foo, 0); if (errflag) { if (isarr) *isarr = 0; return 0; } if ((l = countlinknodes(foo)) > 1) { p = r = ncalloc((l + 1) * sizeof(char*)); while (nonempty(foo)) *p++ = (char *)ugetnode(foo); *p = NULL; if (a) { *a = r; *isarr = 1; return 0; } *s = sepjoin(r, NULL); return 0; } if (l) *s = (char *) ugetnode(foo); else *s = dupstring(""); if (isarr) *isarr = 0; return !l; }
int execfor(Estate state, int do_exec) { Wordcode end, loop; wordcode code = state->pc[-1]; int iscond = (WC_FOR_TYPE(code) == WC_FOR_COND), ctok = 0, atok = 0; int last = 0; char *name, *str, *cond = NULL, *advance = NULL; zlong val = 0; LinkList vars = NULL, args = NULL; int old_simple_pline = simple_pline; /* See comments in execwhile() */ simple_pline = 1; end = state->pc + WC_FOR_SKIP(code); if (iscond) { str = dupstring(ecgetstr(state, EC_NODUP, NULL)); singsub(&str); if (isset(XTRACE)) { char *str2 = dupstring(str); untokenize(str2); printprompt4(); fprintf(xtrerr, "%s\n", str2); fflush(xtrerr); } if (!errflag) { matheval(str); } if (errflag) { state->pc = end; simple_pline = old_simple_pline; return 1; } cond = ecgetstr(state, EC_NODUP, &ctok); advance = ecgetstr(state, EC_NODUP, &atok); } else { vars = ecgetlist(state, *state->pc++, EC_NODUP, NULL); if (WC_FOR_TYPE(code) == WC_FOR_LIST) { int htok = 0; if (!(args = ecgetlist(state, *state->pc++, EC_DUPTOK, &htok))) { state->pc = end; simple_pline = old_simple_pline; return 0; } if (htok) { execsubst(args); if (errflag) { state->pc = end; simple_pline = old_simple_pline; return 1; } } } else { char **x; args = newlinklist(); for (x = pparams; *x; x++) addlinknode(args, dupstring(*x)); } } if (!args || empty(args)) lastval = 0; loops++; pushheap(); cmdpush(CS_FOR); loop = state->pc; while (!last) { if (iscond) { if (ctok) { str = dupstring(cond); singsub(&str); } else str = cond; if (!errflag) { while (iblank(*str)) str++; if (*str) { if (isset(XTRACE)) { printprompt4(); fprintf(xtrerr, "%s\n", str); fflush(xtrerr); } val = mathevali(str); } else val = 1; } if (errflag) { if (breaks) breaks--; lastval = 1; break; } if (!val) break; } else { LinkNode node; int count = 0; for (node = firstnode(vars); node; incnode(node)) { name = (char *)getdata(node); if (!args || !(str = (char *) ugetnode(args))) { if (count) { str = ""; last = 1; } else break; } if (isset(XTRACE)) { printprompt4(); fprintf(xtrerr, "%s=%s\n", name, str); fflush(xtrerr); } setsparam(name, ztrdup(str)); count++; } if (!count) break; } state->pc = loop; execlist(state, 1, do_exec && args && empty(args)); if (breaks) { breaks--; if (breaks || !contflag) break; contflag = 0; } if (retflag) break; if (iscond && !errflag) { if (atok) { str = dupstring(advance); singsub(&str); } else str = advance; if (isset(XTRACE)) { printprompt4(); fprintf(xtrerr, "%s\n", str); fflush(xtrerr); } if (!errflag) matheval(str); } if (errflag) { if (breaks) breaks--; lastval = 1; break; } freeheap(); } popheap(); cmdpop(); loops--; simple_pline = old_simple_pline; state->pc = end; return lastval; }
LinkNode stringsubst(LinkList list, LinkNode node, int ssub) { int qt; char *str3 = (char *)getdata(node); char *str = str3; while (!errflag && *str) { if ((qt = *str == Qstring) || *str == String) if (str[1] == Inpar) { str++; goto comsub; } else if (str[1] == Inbrack) { /* $[...] */ char *str2 = str; str2++; if (skipparens(Inbrack, Outbrack, &str2)) { zerr("closing bracket missing", NULL, 0); return NULL; } str2[-1] = *str = '\0'; str = arithsubst(str + 2, &str3, str2); setdata(node, (void *) str3); continue; } else { node = paramsubst(list, node, &str, qt, ssub); if (errflag || !node) return NULL; str3 = (char *)getdata(node); continue; } else if ((qt = *str == Qtick) || *str == Tick) comsub: { LinkList pl; char *s, *str2 = str; char endchar; int l1, l2; if (*str == Inpar) { endchar = Outpar; str[-1] = '\0'; if (skipparens(Inpar, Outpar, &str)) DPUTS(1, "Oops. parse error in command substitution"); str--; } else { endchar = *str; *str = '\0'; while (*++str != endchar) DPUTS(!*str, "Oops. parse error in command substitution"); } *str++ = '\0'; if (endchar == Outpar && str2[1] == '(' && str[-2] == ')') { /* Math substitution of the form $((...)) */ str = arithsubst(str2 + 1, &str3, str); setdata(node, (void *) str3); continue; } /* It is a command substitution, which will be parsed again * * by the lexer, so we untokenize it first, but we cannot use * * untokenize() since in the case of `...` some Bnulls should * * be left unchanged. Note that the lexer doesn't tokenize * * the body of a command substitution so if there are some * * tokens here they are from a ${(e)~...} substitution. */ for (str = str2; *++str; ) if (itok(*str) && *str != Nularg && !(endchar != Outpar && *str == Bnull && (str[1] == '$' || str[1] == '\\' || str[1] == '`' || (qt && str[1] == '"')))) *str = ztokens[*str - Pound]; str++; if (!(pl = getoutput(str2 + 1, qt || ssub))) { zerr("parse error in command substitution", NULL, 0); return NULL; } if (endchar == Outpar) str2--; if (!(s = (char *) ugetnode(pl))) { str = strcpy(str2, str); continue; } if (!qt && ssub && isset(GLOBSUBST)) tokenize(s); l1 = str2 - str3; l2 = strlen(s); if (nonempty(pl)) { LinkNode n = lastnode(pl); str2 = (char *) ncalloc(l1 + l2 + 1); strcpy(str2, str3); strcpy(str2 + l1, s); setdata(node, str2); insertlinklist(pl, node, list); s = (char *) getdata(node = n); l1 = 0; l2 = strlen(s); } str2 = (char *) ncalloc(l1 + l2 + strlen(str) + 1); if (l1) strcpy(str2, str3); strcpy(str2 + l1, s); str = strcpy(str2 + l1 + l2, str); str3 = str2; setdata(node, str3); continue; } str++; } return errflag ? NULL : node; }