Ejemplo n.º 1
0
/*
 * syn0
 *	syn1
 *	syn1 & syntax
 */
static struct command *
syn0(struct wordent *p1, struct wordent *p2, int flags)
{
    struct wordent *p;
    struct command *t, *t1;
    int     l;

    l = 0;
    for (p = p1; p != p2; p = p->next)
	switch (p->word[0]) {

	case '(':
	    l++;
	    continue;

	case ')':
	    l--;
	    if (l < 0)
		seterror(ERR_TOOMANYRP);
	    continue;

	case '|':
	    if (p->word[1] == '|')
		continue;
	    /* fall into ... */

	case '>':
	    if (p->next != p2 && eq(p->next->word, STRand))
		p = p->next;
	    continue;

	case '&':
	    if (l != 0)
		break;
	    if (p->word[1] == '&')
		continue;
	    t1 = syn1(p1, p, flags);
	    if (t1->t_dtyp == NODE_LIST ||
		t1->t_dtyp == NODE_AND ||
		t1->t_dtyp == NODE_OR) {
		t = (struct command *) xcalloc(1, sizeof(*t));
		t->t_dtyp = NODE_PAREN;
		t->t_dflg = F_AMPERSAND | F_NOINTERRUPT;
		t->t_dspr = t1;
		t1 = t;
	    }
	    else
		t1->t_dflg |= F_AMPERSAND | F_NOINTERRUPT;
	    t = (struct command *) xcalloc(1, sizeof(*t));
	    t->t_dtyp = NODE_LIST;
	    t->t_dflg = 0;
	    t->t_dcar = t1;
	    t->t_dcdr = syntax(p, p2, flags);
	    return (t);
	}
    if (l == 0)
	return (syn1(p1, p2, flags));
    seterror(ERR_TOOMANYLP);
    return (0);
}
Ejemplo n.º 2
0
Archivo: sh.c Proyecto: Ju2ender/c-e
/* 
 * syntax 
 *        empty 
 *        syn1 
 * 
 * 从这里开始构建语法树,遍历之前扫描生成的token列表 
 * p1指向token列表头部,p2指向token列表末尾的下一个 
 * 自顶向下三级结构: syn1、syn2、syn3,函数调用关系如下
 * 1.左子树:左边列表递进一层
 * 2.右子树:右边列表回溯或者递归
 * 3.找不到符号:所有列表递进一层
 * 4.生成节点:直接返回
 */ 
int *syntax(char **p1, char **p2) 
{ 

        while(p1 != p2) { 
                if(any(**p1, ";&\n"))        /* 列表前缀为命令序列分隔字符,过滤掉该token,对syntax回溯中碰到*/ 
                        p1++; else 
                        return(syn1(p1, p2));        /* 所有列表递进一层至syn1 */ 
        } 
        return(0); 
} 
Ejemplo n.º 3
0
/*
 * syntax:
 *	empty
 *	syn1
 */
static struct tnode *
syntax(char **p1, char **p2)
{

	while (p1 < p2)
		if (any(**p1, EOC))
			p1++;
		else
			return syn1(p1, p2);
	return NULL;
}
Ejemplo n.º 4
0
Archivo: sh.c Proyecto: Ju2ender/c-e
/* 
 * syn3 
 *        ( syn1 ) [ < in  ] [ > out ] 
 *        word word* [ < in ] [ > out ] 
 * 
 * syn3负责构建复合命令和简单命令节点,前者以圆括号标记,括号内所有token列表回溯至syn1构建子命令节点; 
 * 简单命令是语法树叶子,其左右子树节点为I/O重定向文件,并存储命令参数字符串,生成节点后直接返回。 
 * p1指向token列表头部,p2指向token列表末尾的下一个。 
 */ 
int *syn3(char **p1, char **p2) 
{ 
        char **p; 
        char **lp, **rp; 
        int *t; 
        int n, l, i, o, c, flg; 

        flg = 0; 
        if(**p2 == ')') 
                flg |= FPAR;        /* 复合命令中最后一个子命令不需要fork子进程*/ 
        lp = 0;        /* 子命令开头*/ 
        rp = 0;        /* 子命令末尾*/ 
        i = 0;        /* 输入文件路径*/ 
        o = 0;        /* 输出文件路径*/ 
        n = 0;        /* 字符计数*/ 
        l = 0;        /* 嵌套层数*/ 
        for(p=p1; p!=p2; p++) 
        switch(c = **p) { 

        case '(': 
                if(l == 0) { 
                        if(lp != 0) 
                                error++; 
                        lp = p+1;        /* 当前嵌套最外层,lp指向子命令第一个字符*/ 
                } 
                l++; 
                continue;        /* 同break */ 

        case ')': 
                l--; 
                if(l == 0) 
                        rp = p;        /* 当前嵌套最外层,rp指向子命令后面的')' */ 
                continue; 

        case '>': 
                p++; 
                if(p!=p2 && **p=='>')        /* 追加模式FCAT标识*/ 
                        flg |= FCAT; else 
                        p--; 
/* 注意这里没有break,继续往下走*/ 
        case '<': 
                if(l == 0) { 
                        p++; 
                        if(p == p2) { 
                                error++;    /* 后面没有字符,发生错误 */
                                p--; 
                        } 
                        if(any(**p, "<>("))     /* 非法字符 */
                                error++; 
                        if(c == '<') { 
                                if(i != 0) 
                                        error++; 
                                i = (int)*p;        /* 重定向到输入文件,只对简单命令有效*/ 
                                continue; 
                        } 
                        if(o != 0) 
                                error++; 
                        o = (int)*p;        /* 重定向到输出文件,只对简单命令有效*/ 
                } 
                continue; 

        default: 
                if(l == 0) 
                        p1[n++] = *p;        /* 命令参数前移清除以往记录,并用n计数*/ 
        } 
        if(lp != 0) { 
                if(n != 0) 
                        error++;                /* 复合命令,n必须为0 */ 
                t = tree(5); 
                t[DTYP] = TPAR;        /* 分配复合命令类型节点*/ 
                t[DSPR] = (int)syn1(lp, rp);        /* 括号内所有token列表回溯至syn1构建子命令节点 */ 
                goto out; 
        } 
        if(n == 0) 
                error++;                /* 简单命令,n必须不为0 */ 
        p1[n++] = 0;                /* 字符串结束*/ 
        t = tree(n+5);        /* 分配简单命令节点,大小为5个字段(DSPR字段为空)加上命令字符数*/ 
        t[DTYP] = TCOM; 
        for(l=0; l<n; l++) 
                t[l+DCOM] = (int)p1[l]; 
out: 
        t[DFLG] = flg;        /* 固有属性或者继承自上层节点属性*/ 
        t[DLEF] = i;        /* 对于简单命令,左右子树是重定向的I/O文件*/ 
        t[DRIT] = o;        /* 对于复合命令,左右子树为空*/ 
        return(t); 
} 
Ejemplo n.º 5
0
/*
 * syn3:
 *	command  [arg ...]  [< in]  [> [>] out]
 *	( syn1 )            [< in]  [> [>] out]
 */
static struct tnode *
syn3(char **p1, char **p2)
{
	struct tnode *t;
	enum tnflags flags;
	int ac, c, n, subcnt;
	char **p, **lp, **rp;
	char *fin, *fout;

	flags = 0;
	if (**p2 == RPARENTHESIS)
		flags |= FNOFORK;

	fin    = NULL;
	fout   = NULL;
	lp     = NULL;
	rp     = NULL;
	n      = 0;
	subcnt = 0;
	for (p = p1; p < p2; p++)
		switch (c = **p) {
		case LPARENTHESIS:
			if (subcnt == 0) {
				if (lp != NULL)
					goto syn3err;
				lp = p + 1;
			}
			subcnt++;
			continue;

		case RPARENTHESIS:
			subcnt--;
			if (subcnt == 0)
				rp = p;
			continue;

		case GREATERTHAN:
			p++;
			if (p < p2 && **p == GREATERTHAN)
				flags |= FCAT;
			else
				p--;
			/*FALLTHROUGH*/

		case LESSTHAN:
			if (subcnt == 0) {
				p++;
				if (p == p2 || any(**p, REDIRERR))
					goto syn3err;
				if (c == LESSTHAN) {
					if (fin != NULL)
						goto syn3err;
					fin = *p;
				} else {
					if (fout != NULL)
						goto syn3err;
					fout = *p;
				}
			}
			continue;

		default:
			if (subcnt == 0)
				p1[n++] = *p;
		}

	if (lp == NULL) {
		if (n == 0)
			goto syn3err;
		if ((t = talloc()) == NULL)
			goto syn3err;
		t->ntype = TCOMMAND;
		t->nav   = xmalloc((n + 1) * sizeof(char *));
		for (ac = 0; ac < n; ac++)
			t->nav[ac] = p1[ac];
		t->nav[ac] = NULL;
	} else {
		if (n != 0)
			goto syn3err;
		if ((t = talloc()) == NULL)
			goto syn3err;
		t->ntype = TSUBSHELL;
		t->nsub  = syn1(lp, rp);
	}
	t->nfin   = fin;
	t->nfout  = fout;
	t->nflags = flags;
	return t;

syn3err:
	if (error_message == NULL)
		error_message = ERR_SYNTAX;
	return NULL;
}