示例#1
0
文件: text.c 项目: SumiTomohiko/rush
static void
gettext2(Estate state)
{
    Tstack s, n;
    int stack = 0;
    wordcode code;

    while (1) {
	if (stack) {
	    if (!(s = tstack))
		break;
	    if (s->pop) {
		tstack = s->prev;
		s->prev = tfree;
		tfree = s;
	    }
	    code = s->code;
	    stack = 0;
	} else {
	    s = NULL;
	    code = *state->pc++;
	}
	switch (wc_code(code)) {
	case WC_LIST:
	    if (!s) {
		s = tpush(code, (WC_LIST_TYPE(code) & Z_END));
		stack = 0;
	    } else {
		if (WC_LIST_TYPE(code) & Z_ASYNC) {
		    taddstr(" &");
		    if (WC_LIST_TYPE(code) & Z_DISOWN)
			taddstr("|");
		}
		if (!(stack = (WC_LIST_TYPE(code) & Z_END))) {
		    if (tnewlins)
			taddnl(0);
		    else
			taddstr((WC_LIST_TYPE(code) & Z_ASYNC) ? " " : "; ");
		    s->code = *state->pc++;
		    s->pop = (WC_LIST_TYPE(s->code) & Z_END);
		}
	    }
	    if (!stack && (WC_LIST_TYPE(s->code) & Z_SIMPLE))
		state->pc++;
	    break;
	case WC_SUBLIST:
	    if (!s) {
                if (!(WC_SUBLIST_FLAGS(code) & WC_SUBLIST_SIMPLE) &&
                    wc_code(*state->pc) != WC_PIPE)
                    stack = -1;
		if (WC_SUBLIST_FLAGS(code) & WC_SUBLIST_NOT)
		    taddstr(stack ? "!" : "! ");
		if (WC_SUBLIST_FLAGS(code) & WC_SUBLIST_COPROC)
		    taddstr(stack ? "coproc" : "coproc ");
		s = tpush(code, (WC_SUBLIST_TYPE(code) == WC_SUBLIST_END));
	    } else {
		if (!(stack = (WC_SUBLIST_TYPE(code) == WC_SUBLIST_END))) {
		    taddstr((WC_SUBLIST_TYPE(code) == WC_SUBLIST_OR) ?
			    " || " : " && ");
		    s->code = *state->pc++;
		    s->pop = (WC_SUBLIST_TYPE(s->code) == WC_SUBLIST_END);
		    if (WC_SUBLIST_FLAGS(s->code) & WC_SUBLIST_NOT)
			taddstr("! ");
		    if (WC_SUBLIST_FLAGS(s->code) & WC_SUBLIST_COPROC)
			taddstr("coproc ");
		}
	    }
	    if (stack < 1 && (WC_SUBLIST_FLAGS(s->code) & WC_SUBLIST_SIMPLE))
		state->pc++;
	    break;
	case WC_PIPE:
	    if (!s) {
		tpush(code, (WC_PIPE_TYPE(code) == WC_PIPE_END));
		if (WC_PIPE_TYPE(code) == WC_PIPE_MID)
		    state->pc++;
	    } else {
		if (!(stack = (WC_PIPE_TYPE(code) == WC_PIPE_END))) {
		    taddstr(" | ");
		    s->code = *state->pc++;
		    if (!(s->pop = (WC_PIPE_TYPE(s->code) == WC_PIPE_END)))
			state->pc++;
		}
	    }
	    break;
	case WC_REDIR:
	    if (!s) {
		state->pc--;
		n = tpush(code, 1);
		n->u._redir.list = ecgetredirs(state);
	    } else {
		getredirs(s->u._redir.list);
		stack = 1;
	    }
	    break;
	case WC_ASSIGN:
	    taddstr(ecgetstr(state, EC_NODUP, NULL));
	    if (WC_ASSIGN_TYPE2(code) == WC_ASSIGN_INC) taddchr('+');
	    taddchr('=');
	    if (WC_ASSIGN_TYPE(code) == WC_ASSIGN_ARRAY) {
		taddchr('(');
		taddlist(state, WC_ASSIGN_NUM(code));
		taddstr(") ");
	    } else {
		taddstr(ecgetstr(state, EC_NODUP, NULL));
		taddchr(' ');
	    }
	    break;
	case WC_SIMPLE:
	    taddlist(state, WC_SIMPLE_ARGC(code));
	    stack = 1;
	    break;
	case WC_SUBSH:
	    if (!s) {
		taddstr("(");
		tindent++;
		taddnl(1);
		n = tpush(code, 1);
		n->u._subsh.end = state->pc + WC_SUBSH_SKIP(code);
		/* skip word only use for try/always */
		state->pc++;
	    } else {
		state->pc = s->u._subsh.end;
		dec_tindent();
		/* semicolon is optional here but more standard */
		taddnl(0);
		taddstr(")");
		stack = 1;
	    }
	    break;
	case WC_CURSH:
	    if (!s) {
		taddstr("{");
		tindent++;
		taddnl(1);
		n = tpush(code, 1);
		n->u._subsh.end = state->pc + WC_CURSH_SKIP(code);
		/* skip word only use for try/always */
		state->pc++;
	    } else {
		state->pc = s->u._subsh.end;
		dec_tindent();
		/* semicolon is optional here but more standard */
		taddnl(0);
		taddstr("}");
		stack = 1;
	    }
	    break;
	case WC_TIMED:
	    if (!s) {
		taddstr("time");
		if (WC_TIMED_TYPE(code) == WC_TIMED_PIPE) {
		    taddchr(' ');
		    tindent++;
		    tpush(code, 1);
		} else
		    stack = 1;
	    } else {
		dec_tindent();
		stack = 1;
	    }
	    break;
	case WC_FUNCDEF:
	    if (!s) {
		Wordcode p = state->pc;
		Wordcode end = p + WC_FUNCDEF_SKIP(code);

		taddlist(state, *state->pc++);
		if (tjob) {
		    taddstr(" () { ... }");
		    state->pc = end;
		    stack = 1;
		} else {
		    taddstr(" () {");
		    tindent++;
		    taddnl(1);
		    n = tpush(code, 1);
		    n->u._funcdef.strs = state->strs;
		    n->u._funcdef.end = end;
		    state->strs += *state->pc;
		    state->pc += 3;
		}
	    } else {
		state->strs = s->u._funcdef.strs;
		state->pc = s->u._funcdef.end;
		dec_tindent();
		taddnl(0);
		taddstr("}");
		stack = 1;
	    }
	    break;
	case WC_FOR:
	    if (!s) {
		taddstr("for ");
		if (WC_FOR_TYPE(code) == WC_FOR_COND) {
		    taddstr("((");
		    taddstr(ecgetstr(state, EC_NODUP, NULL));
		    taddstr("; ");
		    taddstr(ecgetstr(state, EC_NODUP, NULL));
		    taddstr("; ");
		    taddstr(ecgetstr(state, EC_NODUP, NULL));
		    taddstr(")) do");
		} else {
		    taddlist(state, *state->pc++);
		    if (WC_FOR_TYPE(code) == WC_FOR_LIST) {
			taddstr(" in ");
			taddlist(state, *state->pc++);
		    }
		    taddnl(0);
		    taddstr("do");
		}
		tindent++;
		taddnl(0);
		tpush(code, 1);
	    } else {
		dec_tindent();
		taddnl(0);
		taddstr("done");
		stack = 1;
	    }
	    break;
	case WC_SELECT:
	    if (!s) {
		taddstr("select ");
		taddstr(ecgetstr(state, EC_NODUP, NULL));
		if (WC_SELECT_TYPE(code) == WC_SELECT_LIST) {
		    taddstr(" in ");
		    taddlist(state, *state->pc++);
		}
		tindent++;
		taddnl(0);
		tpush(code, 1);
	    } else {
		dec_tindent();
		taddnl(0);
		taddstr("done");
		stack = 1;
	    }
	    break;
	case WC_WHILE:
	    if (!s) {
		taddstr(WC_WHILE_TYPE(code) == WC_WHILE_UNTIL ?
			"until " : "while ");
		tindent++;
		tpush(code, 0);
	    } else if (!s->pop) {
		dec_tindent();
		taddnl(0);
		taddstr("do");
		tindent++;
		taddnl(0);
		s->pop = 1;
	    } else {
		dec_tindent();
		taddnl(0);
		taddstr("done");
		stack = 1;
	    }
	    break;
	case WC_REPEAT:
	    if (!s) {
		taddstr("repeat ");
		taddstr(ecgetstr(state, EC_NODUP, NULL));
		taddnl(0);
		taddstr("do");
		tindent++;
		taddnl(0);
		tpush(code, 1);
	    } else {
		dec_tindent();
		taddnl(0);
		taddstr("done");
		stack = 1;
	    }
	    break;
	case WC_CASE:
	    if (!s) {
		Wordcode end = state->pc + WC_CASE_SKIP(code);

		taddstr("case ");
		taddstr(ecgetstr(state, EC_NODUP, NULL));
		taddstr(" in");

		if (state->pc >= end) {
		    if (tnewlins)
			taddnl(0);
		    else
			taddchr(' ');
		    taddstr("esac");
		    stack = 1;
		} else {
		    tindent++;
		    if (tnewlins)
			taddnl(0);
		    else
			taddchr(' ');
		    taddstr("(");
		    code = *state->pc++;
		    taddstr(ecgetstr(state, EC_NODUP, NULL));
		    state->pc++;
		    taddstr(") ");
		    tindent++;
		    n = tpush(code, 0);
		    n->u._case.end = end;
		    n->pop = (state->pc - 2 + WC_CASE_SKIP(code) >= end);
		}
	    } else if (state->pc < s->u._case.end) {
		dec_tindent();
		switch (WC_CASE_TYPE(code)) {
		case WC_CASE_OR:
		    taddstr(" ;;");
		    break;

		case WC_CASE_AND:
		    taddstr(";&");
		    break;

		default:
		    taddstr(";|");
		    break;
		}
		if (tnewlins)
		    taddnl(0);
		else
		    taddchr(' ');
		taddstr("(");
		code = *state->pc++;
		taddstr(ecgetstr(state, EC_NODUP, NULL));
		state->pc++;
		taddstr(") ");
		tindent++;
		s->code = code;
		s->pop = ((state->pc - 2 + WC_CASE_SKIP(code)) >=
			  s->u._case.end);
	    } else {
		dec_tindent();
		switch (WC_CASE_TYPE(code)) {
		case WC_CASE_OR:
		    taddstr(" ;;");
		    break;

		case WC_CASE_AND:
		    taddstr(";&");
		    break;

		default:
		    taddstr(";|");
		    break;
		}
		dec_tindent();
		if (tnewlins)
		    taddnl(0);
		else
		    taddchr(' ');
		taddstr("esac");
		stack = 1;
	    }
	    break;
	case WC_IF:
	    if (!s) {
		Wordcode end = state->pc + WC_IF_SKIP(code);

		taddstr("if ");
		tindent++;
		state->pc++;

		n = tpush(code, 0);
		n->u._if.end = end;
		n->u._if.cond = 1;
	    } else if (s->pop) {
		stack = 1;
	    } else if (s->u._if.cond) {
		dec_tindent();
		taddnl(0);
		taddstr("then");
		tindent++;
		taddnl(0);
		s->u._if.cond = 0;
	    } else if (state->pc < s->u._if.end) {
		dec_tindent();
		taddnl(0);
		code = *state->pc++;
		if (WC_IF_TYPE(code) == WC_IF_ELIF) {
		    taddstr("elif ");
		    tindent++;
		    s->u._if.cond = 1;
		} else {
		    taddstr("else");
		    tindent++;
		    taddnl(0);
		}
	    } else {
		s->pop = 1;
		dec_tindent();
		taddnl(0);
		taddstr("fi");
		stack = 1;
	    }
	    break;
	case WC_COND:
	    {
		static char *c1[] = {
		    "=", "!=", "<", ">", "-nt", "-ot", "-ef", "-eq",
		    "-ne", "-lt", "-gt", "-le", "-ge", "=~"
		};

		int ctype;

		if (!s) {
		    taddstr("[[ ");
		    n = tpush(code, 1);
		    n->u._cond.par = 2;
		} else if (s->u._cond.par == 2) {
		    taddstr(" ]]");
		    stack = 1;
		    break;
		} else if (s->u._cond.par == 1) {
		    taddstr(" )");
		    stack = 1;
		    break;
		} else if (WC_COND_TYPE(s->code) == COND_AND) {
		    taddstr(" && ");
		    code = *state->pc++;
		    if (WC_COND_TYPE(code) == COND_OR) {
			taddstr("( ");
			n = tpush(code, 1);
			n->u._cond.par = 1;
		    }
		} else if (WC_COND_TYPE(s->code) == COND_OR) {
		    taddstr(" || ");
		    code = *state->pc++;
		    if (WC_COND_TYPE(code) == COND_AND) {
			taddstr("( ");
			n = tpush(code, 1);
			n->u._cond.par = 1;
		    }
		}
		while (!stack) {
		    switch ((ctype = WC_COND_TYPE(code))) {
		    case COND_NOT:
			taddstr("! ");
			code = *state->pc++;
			if (WC_COND_TYPE(code) <= COND_OR) {
			    taddstr("( ");
			    n = tpush(code, 1);
			    n->u._cond.par = 1;
			}
			break;
		    case COND_AND:
			n = tpush(code, 1);
			n->u._cond.par = 0;
			code = *state->pc++;
			if (WC_COND_TYPE(code) == COND_OR) {
			    taddstr("( ");
			    n = tpush(code, 1);
			    n->u._cond.par = 1;
			}
			break;
		    case COND_OR:
			n = tpush(code, 1);
			n->u._cond.par = 0;
			code = *state->pc++;
			if (WC_COND_TYPE(code) == COND_AND) {
			    taddstr("( ");
			    n = tpush(code, 1);
			    n->u._cond.par = 1;
			}
			break;
		    case COND_MOD:
			taddstr(ecgetstr(state, EC_NODUP, NULL));
			taddchr(' ');
			taddlist(state, WC_COND_SKIP(code));
			stack = 1;
			break;
		    case COND_MODI:
			{
			    char *name = ecgetstr(state, EC_NODUP, NULL);

			    taddstr(ecgetstr(state, EC_NODUP, NULL));
			    taddchr(' ');
			    taddstr(name);
			    taddchr(' ');
			    taddstr(ecgetstr(state, EC_NODUP, NULL));
			    stack = 1;
			}
			break;
		    default:
			if (ctype < COND_MOD) {
			    /* Binary test: `a = b' etc. */
			    taddstr(ecgetstr(state, EC_NODUP, NULL));
			    taddstr(" ");
			    taddstr(c1[ctype - COND_STREQ]);
			    taddstr(" ");
			    taddstr(ecgetstr(state, EC_NODUP, NULL));
			    if (ctype == COND_STREQ ||
				ctype == COND_STRNEQ)
				state->pc++;
			} else {
			    /* Unary test: `-f foo' etc. */ 
			    char c2[4];

			    c2[0] = '-';
			    c2[1] = ctype;
			    c2[2] = ' ';
			    c2[3] = '\0';
			    taddstr(c2);
			    taddstr(ecgetstr(state, EC_NODUP, NULL));
			}
			stack = 1;
			break;
		    }
		}
	    }
	    break;
	case WC_ARITH:
	    taddstr("((");
	    taddstr(ecgetstr(state, EC_NODUP, NULL));
	    taddstr("))");
	    stack = 1;
	    break;
	case WC_TRY:
	    if (!s) {
		taddstr("{");
		tindent++;
		taddnl(0);
		n = tpush(code, 0);
		state->pc++;
		/* this is the end of the try block alone */
		n->u._subsh.end = state->pc + WC_CURSH_SKIP(state->pc[-1]);
	    } else if (!s->pop) {
		state->pc = s->u._subsh.end;
		dec_tindent();
		taddnl(0);
		taddstr("} always {");
		tindent++;
		taddnl(0);
		s->pop = 1;
	    } else {
		dec_tindent();
		taddnl(0);
		taddstr("}");
		stack = 1;
	    }
	    break;
	case WC_END:
	    stack = 1;
	    break;
	default:
	    DPUTS(1, "unknown word code in gettext2()");
	    return;
	}
    }
    tdopending();
}
示例#2
0
文件: loop.c 项目: phy1729/zsh
int
execselect(Estate state, UNUSED(int do_exec))
{
    Wordcode end, loop;
    wordcode code = state->pc[-1];
    char *str, *s, *name;
    LinkNode n;
    int i, usezle;
    FILE *inp;
    size_t more;
    LinkList args;
    int old_simple_pline = simple_pline;

    /* See comments in execwhile() */
    simple_pline = 1;

    end = state->pc + WC_FOR_SKIP(code);
    name = ecgetstr(state, EC_NODUP, NULL);

    if (WC_SELECT_TYPE(code) == WC_SELECT_PPARAM) {
	char **x;

	args = newlinklist();
	for (x = pparams; *x; x++)
	    addlinknode(args, dupstring(*x));
    } else {
	int htok = 0;

	if (!(args = ecgetlist(state, *state->pc++, EC_DUPTOK, &htok))) {
	    state->pc = end;
	    simple_pline = old_simple_pline;
	    return 0;
	}
	if (htok) {
	    execsubst(args);
	    if (errflag) {
		state->pc = end;
		simple_pline = old_simple_pline;
		return 1;
	    }
	}
    }
    if (!args || empty(args)) {
	state->pc = end;
	simple_pline = old_simple_pline;
	return 0;
    }
    loops++;

    pushheap();
    cmdpush(CS_SELECT);
    usezle = interact && SHTTY != -1 && isset(USEZLE);
    inp = fdopen(dup(usezle ? SHTTY : 0), "r");
    more = selectlist(args, 0);
    loop = state->pc;
    for (;;) {
	for (;;) {
	    if (empty(bufstack)) {
	    	if (usezle) {
		    int oef = errflag;

		    isfirstln = 1;
		    str = zleentry(ZLE_CMD_READ, &prompt3, NULL,
				   0, ZLCON_SELECT);
		    if (errflag)
			str = NULL;
		    /* Keep any user interrupt error status */
		    errflag = oef | (errflag & ERRFLAG_INT);
	    	} else {
		    str = promptexpand(prompt3, 0, NULL, NULL, NULL);
		    zputs(str, stderr);
		    free(str);
		    fflush(stderr);
		    str = fgets(zhalloc(256), 256, inp);
	    	}
	    } else
		str = (char *)getlinknode(bufstack);
            if (!str && !errflag)
                setsparam("REPLY", ztrdup("")); /* EOF (user pressed Ctrl+D) */
	    if (!str || errflag) {
		if (breaks)
		    breaks--;
		fprintf(stderr, "\n");
		fflush(stderr);
		goto done;
	    }
	    if ((s = strchr(str, '\n')))
		*s = '\0';
	    if (*str)
	      break;
	    more = selectlist(args, more);
	}
	setsparam("REPLY", ztrdup(str));
	i = atoi(str);
	if (!i)
	    str = "";
	else {
	    for (i--, n = firstnode(args); n && i; incnode(n), i--);
	    if (n)
		str = (char *) getdata(n);
	    else
		str = "";
	}
	setsparam(name, ztrdup(str));
	state->pc = loop;
	execlist(state, 1, 0);
	freeheap();
	if (breaks) {
	    breaks--;
	    if (breaks || !contflag)
		break;
	    contflag = 0;
	}
	if (retflag || errflag)
	    break;
    }
  done:
    cmdpop();
    popheap();
    fclose(inp);
    loops--;
    simple_pline = old_simple_pline;
    state->pc = end;
    return lastval;
}