Exemple #1
0
/*
 *	extract a variable name
 */
static Bufblock*
varname(char **s)
{
	Bufblock *b;
	char *cp;
	Rune r;
	int n;

	b = newbuf();
	cp = *s;
	for(;;){
		n = chartorune(&r, cp);
		if (!WORDCHR(r))
			break;
		rinsert(b, r);
		cp += n;
	}
	if (b->current == b->start){
		SYNERR(-1);
		fprint(2, "missing variable name <%s>\n", *s);
		freebuf(b);
		return 0;
	}
	*s = cp;
	insert(b, 0);
	return b;
}
Exemple #2
0
/*
 *	Input an escaped token.  Possible escape chars are single-quote,
 *	double-quote and backslash.  Only the first is a valid escape for
 *	rc; the others are just inserted into the receiving buffer.
 */
int
escapetoken(Biobuf *bp, Bufblock *buf, int preserve, int esc)
{
	int c, line;

	if(esc != '\'')
		return 1;

	line = mkinline;
	while((c = nextrune(bp, 0)) > 0){
		if(c == '\''){
			if(preserve)
				rinsert(buf, c);
			c = Bgetrune(bp);
			if (c < 0)
				break;
			if(c != '\''){
				Bungetrune(bp);
				return 1;
			}
		}
		rinsert(buf, c);
	}
	SYNERR(line); fprint(2, "missing closing %c\n", esc);
	return 0;
}
Exemple #3
0
static Word*
expandvar(char **s)
{
	Word *w;
	Bufblock *buf;
	Symtab *sym;
	char *cp, *begin, *end;

	begin = *s;
	(*s)++;						/* skip the '{' */
	buf = varname(s);
	if (buf == 0)
		return 0;
	cp = *s;
	if (*cp == '}') {				/* ${name} variant*/
		(*s)++;					/* skip the '}' */
		w = varmatch(buf->start, s);
		freebuf(buf);
		return w;
	}
	if (*cp != ':') {
		SYNERR(-1);
		fprint(2, "bad variable name <%s>\n", buf->start);
		freebuf(buf);
		return 0;
	}
	cp++;
	end = charin(cp , "}");
	if(end == 0){
		SYNERR(-1);
		fprint(2, "missing '}': %s\n", begin);
		Exit();
	}
	*end = 0;
	*s = end+1;
	
	sym = symlook(buf->start, S_VAR, 0);
	if(sym == 0 || sym->value == 0)
		w = newword(buf->start);
	else
		w = subsub((Word*) sym->value, cp, end);
	freebuf(buf);
	return w;
}
Exemple #4
0
/*
 *	skip a token in quotes.
 */
static char *
squote(char *cp, int c)
{
	Rune r;
	int n;

	while(*cp){
		n = chartorune(&r, cp);
		if(r == c)
			return cp;
		if(r == '\\')
			n += chartorune(&r, cp+n);
		cp += n;
	}
	SYNERR(-1);		/* should never occur */
	fprint(2, "missing closing '\n");
	return 0;
}
Exemple #5
0
/*
 *	search a string for unescaped characters in a pattern set
 */
static char *
shcharin(char *cp, char *pat)
{
	Rune r;
	int n, vargen;

	vargen = 0;
	while(*cp){
		n = chartorune(&r, cp);
		switch(r){
		case '\\':			/* skip escaped char */
			cp += n;
			n = chartorune(&r, cp);
			break;
		case '\'':			/* skip quoted string */
		case '"':
			cp = squote(cp+1, r);	/* n must = 1 */
			if(!cp)
				return 0;
			break;
		case '$':
			if(*(cp+1) == '{')
				vargen = 1;
			break;
		case '}':
			if(vargen)
				vargen = 0;
			else if(utfrune(pat, r))
				return cp;
			break;
		default:
			if(vargen == 0 && utfrune(pat, r))
				return cp;
			break;
		}
		cp += n;
	}
	if(vargen){
		SYNERR(-1);
		fprint(2, "missing closing } in pattern generator\n");
	}
	return 0;
}
Exemple #6
0
/*
 *	assemble a back-quoted shell command into a buffer
 */
static int
bquote(Biobuf *bp, Bufblock *buf)
{
	int c, line, term, depth;
	int start;

	line = mkinline;
	while((c = Bgetrune(bp)) == ' ' || c == '\t')
			;
	if(c == '{'){
		term = '}';		/* rc style */
		while((c = Bgetrune(bp)) == ' ' || c == '\t')
			;
	} else
		term = '`';		/* sh style */

	depth = 1;
	start = buf->current-buf->start;
	for(;c > 0; c = nextrune(bp, 0)){
		if(c == '{' && term == '}')
			depth++;
		if(c == term && --depth == 0){
			insert(buf, '\n');
			insert(buf,0);
			buf->current = buf->start+start;
			execinit();
			execsh(0, buf->current, buf, envy);
			return 1;
		}
		if(c == '\n')
			break;
		if(c == '\'' || c == '"' || c == '\\'){
			insert(buf, c);
			if(!escapetoken(bp, buf, 1, c))
				return 0;
			continue;
		}
		rinsert(buf, c);
	}
	SYNERR(line);
	fprint(2, "missing closing %c after `\n", term);
	return 0;
}
Exemple #7
0
/*
 *	Input an escaped token.  Possible escape chars are single-quote,
 *	double-quote and backslash.
 */
static int
shescapetoken(Biobuf *bp, Bufblock *buf, int preserve, int esc)
{
	int c, line;

	if(esc == '\\') {
		c = Bgetrune(bp);
		if(c == '\r')
			c = Bgetrune(bp);
		if (c == '\n')
			mkinline++;
		rinsert(buf, c);
		return 1;
	}

	line = mkinline;
	while((c = nextrune(bp, 0)) >= 0){
		if(c == esc){
			if(preserve)
				rinsert(buf, c);
			return 1;
		}
		if(c == '\\') {
			rinsert(buf, c);
			c = Bgetrune(bp);
			if(c == '\r')
				c = Bgetrune(bp);
			if (c < 0)
				break;
			if (c == '\n')
				mkinline++;
		}
		rinsert(buf, c);
	}
	SYNERR(line); fprint(2, "missing closing %c\n", esc);
	return 0;
}
Exemple #8
0
void
parse(char *f, int fd, int varoverride)
{
    int hline;
    char *body;
    Word *head, *tail;
    int attr, set, pid;
    char *prog, *p;
    int newfd;
    Biobuf in;
    Bufblock *buf;

    if(fd < 0) {
        perror(f);
        Exit();
    }
    ipush();
    infile = strdup(f);
    mkinline = 1;
    Binit(&in, fd, OREAD);
    buf = newbuf();
    while(assline(&in, buf)) {
        hline = mkinline;
        switch(rhead(buf->start, &head, &tail, &attr, &prog))
        {
        case '<':
            p = wtos(tail, ' ');
            if(*p == 0) {
                SYNERR(-1);
                fprint(2, "missing include file name\n");
                Exit();
            }
            newfd = open(p, OREAD);
            if(newfd < 0) {
                fprint(2, "warning: skipping missing include file: ");
                perror(p);
            } else
                parse(p, newfd, 0);
            break;
        case '|':
            p = wtos(tail, ' ');
            if(*p == 0) {
                SYNERR(-1);
                fprint(2, "missing include program name\n");
                Exit();
            }
            execinit();
            pid=pipecmd(p, envy, &newfd);
            if(newfd < 0) {
                fprint(2, "warning: skipping missing program file: ");
                perror(p);
            } else
                parse(p, newfd, 0);
            while(waitup(-3, &pid) >= 0)
                ;
            if(pid != 0) {
                fprint(2, "bad include program status\n");
                Exit();
            }
            break;
        case ':':
            body = rbody(&in);
            addrules(head, tail, body, attr, hline, prog);
            break;
        case '=':
            if(head->next) {
                SYNERR(-1);
                fprint(2, "multiple vars on left side of assignment\n");
                Exit();
            }
            if(symlook(head->s, S_OVERRIDE, 0)) {
                set = varoverride;
            } else {
                set = 1;
                if(varoverride)
                    symlook(head->s, S_OVERRIDE, (void *)"");
            }
            if(set) {
                /*
                char *cp;
                dumpw("tail", tail);
                cp = wtos(tail, ' '); print("assign %s to %s\n", head->s, cp); free(cp);
                */
                setvar(head->s, (void *) tail);
                symlook(head->s, S_WESET, (void *)"");
            }
            if(attr)
                symlook(head->s, S_NOEXPORT, (void *)"");
            break;
        default:
            SYNERR(hline);
            fprint(2, "expected one of :<=\n");
            Exit();
            break;
        }
    }
    close(fd);
    freebuf(buf);
    ipop();
}
Exemple #9
0
static int
rhead(char *line, Word **h, Word **t, int *attr, char **prog)
{
    char *p;
    char *pp;
    int sep;
    Rune r;
    int n;
    Word *w;

    p = charin(line,":=<");
    if(p == 0)
        return('?');
    sep = *p;
    *p++ = 0;
    if(sep == '<' && *p == '|') {
        sep = '|';
        p++;
    }
    *attr = 0;
    *prog = 0;
    if(sep == '=') {
        pp = charin(p, termchars);	/* termchars is shell-dependent */
        if (pp && *pp == '=') {
            while (p != pp) {
                n = chartorune(&r, p);
                switch(r)
                {
                default:
                    SYNERR(-1);
                    fprint(2, "unknown attribute '%c'\n",*p);
                    Exit();
                case 'U':
                    *attr = 1;
                    break;
                }
                p += n;
            }
            p++;		/* skip trailing '=' */
        }
    }
    if((sep == ':') && *p && (*p != ' ') && (*p != '\t')) {
        while (*p) {
            n = chartorune(&r, p);
            if (r == ':')
                break;
            p += n;
            switch(r)
            {
            default:
                SYNERR(-1);
                fprint(2, "unknown attribute '%c'\n", p[-1]);
                Exit();
            case 'D':
                *attr |= DEL;
                break;
            case 'E':
                *attr |= NOMINUSE;
                break;
            case 'n':
                *attr |= NOVIRT;
                break;
            case 'N':
                *attr |= NOREC;
                break;
            case 'P':
                pp = utfrune(p, ':');
                if (pp == 0 || *pp == 0)
                    goto eos;
                *pp = 0;
                *prog = strdup(p);
                *pp = ':';
                p = pp;
                break;
            case 'Q':
                *attr |= QUIET;
                break;
            case 'R':
                *attr |= REGEXP;
                break;
            case 'U':
                *attr |= UPD;
                break;
            case 'V':
                *attr |= VIR;
                break;
            }
        }
        if (*p++ != ':') {
eos:
            SYNERR(-1);
            fprint(2, "missing trailing :\n");
            Exit();
        }
    }
    *h = w = stow(line);
    if(*w->s == 0 && sep != '<' && sep != '|') {
        SYNERR(mkinline-1);
        fprint(2, "no var on left side of assignment/rule\n");
        Exit();
    }
    *t = stow(p);
    return(sep);
}