/* * syn1b * syn2 * syn2 && syn1b */ static struct command * syn1b(struct wordent *p1, struct wordent *p2, int flags) { struct wordent *p; struct command *t; int l = 0; for (p = p1; p != p2; p = p->next) switch (p->word[0]) { case '(': l++; continue; case ')': l--; continue; case '&': if (p->word[1] == '&' && l == 0) { t = (struct command *) xcalloc(1, sizeof(*t)); t->t_dtyp = NODE_AND; t->t_dcar = syn2(p1, p, flags); t->t_dcdr = syn1b(p->next, p2, flags); t->t_dflg = 0; return (t); } continue; } return (syn2(p1, p2, flags)); }
/* * syn2 * syn3 * syn3 | syn2 * * syn2负责构建管道线节点,搜索管道线符号, * 自顶向下生成左子树,递归生成右子树。 * p1指向token列表头部,p2指向token列表末尾的下一个。 */ int *syn2(char **p1, char **p2) { char **p; int l, *t; l = 0; for(p=p1; p!=p2; p++) switch(**p) { case '(': l++; continue; /* 此处等同于break */ case ')': l--; continue; case '|': case '^': if(l == 0) { /* 没有圆括弧嵌套 */ t = tree(4); t[DTYP] = TFIL; /* 建立管道线节点*/ t[DLEF] = (int)syn3(p1, p); /* 左边列表递进一层生成左子树节点*/ t[DRIT] = (int)syn2(p+1, p2); /* 右边递归生成右子树节点*/ t[DFLG] = 0; /* 标志位继承自上层节点*/ return(t); } } return(syn3(p1, p2)); /* 没有找到管道线,所有列表递进一层,不需要判断嵌套是否归零*/ }
/* * syn2: * syn3 * syn3 | syn2 * syn3 ^ syn2 */ static struct tnode * syn2(char **p1, char **p2) { struct tnode *t; int subcnt; char **p; subcnt = 0; for (p = p1; p < p2; p++) switch (**p) { case LPARENTHESIS: subcnt++; continue; case RPARENTHESIS: subcnt--; continue; case VERTICALBAR: case CARET: if (subcnt == 0) { if ((t = talloc()) == NULL) return NULL; t->ntype = TPIPE; t->nleft = syn3(p1, p); t->nright = syn2(p + 1, p2); t->nflags = 0; return t; } break; } return syn3(p1, p2); }
/* * syn2 * syn3 * syn3 | syn2 * syn3 |& syn2 */ static struct command * syn2(struct wordent *p1, struct wordent *p2, int flags) { struct wordent *p, *pn; struct command *t; int f, l; l = 0; for (p = p1; p != p2; p = p->next) switch (p->word[0]) { case '(': l++; continue; case ')': l--; continue; case '|': if (l != 0) continue; t = (struct command *)xcalloc(1, sizeof(*t)); f = flags | POUT; pn = p->next; if (pn != p2 && pn->word[0] == '&') { f |= PERR; t->t_dflg |= F_STDERR; } t->t_dtyp = NODE_PIPE; t->t_dcar = syn3(p1, p, f); if (pn != p2 && pn->word[0] == '&') p = pn; t->t_dcdr = syn2(p->next, p2, flags | PIN); return (t); } return (syn3(p1, p2, flags)); }
/* * syn1: * syn2 * syn2 ; syntax * syn2 & syntax */ static struct tnode * syn1(char **p1, char **p2) { struct tnode *t; int c, subcnt; char **p; subcnt = 0; for (p = p1; p < p2; p++) switch (**p) { case LPARENTHESIS: subcnt++; continue; case RPARENTHESIS: subcnt--; if (subcnt < 0) goto syn1err; continue; case SEMICOLON: case AMPERSAND: case EOL: if (subcnt == 0) { c = **p; if ((t = talloc()) == NULL) goto syn1err; t->ntype = TLIST; t->nleft = syn2(p1, p); if (c == AMPERSAND && t->nleft != NULL) t->nleft->nflags |= FAND | FINTR | FPRS; t->nright = syntax(p + 1, p2); t->nflags = 0; return t; } break; } if (subcnt == 0) return syn2(p1, p2); syn1err: if (error_message == NULL) error_message = ERR_SYNTAX; return NULL; }
/* * syn1 * syn2 * syn2 & syntax * syn2 ; syntax * * syn1生成命令序列节点,查找分隔符, * 自顶向下生成左子树,回溯生成右子树。 * p1指向token列表头部,p2指向token列表末尾的下一个。 */ int *syn1(char **p1, char **p2) { char **p; int *t, *t1; int l; l = 0; for(p=p1; p!=p2; p++) switch(**p) { case '(': l++; continue; /* 此处等同于break */ case ')': l--; if(l < 0) error++; continue; case '&': case ';': case '\n': if(l == 0) { /* 没有圆括弧嵌套 */ l = **p; t = tree(4); t[DTYP] = TLST; /* 生成命令序列节点*/ t[DLEF] = (int)syn2(p1, p); /* 左边列表递进一层生成左子树节点*/ t[DFLG] = 0; /* 命令序列节点不设置任何标志位*/ if(l == '&') { t1 = (int *)t[DLEF]; t1[DFLG] |= FAND|FPRS|FINT; /* 若有后台进程,其属性下推到左子树节点*/ } t[DRIT] = (int)syntax(p+1, p2); /* 右边列表回溯到syntax生成右子树节点*/ return(t); } } if(l == 0) return(syn2(p1, p2)); /* 没有找到命令分隔符,所有列表递进一层至syn2 */ error++; /* 如果嵌套不归零发生错误*/ }