Пример #1
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);
}
Пример #2
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;
    }
}
Пример #3
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;
	}
}
Пример #4
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;
	}
}