示例#1
0
/*
 * Perform expansions on an argument, placing the resulting list of arguments
 * in arglist.  Parameter expansion, command substitution and arithmetic
 * expansion are always performed; additional expansions can be requested
 * via flag (EXP_*).
 * The result is left in the stack string.
 * When arglist is NULL, perform here document expansion.
 *
 * When doing something that may cause this to be re-entered, make sure
 * the stack string is empty via grabstackstr() and do not assume expdest
 * remains valid.
 */
void
expandarg(union node *arg, struct arglist *arglist, int flag)
{
	struct worddest exparg;
	struct nodelist *argbackq;

	if (fflag)
		flag &= ~EXP_GLOB;
	argbackq = arg->narg.backquote;
	exparg.list = arglist;
	exparg.state = WORD_IDLE;
	STARTSTACKSTR(expdest);
	argstr(arg->narg.text, &argbackq, flag, &exparg);
	if (arglist == NULL) {
		STACKSTRNUL(expdest);
		return;			/* here document expanded */
	}
	if ((flag & EXP_SPLIT) == 0 || expdest != stackblock() ||
	    exparg.state == WORD_QUOTEMARK) {
		STPUTC('\0', expdest);
		if (flag & EXP_SPLIT) {
			if (flag & EXP_GLOB)
				expandmeta(grabstackstr(expdest), exparg.list);
			else
				appendarglist(exparg.list, grabstackstr(expdest));
		}
	}
	if ((flag & EXP_SPLIT) == 0)
		appendarglist(arglist, grabstackstr(expdest));
}
示例#2
0
文件: expand.c 项目: gahr/poudriere
/*
 * 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;
}
示例#3
0
/*
 * 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;
}
示例#4
0
int
evalcmd(int argc, char **argv)
{
        char *p;
        char *concat;
        char **ap;

        if (argc > 1) {
                p = argv[1];
                if (argc > 2) {
                        STARTSTACKSTR(concat);
                        ap = argv + 2;
                        for (;;) {
                        	concat = stputs(p, concat);
                                if ((p = *ap++) == NULL)
                                        break;
                                STPUTC(' ', concat);
                        }
                        STPUTC('\0', concat);
                        p = grabstackstr(concat);
                }
                return evalstring(p, ~SKIPEVAL);
        }
        return 0;
}
示例#5
0
文件: eval.c 项目: dpl0/soc2013
int
evalcmd(int argc, char **argv)
{
        char *p;
        char *concat;
        char **ap;

        if (argc > 1) {
                p = argv[1];
                if (argc > 2) {
                        STARTSTACKSTR(concat);
                        ap = argv + 2;
                        for (;;) {
                                STPUTS(p, concat);
                                if ((p = *ap++) == NULL)
                                        break;
                                STPUTC(' ', concat);
                        }
                        STPUTC('\0', concat);
                        p = grabstackstr(concat);
                }
                evalstring(p, builtin_flags);
        } else
                exitstatus = 0;
        return exitstatus;
}
示例#6
0
/*
 *  The exp(1) builtin.
 */
int
letcmd(int argc, char **argv)
{
	const char *p;
	char *concat;
	char **ap;
	arith_t i;

	if (argc > 1) {
		p = argv[1];
		if (argc > 2) {
			/*
			 * Concatenate arguments.
			 */
			STARTSTACKSTR(concat);
			ap = argv + 2;
			for (;;) {
				while (*p)
					STPUTC(*p++, concat);
				if ((p = *ap++) == NULL)
					break;
				STPUTC(' ', concat);
			}
			STPUTC('\0', concat);
			p = grabstackstr(concat);
		}
	} else
		p = "";

	i = arith(p);

	out1fmt(ARITH_FORMAT_STR "\n", i);
	return !i;
}
示例#7
0
文件: eval.c 项目: dezelin/kBuild
int
evalcmd(shinstance *psh, int argc, char **argv)
{
	char *p;
	char *concat;
	char **ap;

	if (argc > 1) {
		p = argv[1];
		if (argc > 2) {
			STARTSTACKSTR(psh, concat);
			ap = argv + 2;
			for (;;) {
				while (*p)
					STPUTC(psh, *p++, concat);
				if ((p = *ap++) == NULL)
					break;
				STPUTC(psh, ' ', concat);
			}
			STPUTC(psh, '\0', concat);
			p = grabstackstr(psh, concat);
		}
		evalstring(psh, p, EV_TESTED);
	}
	return psh->exitstatus;
}
示例#8
0
文件: eval.c 项目: 7shi/minix-tools
int
evalcmd(int argc, char **argv)
{
        char *p;
        char *concat;
        char **ap;

        if (argc > 1) {
                p = argv[1];
                if (argc > 2) {
                        STARTSTACKSTR(concat);
                        ap = argv + 2;
                        for (;;) {
                                while (*p)
                                        STPUTC(*p++, concat);
                                if ((p = *ap++) == NULL)
                                        break;
                                STPUTC(' ', concat);
                        }
                        STPUTC('\0', concat);
                        p = grabstackstr(concat);
                }
                evalstring(p);
        }
        return exitstatus;
}
示例#9
0
/** handle one line of the read command.
 *  more fields than variables -> remainder shall be part of last variable.
 *  less fields than variables -> remaining variables unset.
 *
 *  @param line complete line of input
 *  @param ap argument (variable) list
 *  @param len length of line including trailing '\0'
 */
static void
readcmd_handle_line(char *s, char **ap)
{
	struct arglist arglist;
	struct strlist *sl;
	char *backup;
	char *line;

	/* ifsbreakup will fiddle with stack region... */
	line = stackblock();
	s = grabstackstr(s);

	/* need a copy, so that delimiters aren't lost
	 * in case there are more fields than variables */
	backup = sstrdup(line);

	arglist.lastp = &arglist.list;
	
	ifsbreakup(s, &arglist);
	*arglist.lastp = NULL;
	ifsfree();

	sl = arglist.list;

	do {
		if (!sl) {
			/* nullify remaining arguments */
			do {
				setvar(*ap, nullstr, 0);
			} while (*++ap);

			return;
		}

		/* remaining fields present, but no variables left. */
		if (!ap[1] && sl->next) {
			size_t offset;
			char *remainder;

			/* FIXME little bit hacky, assuming that ifsbreakup 
			 * will not modify the length of the string */
			offset = sl->text - s;
			remainder = backup + offset;
			rmescapes(remainder);
			setvar(*ap, remainder, 0);

			return;
		}
		
		/* set variable to field */
		rmescapes(sl->text);
		setvar(*ap, sl->text, 0);
		sl = sl->next;
	} while (*++ap);
}
示例#10
0
/*
 * Perform expansions on an argument, placing the resulting list of arguments
 * in arglist.  Parameter expansion, command substitution and arithmetic
 * expansion are always performed; additional expansions can be requested
 * via flag (EXP_*).
 * The result is left in the stack string.
 * When arglist is NULL, perform here document expansion.
 *
 * Caution: this function uses global state and is not reentrant.
 * However, a new invocation after an interrupted invocation is safe
 * and will reset the global state for the new call.
 */
void
expandarg(union node* arg, struct arglist* arglist, int32_t flag)
{
    struct strlist* sp;
    cstring_t p;
    argbackq = arg->narg.backquote;
    STARTSTACKSTR(expdest);
    ifsfirst.next = NULL;
    ifslastp = NULL;
    argstr(arg->narg.text, flag);
    if (arglist == NULL)
    {
        STACKSTRNUL(expdest);
        return;			/* here document expanded */
    }
    STPUTC('\0', expdest);
    p = grabstackstr(expdest);
    exparg.lastp = &exparg.list;
    /*
     * TODO - EXP_REDIR
     */
    if (flag & EXP_FULL)
    {
        ifsbreakup(p, &exparg);
        *exparg.lastp = NULL;
        exparg.lastp = &exparg.list;
        expandmeta(exparg.list, flag);
    }
    else
    {
        if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
            rmescapes(p);
        sp = (struct strlist*)stalloc(sizeof(struct strlist));
        sp->text = p;
        *exparg.lastp = sp;
        exparg.lastp = &sp->next;
    }
    while (ifsfirst.next != NULL)
    {
        pifsregion_t ifsp;
        INTOFF;
        ifsp = ifsfirst.next->next;
        ckfree(ifsfirst.next);
        ifsfirst.next = ifsp;
        INTON;
    }
    *exparg.lastp = NULL;
    if (exparg.list)
    {
        *arglist->lastp = exparg.list;
        arglist->lastp = exparg.lastp;
    }
}
示例#11
0
static char *
nextword(char c, int flag, char *p, struct worddest *dst)
{
	int is_ws;

	is_ws = c == '\t' || c == '\n' || c == ' ';
	if (p != stackblock() || (is_ws ? dst->state == WORD_QUOTEMARK :
	    dst->state != WORD_WS_DELIMITED) || c == '\0') {
		STPUTC('\0', p);
		if (flag & EXP_GLOB)
			expandmeta(grabstackstr(p), dst->list);
		else
			appendarglist(dst->list, grabstackstr(p));
		dst->state = is_ws ? WORD_WS_DELIMITED : WORD_IDLE;
	} else if (!is_ws && dst->state == WORD_WS_DELIMITED)
		dst->state = WORD_IDLE;
	/* Reserve space while the stack string is empty. */
	appendarglist(dst->list, NULL);
	dst->list->count--;
	STARTSTACKSTR(p);
	return p;
}
示例#12
0
文件: expand.c 项目: AhmadTux/freebsd
/*
 * 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);
}
示例#13
0
文件: expand.c 项目: pkelsey/freebsd
/*
 * 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;
}
示例#14
0
文件: expand.c 项目: gahr/poudriere
int
casematch(union node *pattern, const char *val)
{
	struct stackmark smark;
	int result;
	char *p;

	setstackmark(&smark);
	argbackq = pattern->narg.backquote;
	STARTSTACKSTR(expdest);
	argstr(pattern->narg.text, EXP_TILDE | EXP_CASE, NULL);
	STPUTC('\0', expdest);
	p = grabstackstr(expdest);
	result = patmatch(p, val);
	popstackmark(&smark);
	return result;
}
示例#15
0
int32_t
casematch(union node* pattern, const_cstring_t val)
{
    struct stackmark smark;
    int32_t result;
    cstring_t p;
    setstackmark(&smark);
    argbackq = pattern->narg.backquote;
    STARTSTACKSTR(expdest);
    ifslastp = NULL;
    argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
    STPUTC('\0', expdest);
    p = grabstackstr(expdest);
    result = patmatch(p, val, 0);
    popstackmark(&smark);
    return result;
}
示例#16
0
int
casematch(shinstance *psh, union node *pattern, char *val)
{
	struct stackmark smark;
	int result;
	char *p;

	setstackmark(psh, &smark);
	psh->argbackq = pattern->narg.backquote;
	STARTSTACKSTR(psh, psh->expdest);
	psh->ifslastp = NULL;
	argstr(psh, pattern->narg.text, EXP_TILDE | EXP_CASE);
	STPUTC(psh, '\0', psh->expdest);
	p = grabstackstr(psh, psh->expdest);
	result = patmatch(psh, p, val, 0);
	popstackmark(psh, &smark);
	return result;
}
示例#17
0
/*
 * Perform expansions on an argument, placing the resulting list of arguments
 * in arglist.  Parameter expansion, command substitution and arithmetic
 * expansion are always performed; additional expansions can be requested
 * via flag (EXP_*).
 * The result is left in the stack string.
 * When arglist is NULL, perform here document expansion.
 *
 * Caution: this function uses global state and is not reentrant.
 * However, a new invocation after an interrupted invocation is safe
 * and will reset the global state for the new call.
 */
void
expandarg(union node *arg, struct arglist *arglist, int flag)
{
	struct strlist *sp;
	char *p;

	argbackq = arg->narg.backquote;
	STARTSTACKSTR(expdest);
	ifsfirst.next = NULL;
	ifslastp = NULL;
	argstr(arg->narg.text, flag);
	if (arglist == NULL) {
		STACKSTRNUL(expdest);
		return;			/* here document expanded */
	}
	STPUTC('\0', expdest);
	p = grabstackstr(expdest);
	exparg.lastp = &exparg.list;
	if (flag & EXP_FULL) {
		ifsbreakup(p, &exparg);
		*exparg.lastp = NULL;
		exparg.lastp = &exparg.list;
		expandmeta(exparg.list);
	} else {
		sp = (struct strlist *)stalloc(sizeof (struct strlist));
		sp->text = p;
		*exparg.lastp = sp;
		exparg.lastp = &sp->next;
	}
	while (ifsfirst.next != NULL) {
		struct ifsregion *ifsp;
		INTOFF;
		ifsp = ifsfirst.next->next;
		ckfree(ifsfirst.next);
		ifsfirst.next = ifsp;
		INTON;
	}
	*exparg.lastp = NULL;
	if (exparg.list) {
		*arglist->lastp = exparg.list;
		arglist->lastp = exparg.lastp;
	}
}
示例#18
0
void
expandarg(shinstance *psh, union node *arg, struct arglist *arglist, int flag)
{
	struct strlist *sp;
	char *p;

	psh->argbackq = arg->narg.backquote;
	STARTSTACKSTR(psh, psh->expdest);
	psh->ifsfirst.next = NULL;
	psh->ifslastp = NULL;
	argstr(psh, arg->narg.text, flag);
	if (arglist == NULL) {
		return;			/* here document expanded */
	}
	STPUTC(psh, '\0', psh->expdest);
	p = grabstackstr(psh, psh->expdest);
	TRACE2((psh, "expandarg: p='%s'\n", p));
	psh->exparg.lastp = &psh->exparg.list;
	/*
	 * TODO - EXP_REDIR
	 */
	if (flag & EXP_FULL) {
		ifsbreakup(psh, p, &psh->exparg);
		*psh->exparg.lastp = NULL;
		psh->exparg.lastp = &psh->exparg.list;
		expandmeta(psh, psh->exparg.list, flag);
	} else {
		if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
			rmescapes(psh, p);
		sp = (struct strlist *)stalloc(psh, sizeof (struct strlist));
		sp->text = p;
		*psh->exparg.lastp = sp;
		psh->exparg.lastp = &sp->next;
	}
	ifsfree(psh);
	*psh->exparg.lastp = NULL;
	if (psh->exparg.list) {
		*arglist->lastp = psh->exparg.list;
		arglist->lastp = psh->exparg.lastp;
	}
}
示例#19
0
STATIC const char *
fc_replace(const char *s, char *p, char *r)
{
	char *dest;
	int plen = strlen(p);

	STARTSTACKSTR(dest);
	while (*s) {
		if (*s == *p && strncmp(s, p, plen) == 0) {
			while (*r)
				STPUTC(*r++, dest);
			s += plen;
			*p = '\0';	/* so no more matches */
		} else
			STPUTC(*s++, dest);
	}
	STACKSTRNUL(dest);
	dest = grabstackstr(dest);

	return (dest);
}
示例#20
0
/*
 * 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;
}
示例#21
0
文件: expand.c 项目: gahr/poudriere
/*
 * 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;
}
示例#22
0
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;
}
示例#23
0
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;
}