/* * Expand arithmetic expression. */ static char * expari(char *p, int flag, struct worddest *dst) { char *q, *start; arith_t result; int begoff; int quoted; int adj; quoted = *p++ == '"'; begoff = expdest - stackblock(); p = argstr(p, 0, NULL); STPUTC('\0', expdest); start = stackblock() + begoff; q = grabstackstr(expdest); result = arith(start); ungrabstackstr(q, expdest); start = stackblock() + begoff; adj = start - expdest; STADJUST(adj, expdest); CHECKSTRSPACE((int)(DIGITS(result) + 1), expdest); fmtstr(expdest, DIGITS(result), ARITH_FORMAT_STR, result); adj = strlen(expdest); STADJUST(adj, expdest); if (!quoted) reprocess(expdest - adj - stackblock(), flag, VSNORMAL, 0, dst); return p; }
/* * Expand arithmetic expression. * Note that flag is not required as digits never require CTLESC characters. */ static char * expari(char *p) { char *q, *start; arith_t result; int begoff; int quoted; int adj; quoted = *p++ == '"'; begoff = expdest - stackblock(); p = argstr(p, 0); removerecordregions(begoff); STPUTC('\0', expdest); start = stackblock() + begoff; q = grabstackstr(expdest); result = arith(start); ungrabstackstr(q, expdest); start = stackblock() + begoff; adj = start - expdest; STADJUST(adj, expdest); CHECKSTRSPACE((int)(DIGITS(result) + 1), expdest); fmtstr(expdest, DIGITS(result), ARITH_FORMAT_STR, result); adj = strlen(expdest); STADJUST(adj, expdest); if (!quoted) recordregion(begoff, expdest - stackblock(), 0); return p; }
/* * Expand arithmetic expression. Backup to start of expression, * evaluate, place result in (backed up) result, adjust string position. */ void expari(int flag) { char *p, *q, *start; arith_t result; int begoff; int quotes = flag & (EXP_FULL | EXP_CASE | EXP_REDIR); int quoted; /* * This routine is slightly over-complicated for * efficiency. First we make sure there is * enough space for the result, which may be bigger * than the expression. Next we * scan backwards looking for the start of arithmetic. If the * next previous character is a CTLESC character, then we * have to rescan starting from the beginning since CTLESC * characters have to be processed left to right. */ CHECKSTRSPACE(DIGITS(result) - 2, expdest); USTPUTC('\0', expdest); start = stackblock(); p = expdest - 2; while (p >= start && *p != CTLARI) --p; if (p < start || *p != CTLARI) error("missing CTLARI (shouldn't happen)"); if (p > start && *(p - 1) == CTLESC) for (p = start; *p != CTLARI; p++) if (*p == CTLESC) p++; if (p[1] == '"') quoted=1; else quoted=0; begoff = p - start; removerecordregions(begoff); if (quotes) rmescapes(p+2); q = grabstackstr(expdest); result = arith(p+2); ungrabstackstr(q, expdest); fmtstr(p, DIGITS(result), ARITH_FORMAT_STR, result); while (*p++) ; if (quoted == 0) recordregion(begoff, p - 1 - start, 0); result = expdest - p + 1; STADJUST(-result, expdest); }
/* * Expand arithmetic expression. * Note that flag is not required as digits never require CTLESC characters. */ static char * expari(char *p) { char *q, *start; arith_t result; int begoff; int quoted; int c; int nesting; int adj; quoted = *p++ == '"'; begoff = expdest - stackblock(); argstr(p, 0); removerecordregions(begoff); STPUTC('\0', expdest); start = stackblock() + begoff; q = grabstackstr(expdest); result = arith(start); ungrabstackstr(q, expdest); start = stackblock() + begoff; adj = start - expdest; STADJUST(adj, expdest); CHECKSTRSPACE((int)(DIGITS(result) + 1), expdest); fmtstr(expdest, DIGITS(result), ARITH_FORMAT_STR, result); adj = strlen(expdest); STADJUST(adj, expdest); if (!quoted) recordregion(begoff, expdest - stackblock(), 0); nesting = 1; while (nesting > 0) { c = *p++; if (c == CTLESC) p++; else if (c == CTLARI) nesting++; else if (c == CTLENDARI) nesting--; else if (c == CTLVAR) p++; /* ignore variable substitution byte */ else if (c == '\0') return p - 1; } return p; }
/* * Perform command substitution. */ static void expbackq(union node *cmd, int quoted, int flag) { struct backcmd in; int i; char buf[128]; char *p; char *dest = expdest; struct ifsregion saveifs, *savelastp; struct nodelist *saveargbackq; char lastc; int startloc = dest - stackblock(); char const *syntax = quoted? DQSYNTAX : BASESYNTAX; int quotes = flag & (EXP_FULL | EXP_CASE); size_t nnl; INTOFF; saveifs = ifsfirst; savelastp = ifslastp; saveargbackq = argbackq; p = grabstackstr(dest); evalbackcmd(cmd, &in); ungrabstackstr(p, dest); ifsfirst = saveifs; ifslastp = savelastp; argbackq = saveargbackq; p = in.buf; lastc = '\0'; nnl = 0; /* Don't copy trailing newlines */ for (;;) { if (--in.nleft < 0) { if (in.fd < 0) break; while ((i = read(in.fd, buf, sizeof buf)) < 0 && errno == EINTR); TRACE(("expbackq: read returns %d\n", i)); if (i <= 0) break; p = buf; in.nleft = i - 1; } lastc = *p++; if (lastc != '\0') { if (lastc == '\n') { nnl++; } else { CHECKSTRSPACE(nnl + 2, dest); while (nnl > 0) { nnl--; USTPUTC('\n', dest); } if (quotes && syntax[(int)lastc] == CCTL) USTPUTC(CTLESC, dest); USTPUTC(lastc, dest); } } } if (in.fd >= 0) close(in.fd); if (in.buf) ckfree(in.buf); if (in.jp) exitstatus = waitforjob(in.jp, (int *)NULL); if (quoted == 0) recordregion(startloc, dest - stackblock(), 0); TRACE(("expbackq: size=%td: \"%.*s\"\n", ((dest - stackblock()) - startloc), (int)((dest - stackblock()) - startloc), stackblock() + startloc)); expdest = dest; INTON; }
STATIC void expbackq(shinstance *psh, union node *cmd, int quoted, int flag) { struct backcmd in; int i; char buf[128]; char *p; char *dest = psh->expdest; struct ifsregion saveifs, *savelastp; struct nodelist *saveargbackq; char lastc; int startloc = (int)(dest - stackblock(psh)); char const *syntax = quoted? DQSYNTAX : BASESYNTAX; int saveherefd; int quotes = flag & (EXP_FULL | EXP_CASE); #ifdef SH_DEAL_WITH_CRLF int pending_cr = 0; #endif INTOFF; saveifs = psh->ifsfirst; savelastp = psh->ifslastp; saveargbackq = psh->argbackq; saveherefd = psh->herefd; psh->herefd = -1; p = grabstackstr(psh, dest); evalbackcmd(psh, cmd, &in); ungrabstackstr(psh, p, dest); psh->ifsfirst = saveifs; psh->ifslastp = savelastp; psh->argbackq = saveargbackq; psh->herefd = saveherefd; p = in.buf; lastc = '\0'; for (;;) { if (--in.nleft < 0) { if (in.fd < 0) break; while ((i = shfile_read(&psh->fdtab, in.fd, buf, sizeof buf)) < 0 && errno == EINTR); TRACE((psh, "expbackq: read returns %d\n", i)); if (i <= 0) break; p = buf; in.nleft = i - 1; } lastc = *p++; #ifdef SH_DEAL_WITH_CRLF if (pending_cr) { pending_cr = 0; if (lastc != '\n') { if (quotes && syntax[(int)'\r'] == CCTL) STPUTC(psh, CTLESC, dest); STPUTC(psh, '\r', dest); } } if (lastc == '\r') pending_cr = '\r'; else #endif if (lastc != '\0') { if (quotes && syntax[(int)lastc] == CCTL) STPUTC(psh, CTLESC, dest); STPUTC(psh, lastc, dest); } } #ifdef SH_DEAL_WITH_CRLF if (pending_cr) { if (quotes && syntax[(int)'\r'] == CCTL) STPUTC(psh, CTLESC, dest); STPUTC(psh, '\r', dest); } #endif /* Eat all trailing newlines */ p = stackblock(psh) + startloc; while (dest > p && dest[-1] == '\n') STUNPUTC(psh, dest); if (in.fd >= 0) shfile_close(&psh->fdtab, in.fd); if (in.buf) ckfree(psh, in.buf); if (in.jp) psh->back_exitstatus = waitforjob(psh, in.jp); if (quoted == 0) recordregion(psh, startloc, (int)(dest - stackblock(psh)), 0); TRACE((psh, "evalbackq: size=%d: \"%.*s\"\n", (dest - stackblock(psh)) - startloc, (dest - stackblock(psh)) - startloc, stackblock(psh) + startloc)); psh->expdest = dest; INTON; }
STATIC void expbackq(union node *cmd, int quoted, int flag) { struct backcmd in; int i; char buf[128]; char *p; char *dest = expdest; struct ifsregion saveifs, *savelastp; struct nodelist *saveargbackq; char lastc; int startloc = dest - stackblock(); char const *syntax = quoted? DQSYNTAX : BASESYNTAX; int saveherefd; int quotes = flag & (EXP_FULL | EXP_CASE); INTOFF; saveifs = ifsfirst; savelastp = ifslastp; saveargbackq = argbackq; saveherefd = herefd; herefd = -1; p = grabstackstr(dest); evalbackcmd(cmd, &in); ungrabstackstr(p, dest); ifsfirst = saveifs; ifslastp = savelastp; argbackq = saveargbackq; herefd = saveherefd; p = in.buf; lastc = '\0'; for (;;) { if (--in.nleft < 0) { if (in.fd < 0) break; while ((i = read(in.fd, buf, sizeof buf)) < 0 && errno == EINTR); TRACE(("expbackq: read returns %d\n", i)); if (i <= 0) break; p = buf; in.nleft = i - 1; } lastc = *p++; if (lastc != '\0') { if (quotes && syntax[(int)lastc] == CCTL) STPUTC(CTLESC, dest); STPUTC(lastc, dest); } } /* Eat all trailing newlines */ p = stackblock() + startloc; while (dest > p && dest[-1] == '\n') STUNPUTC(dest); if (in.fd >= 0) close(in.fd); if (in.buf) ckfree(in.buf); if (in.jp) back_exitstatus = waitforjob(in.jp); if (quoted == 0) recordregion(startloc, dest - stackblock(), 0); TRACE(("evalbackq: size=%d: \"%.*s\"\n", (dest - stackblock()) - startloc, (dest - stackblock()) - startloc, stackblock() + startloc)); expdest = dest; INTON; }
/* * Perform command substitution. */ static void expbackq(union node *cmd, int quoted, int flag, struct worddest *dst) { struct backcmd in; int i; char buf[128]; char *p; char *dest = expdest; struct nodelist *saveargbackq; char lastc; char const *syntax = quoted? DQSYNTAX : BASESYNTAX; int quotes = flag & (EXP_GLOB | EXP_CASE); size_t nnl; const char *ifs; INTOFF; saveargbackq = argbackq; p = grabstackstr(dest); evalbackcmd(cmd, &in); ungrabstackstr(p, dest); argbackq = saveargbackq; p = in.buf; lastc = '\0'; nnl = 0; if (!quoted && flag & EXP_SPLIT) ifs = ifsset() ? ifsval() : " \t\n"; else ifs = ""; /* Don't copy trailing newlines */ for (;;) { if (--in.nleft < 0) { if (in.fd < 0) break; while ((i = read(in.fd, buf, sizeof buf)) < 0 && errno == EINTR); TRACE(("expbackq: read returns %d\n", i)); if (i <= 0) break; p = buf; in.nleft = i - 1; } lastc = *p++; if (lastc == '\0') continue; if (lastc == '\n') { nnl++; } else { if (nnl > 0) { if (strchr(ifs, '\n') != NULL) { NEXTWORD('\n', flag, dest, dst); nnl = 0; } else { CHECKSTRSPACE(nnl + 2, dest); while (nnl > 0) { nnl--; USTPUTC('\n', dest); } } } if (strchr(ifs, lastc) != NULL) NEXTWORD(lastc, flag, dest, dst); else { CHECKSTRSPACE(2, dest); if (quotes && syntax[(int)lastc] == CCTL) USTPUTC(CTLESC, dest); USTPUTC(lastc, dest); } } } if (in.fd >= 0) close(in.fd); if (in.buf) ckfree(in.buf); if (in.jp) exitstatus = waitforjob(in.jp, (int *)NULL); TRACE(("expbackq: size=%td: \"%.*s\"\n", ((dest - stackblock()) - startloc), (int)((dest - stackblock()) - startloc), stackblock() + startloc)); expdest = dest; INTON; }