Beispiel #1
0
/*
 * Pack up more characters in this word
 */
static int
Dpack(struct Strbuf *wbuf)
{
    eChar c;

    for (;;) {
	c = DgetC(DODOL);
	if (c == '\\') {
	    c = DgetC(0);
	    if (c == DEOF) {
		unDredc(c);
		return 1;
	    }
	    if (c == '\n')
		c = ' ';
	    else
		c |= QUOTE;
	}
	if (c == DEOF) {
	    unDredc(c);
	    return 1;
	}
	if (cmap(c, _SP | _NL | _QF | _QB)) {	/* sp \t\n'"` */
	    unDgetC(c);
	    if (cmap(c, QUOTES))
		return 0;
	    return 1;
	}
	Strbuf_append1(wbuf, (Char) c);
    }
}
Beispiel #2
0
static void
fixDolMod(void)
{
    int c;

    c = DgetC(0);
    if (c == ':') {
	do {
	    c = DgetC(0), dolmcnt = 1, dolwcnt = 1;
	    if (c == 'g' || c == 'a') {
		if (c == 'g')
		    dolmcnt = 10000;
		else
		    dolwcnt = 10000;
		c = DgetC(0);
	    }
	    if ((c == 'g' && dolmcnt != 10000) ||
		(c == 'a' && dolwcnt != 10000)) {
		if (c == 'g')
		    dolmcnt = 10000;
		else
		    dolwcnt = 10000;
		c = DgetC(0);
	    }

	    if (c == 's') {	/* [eichin:19910926.0755EST] */
		int delimcnt = 2;
		int delim = DgetC(0);
		dolmod[dolnmod++] = c;
		dolmod[dolnmod++] = delim;

		if (!delim || letter(delim)
		    || Isdigit(delim) || any(" \t\n", delim)) {
		    seterror(ERR_BADSUBST);
		    break;
		}
		while ((c = DgetC(0)) != (-1)) {
		    dolmod[dolnmod++] = c;
		    if(c == delim) delimcnt--;
		    if(!delimcnt) break;
		}
		if(delimcnt) {
		    seterror(ERR_BADSUBST);
		    break;
		}
		continue;
	    }
	    if (!any("htrqxes", c))
		stderror(ERR_BADMOD, c);
	    dolmod[dolnmod++] = c;
	    if (c == 'q')
		dolmcnt = 10000;
	}
	while ((c = DgetC(0)) == ':');
	unDredc(c);
    }
    else
	unDredc(c);
}
Beispiel #3
0
static void
fixDolMod(void)
{
    eChar c;

    c = DgetC(0);
    if (c == ':') {
	do {
	    c = DgetC(0), dolmcnt = 1, dol_flag_a = 0;
	    if (c == 'g' || c == 'a') {
		if (c == 'g')
		    dolmcnt = INT_MAX;
		else
		    dol_flag_a = 1;
		c = DgetC(0);
	    }
	    if ((c == 'g' && dolmcnt != INT_MAX) || 
		(c == 'a' && dol_flag_a == 0)) {
		if (c == 'g')
		    dolmcnt = INT_MAX;
		else
		    dol_flag_a = 1;
		c = DgetC(0);
	    }

	    if (c == 's') {	/* [eichin:19910926.0755EST] */
		int delimcnt = 2;
		eChar delim = DgetC(0);
		Strbuf_append1(&dolmod, (Char) c);
		Strbuf_append1(&dolmod, (Char) delim);

		if (delim == DEOF || !delim || letter(delim)
		    || Isdigit(delim) || any(" \t\n", delim)) {
		    seterror(ERR_BADSUBST);
		    break;
		}	
		while ((c = DgetC(0)) != DEOF) {
		    Strbuf_append1(&dolmod, (Char) c);
		    if(c == delim) delimcnt--;
		    if(!delimcnt) break;
		}
		if(delimcnt) {
		    seterror(ERR_BADSUBST);
		    break;
		}
		continue;
	    }
	    if (!any("luhtrqxes", c))
		stderror(ERR_BADMOD, (int)c);
	    Strbuf_append1(&dolmod, (Char) c);
	    if (c == 'q')
		dolmcnt = INT_MAX;
	}
	while ((c = DgetC(0)) == ':');
	unDredc(c);
    }
    else
	unDredc(c);
}
Beispiel #4
0
/*
 * Pack up more characters in this word
 */
static Char *
Dpack(Char *wbuf, Char *wp)
{
    int c;
    int i = MAXWLEN - (wp - wbuf);

    for (;;) {
	c = DgetC(DODOL);
	if (c == '\\') {
	    c = DgetC(0);
	    if (c == DEOF) {
		unDredc(c);
		*wp = 0;
		Gcat(STRNULL, wbuf);
		return (NULL);
	    }
	    if (c == '\n')
		c = ' ';
	    else
		c |= QUOTE;
	}
	if (c == DEOF) {
	    unDredc(c);
	    *wp = 0;
	    Gcat(STRNULL, wbuf);
	    return (NULL);
	}
	if (cmap(c, _SP | _NL | _QF | _QB)) {	/* sp \t\n'"` */
	    unDgetC(c);
	    if (cmap(c, QUOTES))
		return (wp);
	    *wp++ = 0;
	    Gcat(STRNULL, wbuf);
	    return (NULL);
	}
	if (--i <= 0)
	    stderror(ERR_WTOOLONG);
	*wp++ = c;
    }
}
Beispiel #5
0
/*
 * Subroutine to do actual fixing after state initialization.
 */
static void
Dfix2(Char **v)
{
    ginit();			/* Initialize glob's area pointers */
    Dvp = v;
    Dcp = STRNULL;		/* Setup input vector for Dreadc */
    unDgetC(0);
    unDredc(0);			/* Clear out any old peeks (at error) */
    dolp = 0;
    dolcnt = 0;			/* Clear out residual $ expands (...) */
    while (Dword())
	continue;
}
Beispiel #6
0
/*
 * Subroutine to do actual fixing after state initialization.
 */
void
Dfix2(tchar **v)
{
	tchar *agargv[GAVSIZ];

#ifdef TRACE
	tprintf("TRACE- Dfix2()\n");
#endif
	ginit(agargv);			/* Initialize glob's area pointers */
	Dvp = v; Dcp = S_ /* "" */;	/* Setup input vector for Dreadc */
	unDgetC(0); unDredc(0);		/* Clear out any old peeks (at error) */
	dolp = 0; dolcnt = 0;		/* Clear out residual $ expands (...) */
	while (Dword())
		continue;
	gargv = copyblk(gargv);
}
Beispiel #7
0
/*
 * Handle the multitudinous $ expansion forms.
 * Ugh.
 */
static void
Dgetdol(void)
{
    Char *np;
    struct varent *vp = NULL;
    Char    name[4 * MAXVARLEN + 1];
    int     c, sc;
    int     subscr = 0, lwb = 1, upb = 0;
    bool    dimen = 0, bitset = 0;
    char    tnp;
    Char    wbuf[BUFSIZ];
    static Char *dolbang = NULL;

    dolnmod = dolmcnt = dolwcnt = 0;
    c = sc = DgetC(0);
    if (c == '{')
	c = DgetC(0);		/* sc is { to take } later */
    if ((c & TRIM) == '#')
	dimen++, c = DgetC(0);	/* $# takes dimension */
    else if (c == '?')
	bitset++, c = DgetC(0);	/* $? tests existence */
    switch (c) {

    case '!':
	if (dimen || bitset)
	    stderror(ERR_SYNTAX);
	if (backpid != 0) {
	    if (dolbang)
		xfree(dolbang);
	    setDolp(dolbang = putn(backpid));
	}
	goto eatbrac;

    case '$':
	if (dimen || bitset)
	    stderror(ERR_SYNTAX);
	setDolp(doldol);
	goto eatbrac;

    case '<' | QUOTE:
	if (bitset)
	    stderror(ERR_NOTALLOWED, "$?<");
	if (dimen)
	    stderror(ERR_NOTALLOWED, "$?#");
	for (np = wbuf; read(OLDSTD, &tnp, 1) == 1; np++) {
	    *np = (unsigned char) tnp;
	    if (np >= &wbuf[BUFSIZ - 1])
		stderror(ERR_LTOOLONG);
	    if (tnp == '\n')
		break;
	}
	*np = 0;
	/*
	 * KLUDGE: dolmod is set here because it will cause setDolp to call
	 * domod and thus to copy wbuf. Otherwise setDolp would use it
	 * directly. If we saved it ourselves, no one would know when to free
	 * it. The actual function of the 'q' causes filename expansion not to
	 * be done on the interpolated value.
	 */
	dolmod[dolnmod++] = 'q';
	dolmcnt = 10000;
	setDolp(wbuf);
	goto eatbrac;

    case DEOF:
    case '\n':
	stderror(ERR_SYNTAX);
	/* NOTREACHED */
	break;

    case '*':
	(void) Strlcpy(name, STRargv, sizeof name/sizeof(Char));
	vp = adrof(STRargv);
	subscr = -1;		/* Prevent eating [...] */
	break;

    default:
	np = name;
	if (Isdigit(c)) {
	    if (dimen)
		stderror(ERR_NOTALLOWED, "$#<num>");
	    subscr = 0;
	    do {
		subscr = subscr * 10 + c - '0';
		c = DgetC(0);
	    } while (Isdigit(c));
	    unDredc(c);
	    if (subscr < 0)
		stderror(ERR_RANGE);
	    if (subscr == 0) {
		if (bitset) {
		    dolp = ffile ? STR1 : STR0;
		    goto eatbrac;
		}
		if (ffile == 0)
		    stderror(ERR_DOLZERO);
		fixDolMod();
		setDolp(ffile);
		goto eatbrac;
	    }
	    if (bitset)
		stderror(ERR_DOLQUEST);
	    vp = adrof(STRargv);
	    if (vp == 0) {
		vp = &nulargv;
		goto eatmod;
	    }
	    break;
	}
	if (!alnum(c))
	    stderror(ERR_VARALNUM);
	for (;;) {
	    *np++ = c;
	    c = DgetC(0);
	    if (!alnum(c))
		break;
	    if (np >= &name[MAXVARLEN])
		stderror(ERR_VARTOOLONG);
	}
	*np++ = 0;
	unDredc(c);
	vp = adrof(name);
    }
    if (bitset) {
	dolp = (vp || getenv(short2str(name))) ? STR1 : STR0;
	goto eatbrac;
    }
    if (vp == 0) {
	np = str2short(getenv(short2str(name)));
	if (np) {
	    fixDolMod();
	    setDolp(np);
	    goto eatbrac;
	}
	udvar(name);
	/* NOTREACHED */
    }
    c = DgetC(0);
    upb = blklen(vp->vec);
    if (dimen == 0 && subscr == 0 && c == '[') {
	np = name;
	for (;;) {
	    c = DgetC(DODOL);	/* Allow $ expand within [ ] */
	    if (c == ']')
		break;
	    if (c == '\n' || c == DEOF)
		stderror(ERR_INCBR);
	    if (np >= &name[sizeof(name) / sizeof(Char) - 2])
		stderror(ERR_VARTOOLONG);
	    *np++ = c;
	}
	*np = 0, np = name;
	if (dolp || dolcnt)	/* $ exp must end before ] */
	    stderror(ERR_EXPORD);
	if (!*np)
	    stderror(ERR_SYNTAX);
	if (Isdigit(*np)) {
	    int     i;

	    for (i = 0; Isdigit(*np); i = i * 10 + *np++ - '0')
		continue;
	    if ((i < 0 || i > upb) && !any("-*", *np)) {
		dolerror(vp->v_name);
		return;
	    }
	    lwb = i;
	    if (!*np)
		upb = lwb, np = STRstar;
	}
	if (*np == '*')
	    np++;
	else if (*np != '-')
	    stderror(ERR_MISSING, '-');
	else {
	    int i = upb;

	    np++;
	    if (Isdigit(*np)) {
		i = 0;
		while (Isdigit(*np))
		    i = i * 10 + *np++ - '0';
		if (i < 0 || i > upb) {
		    dolerror(vp->v_name);
		    return;
		}
	    }
	    if (i < lwb)
		upb = lwb - 1;
	    else
		upb = i;
	}
	if (lwb == 0) {
	    if (upb != 0) {
		dolerror(vp->v_name);
		return;
	    }
	    upb = -1;
	}
	if (*np)
	    stderror(ERR_SYNTAX);
    }
    else {
	if (subscr > 0) {
	    if (subscr > upb)
		lwb = 1, upb = 0;
	    else
		lwb = upb = subscr;
	}
	unDredc(c);
    }
    if (dimen) {
	Char   *cp = putn(upb - lwb + 1);

	addla(cp);
	xfree(cp);
    }
    else {
eatmod:
	fixDolMod();
	dolnxt = &vp->vec[lwb - 1];
	dolcnt = upb - lwb + 1;
    }
eatbrac:
    if (sc == '{') {
	c = Dredc();
	if (c != '}')
	    stderror(ERR_MISSING, '}');
    }
}
Beispiel #8
0
/*
 * Get a word.  This routine is analogous to the routine
 * word() in sh.lex.c for the main lexical input.  One difference
 * here is that we don't get a newline to terminate our expansion.
 * Rather, DgetC will return a DEOF when we hit the end-of-input.
 */
static int
Dword(void)
{
    int c, c1;
    Char    wbuf[BUFSIZ];
    Char *wp = wbuf;
    int i = MAXWLEN;
    bool dolflg;
    bool    sofar = 0, done = 0;

    while (!done) {
	done = 1;
	c = DgetC(DODOL);
	switch (c) {

	case DEOF:
	    if (sofar == 0)
		return (0);
	    /* finish this word and catch the code above the next time */
	    unDredc(c);
	    /* fall into ... */

	case '\n':
	    *wp = 0;
	    Gcat(STRNULL, wbuf);
	    return (1);

	case ' ':
	case '\t':
	    done = 0;
	    break;

	case '`':
	    /* We preserve ` quotations which are done yet later */
	    *wp++ = c, --i;
	case '\'':
	case '"':
	    /*
	     * Note that DgetC never returns a QUOTES character from an
	     * expansion, so only true input quotes will get us here or out.
	     */
	    c1 = c;
	    dolflg = c1 == '"' ? DODOL : 0;
	    for (;;) {
		c = DgetC(dolflg);
		if (c == c1)
		    break;
		if (c == '\n' || c == DEOF)
		    stderror(ERR_UNMATCHED, c1);
		if ((c & (QUOTE | TRIM)) == ('\n' | QUOTE))
		    --wp, ++i;
		if (--i <= 0)
		    stderror(ERR_WTOOLONG);
		switch (c1) {

		case '"':
		    /*
		     * Leave any `s alone for later. Other chars are all
		     * quoted, thus `...` can tell it was within "...".
		     */
		    *wp++ = c == '`' ? '`' : c | QUOTE;
		    break;

		case '\'':
		    /* Prevent all further interpretation */
		    *wp++ = c | QUOTE;
		    break;

		case '`':
		    /* Leave all text alone for later */
		    *wp++ = c;
		    break;

		default:
		    break;
		}
	    }
	    if (c1 == '`')
		*wp++ = '`' /* i--; eliminated */;
	    sofar = 1;
	    if ((wp = Dpack(wbuf, wp)) == NULL)
		return (1);
	    else {
		i = MAXWLEN - (wp - wbuf);
		done = 0;
	    }
	    break;

	case '\\':
	    c = DgetC(0);	/* No $ subst! */
	    if (c == '\n' || c == DEOF) {
		done = 0;
		break;
	    }
	    c |= QUOTE;
	    break;

	default:
	    break;
	}
	if (done) {
	    unDgetC(c);
	    sofar = 1;
	    if ((wp = Dpack(wbuf, wp)) == NULL)
		return (1);
	    else {
		i = MAXWLEN - (wp - wbuf);
		done = 0;
	    }
	}
    }
    /* Really NOTREACHED */
    return (0);
}
Beispiel #9
0
/*
 * Handle the multitudinous $ expansion forms.
 * Ugh.
 */
static void
Dgetdol(void)
{
    Char *np;
    struct varent *vp = NULL;
    struct Strbuf *name = Strbuf_alloc();
    eChar   c, sc;
    int     subscr = 0, lwb = 1, upb = 0;
    int    dimen = 0, bitset = 0, length = 0;
    static Char *dolbang = NULL;

    cleanup_push(name, Strbuf_free);
    dolmod.len = dolmcnt = dol_flag_a = 0;
    c = sc = DgetC(0);
    if (c == DEOF) {
      stderror(ERR_SYNTAX);
      return;
    }
    if (c == '{')
	c = DgetC(0);		/* sc is { to take } later */
    if ((c & TRIM) == '#')
	dimen++, c = DgetC(0);	/* $# takes dimension */
    else if (c == '?')
	bitset++, c = DgetC(0);	/* $? tests existence */
    else if (c == '%')
	length++, c = DgetC(0); /* $% returns length in chars */
    switch (c) {

    case '!':
	if (dimen || bitset || length)
	    stderror(ERR_SYNTAX);
	if (backpid != 0) {
	    xfree(dolbang);
	    setDolp(dolbang = putn((tcsh_number_t)backpid));
	}
	cleanup_until(name);
	goto eatbrac;

    case '$':
	if (dimen || bitset || length)
	    stderror(ERR_SYNTAX);
	setDolp(doldol);
	cleanup_until(name);
	goto eatbrac;

    case '<'|QUOTE: {
	static struct Strbuf wbuf; /* = Strbuf_INIT; */

	if (bitset)
	    stderror(ERR_NOTALLOWED, "$?<");
	if (dimen)
	    stderror(ERR_NOTALLOWED, "$#<");
	if (length)
	    stderror(ERR_NOTALLOWED, "$%<");
	wbuf.len = 0;
	{
	    char cbuf[MB_LEN_MAX];
	    size_t cbp = 0;
	    int old_pintr_disabled;

	    for (;;) {
	        int len;
		ssize_t res;
		Char wc;

		pintr_push_enable(&old_pintr_disabled);
		res = force_read(OLDSTD, cbuf + cbp, 1);
		cleanup_until(&old_pintr_disabled);
		if (res != 1)
		    break;
		cbp++;
		len = normal_mbtowc(&wc, cbuf, cbp);
		if (len == -1) {
		    reset_mbtowc();
		    if (cbp < MB_LEN_MAX)
		        continue; /* Maybe a partial character */
		    wc = (unsigned char)*cbuf | INVALID_BYTE;
		}
		if (len <= 0)
		    len = 1;
		if (cbp != (size_t)len)
		    memmove(cbuf, cbuf + len, cbp - len);
		cbp -= len;
		if (wc == '\n')
		    break;
		Strbuf_append1(&wbuf, wc);
	    }
	    while (cbp != 0) {
		int len;
		Char wc;

		len = normal_mbtowc(&wc, cbuf, cbp);
		if (len == -1) {
		    reset_mbtowc();
		    wc = (unsigned char)*cbuf | INVALID_BYTE;
		}
		if (len <= 0)
		    len = 1;
		if (cbp != (size_t)len)
		    memmove(cbuf, cbuf + len, cbp - len);
		cbp -= len;
		if (wc == '\n')
		    break;
		Strbuf_append1(&wbuf, wc);
	    }
	    Strbuf_terminate(&wbuf);
	}

	fixDolMod();
	setDolp(wbuf.s); /* Kept allocated until next $< expansion */
	cleanup_until(name);
	goto eatbrac;
    }

    case '*':
	Strbuf_append(name, STRargv);
	Strbuf_terminate(name);
	vp = adrof(STRargv);
	subscr = -1;		/* Prevent eating [...] */
	break;

    case DEOF:
    case '\n':
	np = dimen ? STRargv : (bitset ? STRstatus : NULL);
	if (np) {
	    bitset = 0;
	    Strbuf_append(name, np);
	    Strbuf_terminate(name);
	    vp = adrof(np);
	    subscr = -1;		/* Prevent eating [...] */
	    unDredc(c);
	    break;
	}
	else
	    stderror(ERR_SYNTAX);
	/*NOTREACHED*/

    default:
	if (Isdigit(c)) {
	    if (dimen)
		stderror(ERR_NOTALLOWED, "$#<num>");
	    subscr = 0;
	    do {
		subscr = subscr * 10 + c - '0';
		c = DgetC(0);
	    } while (c != DEOF && Isdigit(c));
	    unDredc(c);
	    if (subscr < 0)
		stderror(ERR_RANGE);
	    if (subscr == 0) {
		if (bitset) {
		    dolp = dolzero ? STR1 : STR0;
		    cleanup_until(name);
		    goto eatbrac;
		}
		if (ffile == 0)
		    stderror(ERR_DOLZERO);
		if (length) {
		    length = Strlen(ffile);
		    addla(putn((tcsh_number_t)length));
		}
		else {
		    fixDolMod();
		    setDolp(ffile);
		}
		cleanup_until(name);
		goto eatbrac;
	    }
#if 0
	    if (bitset)
		stderror(ERR_NOTALLOWED, "$?<num>");
	    if (length)
		stderror(ERR_NOTALLOWED, "$%<num>");
#endif
	    vp = adrof(STRargv);
	    if (vp == 0) {
		vp = &nulargv;
		cleanup_until(name);
		goto eatmod;
	    }
	    break;
	}
	if (c == DEOF || !alnum(c)) {
	    np = dimen ? STRargv : (bitset ? STRstatus : NULL);
	    if (np) {
		bitset = 0;
		Strbuf_append(name, np);
		Strbuf_terminate(name);
		vp = adrof(np);
		subscr = -1;		/* Prevent eating [...] */
		unDredc(c);
		break;
	    }
	    else
		stderror(ERR_VARALNUM);
	}
	for (;;) {
	    Strbuf_append1(name, (Char) c);
	    c = DgetC(0);
	    if (c == DEOF || !alnum(c))
		break;
	}
	Strbuf_terminate(name);
	unDredc(c);
	vp = adrof(name->s);
    }
    if (bitset) {
	dolp = (vp || getenv(short2str(name->s))) ? STR1 : STR0;
	cleanup_until(name);
	goto eatbrac;
    }
    if (vp == NULL || vp->vec == NULL) {
	np = str2short(getenv(short2str(name->s)));
	if (np) {
	    static Char *env_val; /* = NULL; */

	    cleanup_until(name);
	    fixDolMod();
	    if (length) {
		    addla(putn((tcsh_number_t)Strlen(np)));
	    } else {
		    xfree(env_val);
		    env_val = Strsave(np);
		    setDolp(env_val);
	    }
	    goto eatbrac;
	}
	udvar(name->s);
	/* NOTREACHED */
    }
    cleanup_until(name);
    c = DgetC(0);
    upb = blklen(vp->vec);
    if (dimen == 0 && subscr == 0 && c == '[') {
	name = Strbuf_alloc();
	cleanup_push(name, Strbuf_free);
	np = name->s;
	for (;;) {
	    c = DgetC(DODOL);	/* Allow $ expand within [ ] */
	    if (c == ']')
		break;
	    if (c == '\n' || c == DEOF)
		stderror(ERR_INCBR);
	    Strbuf_append1(name, (Char) c);
	}
	Strbuf_terminate(name);
	np = name->s;
	if (dolp || dolcnt)	/* $ exp must end before ] */
	    stderror(ERR_EXPORD);
	if (!*np)
	    stderror(ERR_SYNTAX);
	if (Isdigit(*np)) {
	    int     i;

	    for (i = 0; Isdigit(*np); i = i * 10 + *np++ - '0')
		continue;
	    if (i < 0 || (i > upb && !any("-*", *np))) {
		cleanup_until(name);
		dolerror(vp->v_name);
		return;
	    }
	    lwb = i;
	    if (!*np)
		upb = lwb, np = STRstar;
	}
	if (*np == '*')
	    np++;
	else if (*np != '-')
	    stderror(ERR_MISSING, '-');
	else {
	    int i = upb;

	    np++;
	    if (Isdigit(*np)) {
		i = 0;
		while (Isdigit(*np))
		    i = i * 10 + *np++ - '0';
		if (i < 0 || i > upb) {
		    cleanup_until(name);
		    dolerror(vp->v_name);
		    return;
		}
	    }
	    if (i < lwb)
		upb = lwb - 1;
	    else
		upb = i;
	}
	if (lwb == 0) {
	    if (upb != 0) {
		cleanup_until(name);
		dolerror(vp->v_name);
		return;
	    }
	    upb = -1;
	}
	if (*np)
	    stderror(ERR_SYNTAX);
	cleanup_until(name);
    }
    else {
	if (subscr > 0) {
	    if (subscr > upb)
		lwb = 1, upb = 0;
	    else
		lwb = upb = subscr;
	}
	unDredc(c);
    }
    if (dimen) {
	/* this is a kludge. It prevents Dgetdol() from */
	/* pushing erroneous ${#<error> values into the labuf. */
	if (sc == '{') {
	    c = Dredc();
	    if (c != '}')
		stderror(ERR_MISSING, '}');
	    unDredc(c);
	}
	addla(putn((tcsh_number_t)(upb - lwb + 1)));
    }
    else if (length) {
	int i;

	for (i = lwb - 1, length = 0; i < upb; i++)
	    length += Strlen(vp->vec[i]);
#ifdef notdef
	/* We don't want that, since we can always compute it by adding $#xxx */
	length += i - 1;	/* Add the number of spaces in */
#endif
	addla(putn((tcsh_number_t)length));
    }
    else {
eatmod:
	fixDolMod();
	dolnxt = &vp->vec[lwb - 1];
	dolcnt = upb - lwb + 1;
    }
eatbrac:
    if (sc == '{') {
	c = Dredc();
	if (c != '}')
	    stderror(ERR_MISSING, '}');
    }
}
Beispiel #10
0
/*
 * Get a word.  This routine is analogous to the routine
 * word() in sh.lex.c for the main lexical input.  One difference
 * here is that we don't get a newline to terminate our expansion.
 * Rather, DgetC will return a DEOF when we hit the end-of-input.
 */
static int
Dword(struct blk_buf *bb)
{
    eChar c, c1;
    struct Strbuf *wbuf = Strbuf_alloc();
    int dolflg;
    int    sofar = 0;
    Char *str;

    cleanup_push(wbuf, Strbuf_free);
    for (;;) {
	c = DgetC(DODOL);
	switch (c) {

	case DEOF:
	    if (sofar == 0) {
		cleanup_until(wbuf);
		return (0);
	    }
	    /* finish this word and catch the code above the next time */
	    unDredc(c);
	    /*FALLTHROUGH*/

	case '\n':
	    goto end;

	case ' ':
	case '\t':
	    continue;

	case '`':
	    /* We preserve ` quotations which are done yet later */
	    Strbuf_append1(wbuf, (Char) c);
	    /*FALLTHROUGH*/
	case '\'':
	case '"':
	    /*
	     * Note that DgetC never returns a QUOTES character from an
	     * expansion, so only true input quotes will get us here or out.
	     */
	    c1 = c;
	    dolflg = c1 == '"' ? DODOL : 0;
	    for (;;) {
		c = DgetC(dolflg);
		if (c == c1)
		    break;
		if (c == '\n' || c == DEOF) {
		    cleanup_until(bb);
		    stderror(ERR_UNMATCHED, (int)c1);
		}
		if ((c & (QUOTE | TRIM)) == ('\n' | QUOTE)) {
		    if (wbuf->len != 0 && (wbuf->s[wbuf->len - 1] & TRIM) == '\\')
			wbuf->len--;
		}
		switch (c1) {

		case '"':
		    /*
		     * Leave any `s alone for later. Other chars are all
		     * quoted, thus `...` can tell it was within "...".
		     */
		    Strbuf_append1(wbuf, c == '`' ? '`' : c | QUOTE);
		    break;

		case '\'':
		    /* Prevent all further interpretation */
		    Strbuf_append1(wbuf, c | QUOTE);
		    break;

		case '`':
		    /* Leave all text alone for later */
		    Strbuf_append1(wbuf, (Char) c);
		    break;

		default:
		    break;
		}
	    }
	    if (c1 == '`')
		Strbuf_append1(wbuf, '`');
	    sofar = 1;
	    if (Dpack(wbuf) != 0)
		goto end;
	    continue;

	case '\\':
	    c = DgetC(0);	/* No $ subst! */
	    if (c == '\n' || c == DEOF)
		continue;
	    c |= QUOTE;
	    break;

	default:
	    break;
	}
	unDgetC(c);
	sofar = 1;
	if (Dpack(wbuf) != 0)
	    goto end;
    }

 end:
    cleanup_ignore(wbuf);
    cleanup_until(wbuf);
    str = Strbuf_finish(wbuf);
    bb_append(bb, str);
    xfree(wbuf);
    return 1;
}
Beispiel #11
0
/*
 * Handle the multitudinous $ expansion forms.
 * Ugh.
 */
void
Dgetdol(void)
{
	tchar *np;
	struct varent *vp;
	tchar name[MAX_VREF_LEN];
	int c, sc;
	int subscr = 0, lwb = 1, upb = 0;
	bool dimen = 0, bitset = 0;
	tchar wbuf[BUFSIZ + MB_LEN_MAX]; /* read_ may return extra bytes */

#ifdef TRACE
	tprintf("TRACE- Dgetdol()\n");
#endif
	dolmod = dolmcnt = 0;
	c = sc = DgetC(0);
	if (c == '{')
		c = DgetC(0);		/* sc is { to take } later */
	if ((c & TRIM) == '#')
		dimen++, c = DgetC(0);		/* $# takes dimension */
	else if (c == '?')
		bitset++, c = DgetC(0);		/* $? tests existence */
	switch (c) {

	case '$':
		if (dimen || bitset)
syntax:
		error("Variable syntax");  /* No $?$, $#$ */
		setDolp(doldol);
		goto eatbrac;

	case '<'|QUOTE:
		if (dimen || bitset)
			goto syntax;		/* No $?<, $#< */
		for (np = wbuf; read_(OLDSTD, np, 1) == 1; np++) {
			if (np >= &wbuf[BUFSIZ-1])
				error("$< line too long");
			if (*np <= 0 || *np == '\n')
				break;
		}
		*np = 0;
		/*
		 * KLUDGE: dolmod is set here because it will
		 * cause setDolp to call domod and thus to copy wbuf.
		 * Otherwise setDolp would use it directly. If we saved
		 * it ourselves, no one would know when to free it.
		 * The actual function of the 'q' causes filename
		 * expansion not to be done on the interpolated value.
		 */
		dolmod = 'q';
		dolmcnt = 10000;
		setDolp(wbuf);
		goto eatbrac;

	case DEOF:
	case '\n':
		goto syntax;

	case '*':
		(void) strcpy_(name, S_argv);
		vp = adrof(S_argv);
		subscr = -1;			/* Prevent eating [...] */
		break;

	default:
		np = name;
		if (digit(c)) {
			if (dimen)
				goto syntax;	/* No $#1, e.g. */
			subscr = 0;
			do {
				subscr = subscr * 10 + c - '0';
				c = DgetC(0);
			} while (digit(c));
			unDredc(c);
			if (subscr < 0)
				error("Subscript out of range");
			if (subscr == 0) {
				if (bitset) {
					dolp = file ? S_1 /* "1" */ : S_0 /* "0" */;
					goto eatbrac;
				}
				if (file == 0)
					error("No file for $0");
				setDolp(file);
				goto eatbrac;
			}
			if (bitset)
				goto syntax;
			vp = adrof(S_argv);
			if (vp == 0) {
				vp = &nulargv;
				goto eatmod;
			}
			break;
		}
		if (!alnum(c))
			goto syntax;
		for (;;) {
			*np++ = c;
			c = DgetC(0);
			if (!alnum(c))
				break;
			/* if variable name is > 20, complain */
			if (np >= &name[MAX_VAR_LEN])
				error("Variable name too long");

		}
		*np++ = 0;
		unDredc(c);
		vp = adrof(name);
	}
	if (bitset) {
		/*
		 * getenv() to getenv_(), because 'name''s type is now tchar *
		 * no need to xalloc
		 */
		dolp = (vp || getenv_(name)) ? S_1 /* "1" */ : S_0 /* "0" */;
		goto eatbrac;
	}
	if (vp == 0) {
		/*
		 * getenv() to getenv_(), because 'name''s type is now tchar *
		 * no need to xalloc
		 */
		np = getenv_(name);
		if (np) {
			addla(np);
			goto eatbrac;
		}
		udvar(name);
		/*NOTREACHED*/
	}
	c = DgetC(0);
	upb = blklen(vp->vec);
	if (dimen == 0 && subscr == 0 && c == '[') {
		np = name;
		for (;;) {
			c = DgetC(DODOL);	/* Allow $ expand within [ ] */
			if (c == ']')
				break;
			if (c == '\n' || c == DEOF)
				goto syntax;
			if (np >= &name[MAX_VREF_LEN])
				error("Variable reference too long");
			*np++ = c;
		}
		*np = 0, np = name;
		if (dolp || dolcnt)		/* $ exp must end before ] */
			goto syntax;
		if (!*np)
			goto syntax;
		if (digit(*np)) {
			int i = 0;

			while (digit(*np))
				i = i * 10 + *np++ - '0';
/*			if ((i < 0 || i > upb) && !any(*np, "-*")) { */
			if ((i < 0 || i > upb) && (*np != '-') && (*np != '*')) {
oob:
				setname(vp->v_name);
				error("Subscript out of range");
			}
			lwb = i;
			if (!*np)
				upb = lwb, np = S_AST /* "*" */;
		}
		if (*np == '*')
			np++;
		else if (*np != '-')
			goto syntax;
		else {
			int i = upb;

			np++;
			if (digit(*np)) {
				i = 0;
				while (digit(*np))
					i = i * 10 + *np++ - '0';
				if (i < 0 || i > upb)
					goto oob;
			}
			if (i < lwb)
				upb = lwb - 1;
			else
				upb = i;
		}
		if (lwb == 0) {
			if (upb != 0)
				goto oob;
			upb = -1;
		}
		if (*np)
			goto syntax;
	} else {
		if (subscr > 0)
			if (subscr > upb)
				lwb = 1, upb = 0;
			else
				lwb = upb = subscr;
		unDredc(c);
	}
	if (dimen) {
		tchar *cp = putn(upb - lwb + 1);

		addla(cp);
		xfree(cp);
	} else {
eatmod:
		c = DgetC(0);
		if (c == ':') {
			c = DgetC(0), dolmcnt = 1;
			if (c == 'g')
				c = DgetC(0), dolmcnt = 10000;
			if (!any(c, S_htrqxe))
				error("Bad : mod in $");
			dolmod = c;
			if (c == 'q')
				dolmcnt = 10000;
		} else
			unDredc(c);
		dolnxt = &vp->vec[lwb - 1];
		dolcnt = upb - lwb + 1;
	}
eatbrac:
	if (sc == '{') {
		c = Dredc();
		if (c != '}')
			goto syntax;
	}
}
Beispiel #12
0
/*
 * Get a word.  This routine is analogous to the routine
 * word() in sh.lex.c for the main lexical input.  One difference
 * here is that we don't get a newline to terminate our expansion.
 * Rather, DgetC will return a DEOF when we hit the end-of-input.
 */
int
Dword(void)
{
	int c, c1;
	static tchar *wbuf = NULL;
	static int wbufsiz = BUFSIZ;
	int wp = 0;
	bool dolflg;
	bool sofar = 0;
#define	DYNAMICBUFFER() \
	do { \
		if (wp >= wbufsiz) { \
			wbufsiz += BUFSIZ; \
			wbuf = xrealloc(wbuf, (wbufsiz+1) * sizeof (tchar)); \
		} \
	} while (0)

#ifdef TRACE
	tprintf("TRACE- Dword()\n");
#endif
	if (wbuf == NULL)
		wbuf = xalloc((wbufsiz+1) * sizeof (tchar));
loop:
	c = DgetC(DODOL);
	switch (c) {

	case DEOF:
deof:
		if (sofar == 0)
			return (0);
		/* finish this word and catch the code above the next time */
		unDredc(c);
		/* fall into ... */

	case '\n':
		wbuf[wp] = 0;
		goto ret;

	case ' ':
	case '\t':
		goto loop;

	case '`':
		/* We preserve ` quotations which are done yet later */
		wbuf[wp++] = c;
	case '\'':
	case '"':
		/*
		 * Note that DgetC never returns a QUOTES character
		 * from an expansion, so only true input quotes will
		 * get us here or out.
		 */
		c1 = c;
		dolflg = c1 == '"' ? DODOL : 0;
		for (;;) {
			c = DgetC(dolflg);
			if (c == c1)
				break;
			if (c == '\n' || c == DEOF)
				error("Unmatched %c", (tchar) c1);
			if ((c & (QUOTE|TRIM)) == ('\n' | QUOTE))
				--wp;
			DYNAMICBUFFER();
			switch (c1) {

			case '"':
				/*
				 * Leave any `s alone for later.
				 * Other chars are all quoted, thus `...`
				 * can tell it was within "...".
				 */
				wbuf[wp++] = c == '`' ? '`' : c | QUOTE;
				break;

			case '\'':
				/* Prevent all further interpretation */
				wbuf[wp++] = c | QUOTE;
				break;

			case '`':
				/* Leave all text alone for later */
				wbuf[wp++] = c;
				break;
			}
		}
		if (c1 == '`') {
			DYNAMICBUFFER();
			wbuf[wp++] = '`';
		}
		goto pack;		/* continue the word */

	case '\\':
		c = DgetC(0);		/* No $ subst! */
		if (c == '\n' || c == DEOF)
			goto loop;
		c |= QUOTE;
		break;
#ifdef MBCHAR /* Could be a space char from aux. codeset. */
	default:
		if (isauxsp(c)) goto loop;
#endif /* MBCHAR */
	}
	unDgetC(c);
pack:
	sofar = 1;
	/* pack up more characters in this word */
	for (;;) {
		c = DgetC(DODOL);
		if (c == '\\') {
			c = DgetC(0);
			if (c == DEOF)
				goto deof;
			if (c == '\n')
				c = ' ';
			else
				c |= QUOTE;
		}
		if (c == DEOF)
			goto deof;
		if (cmap(c, _SP|_NL|_Q|_Q1) ||
		    isauxsp(c)) {		/* sp \t\n'"` or aux. sp */
			unDgetC(c);
			if (cmap(c, QUOTES))
				goto loop;
			DYNAMICBUFFER();
			wbuf[wp++] = 0;
			goto ret;
		}
		DYNAMICBUFFER();
		wbuf[wp++] = c;
	}
ret:
	Gcat(S_ /* "" */, wbuf);
	return (1);
}