int execif(Estate state, int do_exec) { Wordcode end, next; wordcode code = state->pc[-1]; int olderrexit, s = 0, run = 0; olderrexit = noerrexit; end = state->pc + WC_IF_SKIP(code); noerrexit |= NOERREXIT_EXIT | NOERREXIT_RETURN; while (state->pc < end) { code = *state->pc++; if (wc_code(code) != WC_IF || (run = (WC_IF_TYPE(code) == WC_IF_ELSE))) { if (run) run = 2; break; } next = state->pc + WC_IF_SKIP(code); cmdpush(s ? CS_ELIF : CS_IF); execlist(state, 1, 0); cmdpop(); if (!lastval) { run = 1; break; } if (retflag) break; s = 1; state->pc = next; } if (run) { /* we need to ignore lastval until we reach execcmd() */ if (olderrexit) noerrexit = olderrexit; else if (lastval) noerrexit |= NOERREXIT_EXIT | NOERREXIT_RETURN | NOERREXIT_UNTIL_EXEC; else noerrexit &= ~ (NOERREXIT_EXIT | NOERREXIT_RETURN); cmdpush(run == 2 ? CS_ELSE : (s ? CS_ELIFTHEN : CS_IFTHEN)); execlist(state, 1, do_exec); cmdpop(); } else { noerrexit = olderrexit; if (!retflag) lastval = 0; } state->pc = end; this_noerrexit = 1; return lastval; }
int execif(Estate state, int do_exec) { Wordcode end, next; wordcode code = state->pc[-1]; int olderrexit, s = 0, run = 0; olderrexit = noerrexit; end = state->pc + WC_IF_SKIP(code); if (!noerrexit) noerrexit = 1; while (state->pc < end) { code = *state->pc++; if (wc_code(code) != WC_IF || (run = (WC_IF_TYPE(code) == WC_IF_ELSE))) { if (run) run = 2; break; } next = state->pc + WC_IF_SKIP(code); cmdpush(s ? CS_ELIF : CS_IF); execlist(state, 1, 0); cmdpop(); if (!lastval) { run = 1; break; } if (retflag) break; s = 1; state->pc = next; } if (run) { /* we need to ignore lastval until we reach execcmd() */ noerrexit = olderrexit ? olderrexit : lastval ? 2 : 0; cmdpush(run == 2 ? CS_ELSE : (s ? CS_ELIFTHEN : CS_IFTHEN)); execlist(state, 1, do_exec); cmdpop(); } else { noerrexit = olderrexit; lastval = 0; } state->pc = end; return lastval; }
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(); }