mirror of
				git://git.code.sf.net/p/zsh/code
				synced 2025-11-04 07:21:06 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			583 lines
		
	
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			583 lines
		
	
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * loop.c - loop execution
 | 
						|
 *
 | 
						|
 * This file is part of zsh, the Z shell.
 | 
						|
 *
 | 
						|
 * Copyright (c) 1992-1997 Paul Falstad
 | 
						|
 * All rights reserved.
 | 
						|
 *
 | 
						|
 * Permission is hereby granted, without written agreement and without
 | 
						|
 * license or royalty fees, to use, copy, modify, and distribute this
 | 
						|
 * software and to distribute modified versions of this software for any
 | 
						|
 * purpose, provided that the above copyright notice and the following
 | 
						|
 * two paragraphs appear in all copies of this software.
 | 
						|
 *
 | 
						|
 * In no event shall Paul Falstad or the Zsh Development Group be liable
 | 
						|
 * to any party for direct, indirect, special, incidental, or consequential
 | 
						|
 * damages arising out of the use of this software and its documentation,
 | 
						|
 * even if Paul Falstad and the Zsh Development Group have been advised of
 | 
						|
 * the possibility of such damage.
 | 
						|
 *
 | 
						|
 * Paul Falstad and the Zsh Development Group specifically disclaim any
 | 
						|
 * warranties, including, but not limited to, the implied warranties of
 | 
						|
 * merchantability and fitness for a particular purpose.  The software
 | 
						|
 * provided hereunder is on an "as is" basis, and Paul Falstad and the
 | 
						|
 * Zsh Development Group have no obligation to provide maintenance,
 | 
						|
 * support, updates, enhancements, or modifications.
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
#include "zsh.mdh"
 | 
						|
#include "loop.pro"
 | 
						|
 | 
						|
/* # of nested loops we are in */
 | 
						|
 
 | 
						|
/**/
 | 
						|
int loops;
 | 
						|
 
 | 
						|
/* # of continue levels */
 | 
						|
 
 | 
						|
/**/
 | 
						|
int contflag;
 | 
						|
 
 | 
						|
/* # of break levels */
 | 
						|
 
 | 
						|
/**/
 | 
						|
mod_export int breaks;
 | 
						|
 | 
						|
/**/
 | 
						|
int
 | 
						|
execfor(Estate state, int do_exec)
 | 
						|
{
 | 
						|
    Wordcode end, loop;
 | 
						|
    wordcode code = state->pc[-1];
 | 
						|
    int iscond = (WC_FOR_TYPE(code) == WC_FOR_COND), ctok = 0, atok = 0;
 | 
						|
    char *name, *str, *cond = NULL, *advance = NULL;
 | 
						|
    zlong val = 0;
 | 
						|
    LinkList args = NULL;
 | 
						|
 | 
						|
    name = ecgetstr(state, EC_NODUP, NULL);
 | 
						|
    end = state->pc + WC_FOR_SKIP(code);
 | 
						|
 | 
						|
    if (iscond) {
 | 
						|
	str = dupstring(name);
 | 
						|
	singsub(&str);
 | 
						|
	if (isset(XTRACE)) {
 | 
						|
	    char *str2 = dupstring(str);
 | 
						|
	    untokenize(str2);
 | 
						|
	    printprompt4();
 | 
						|
	    fprintf(xtrerr, "%s\n", str2);
 | 
						|
	    fflush(xtrerr);
 | 
						|
	}
 | 
						|
	if (!errflag)
 | 
						|
	    matheval(str);
 | 
						|
	if (errflag) {
 | 
						|
	    state->pc = end;
 | 
						|
	    return lastval = errflag;
 | 
						|
	}
 | 
						|
	cond = ecgetstr(state, EC_NODUP, &ctok);
 | 
						|
	advance = ecgetstr(state, EC_NODUP, &atok);
 | 
						|
    } else if (WC_FOR_TYPE(code) == WC_FOR_LIST) {
 | 
						|
	int htok = 0;
 | 
						|
 | 
						|
	if (!(args = ecgetlist(state, *state->pc++, EC_DUPTOK, &htok))) {
 | 
						|
	    state->pc = end;
 | 
						|
	    return 0;
 | 
						|
	}
 | 
						|
	if (htok)
 | 
						|
	    execsubst(args);
 | 
						|
    } else {
 | 
						|
	char **x;
 | 
						|
 | 
						|
	args = newlinklist();
 | 
						|
	for (x = pparams; *x; x++)
 | 
						|
	    addlinknode(args, dupstring(*x));
 | 
						|
    }
 | 
						|
    lastval = 0;
 | 
						|
    loops++;
 | 
						|
    pushheap();
 | 
						|
    cmdpush(CS_FOR);
 | 
						|
    loop = state->pc;
 | 
						|
    for (;;) {
 | 
						|
	if (iscond) {
 | 
						|
	    if (ctok) {
 | 
						|
		str = dupstring(cond);
 | 
						|
		singsub(&str);
 | 
						|
	    } else
 | 
						|
		str = cond;
 | 
						|
	    if (!errflag) {
 | 
						|
		while (iblank(*str))
 | 
						|
		    str++;
 | 
						|
		if (*str) {
 | 
						|
		    if (isset(XTRACE)) {
 | 
						|
			printprompt4();
 | 
						|
			fprintf(xtrerr, "%s\n", str);
 | 
						|
			fflush(xtrerr);
 | 
						|
		    }
 | 
						|
		    val = mathevali(str);
 | 
						|
		} else
 | 
						|
		    val = 1;
 | 
						|
	    }
 | 
						|
	    if (errflag) {
 | 
						|
		if (breaks)
 | 
						|
		    breaks--;
 | 
						|
		lastval = 1;
 | 
						|
		break;
 | 
						|
	    }
 | 
						|
	    if (!val)
 | 
						|
		break;
 | 
						|
	} else {
 | 
						|
	    if (!args || !(str = (char *) ugetnode(args)))
 | 
						|
		break;
 | 
						|
	    if (isset(XTRACE)) {
 | 
						|
		printprompt4();
 | 
						|
		fprintf(xtrerr, "%s=%s\n", name, str);
 | 
						|
		fflush(xtrerr);
 | 
						|
	    }
 | 
						|
	    setsparam(name, ztrdup(str));
 | 
						|
	}
 | 
						|
	state->pc = loop;
 | 
						|
	execlist(state, 1, do_exec && args && empty(args));
 | 
						|
	if (breaks) {
 | 
						|
	    breaks--;
 | 
						|
	    if (breaks || !contflag)
 | 
						|
		break;
 | 
						|
	    contflag = 0;
 | 
						|
	}
 | 
						|
	if (retflag)
 | 
						|
	    break;
 | 
						|
	if (iscond && !errflag) {
 | 
						|
	    if (atok) {
 | 
						|
		str = dupstring(advance);
 | 
						|
		singsub(&str);
 | 
						|
	    } else
 | 
						|
		str = advance;
 | 
						|
	    if (isset(XTRACE)) {
 | 
						|
		printprompt4();
 | 
						|
		fprintf(xtrerr, "%s\n", str);
 | 
						|
		fflush(xtrerr);
 | 
						|
	    }
 | 
						|
	    if (!errflag)
 | 
						|
		matheval(str);
 | 
						|
	}
 | 
						|
	if (errflag) {
 | 
						|
	    if (breaks)
 | 
						|
		breaks--;
 | 
						|
	    lastval = 1;
 | 
						|
	    break;
 | 
						|
	}
 | 
						|
	freeheap();
 | 
						|
    }
 | 
						|
    popheap();
 | 
						|
    cmdpop();
 | 
						|
    loops--;
 | 
						|
    state->pc = end;
 | 
						|
    return lastval;
 | 
						|
}
 | 
						|
 | 
						|
/**/
 | 
						|
int
 | 
						|
execselect(Estate state, 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;
 | 
						|
 | 
						|
    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;
 | 
						|
	    return 0;
 | 
						|
	}
 | 
						|
	if (htok)
 | 
						|
	    execsubst(args);
 | 
						|
    }
 | 
						|
    if (!args || empty(args)) {
 | 
						|
	state->pc = end;
 | 
						|
	return 1;
 | 
						|
    }
 | 
						|
    loops++;
 | 
						|
    lastval = 0;
 | 
						|
    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 = (char *)zleread(prompt3, NULL, 0);
 | 
						|
		    if (errflag)
 | 
						|
			str = NULL;
 | 
						|
		    errflag = oef;
 | 
						|
	    	} else {
 | 
						|
		    str = promptexpand(prompt3, 0, NULL, NULL);
 | 
						|
		    zputs(str, stderr);
 | 
						|
		    free(str);
 | 
						|
		    fflush(stderr);
 | 
						|
		    str = fgets(zalloc(256), 256, inp);
 | 
						|
	    	}
 | 
						|
	    } else
 | 
						|
		str = (char *)getlinknode(bufstack);
 | 
						|
	    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--;
 | 
						|
    state->pc = end;
 | 
						|
    return lastval;
 | 
						|
}
 | 
						|
 | 
						|
/* And this is used to print select lists. */
 | 
						|
 | 
						|
/**/
 | 
						|
size_t
 | 
						|
selectlist(LinkList l, size_t start)
 | 
						|
{
 | 
						|
    size_t longest = 1, fct, fw = 0, colsz, t0, t1, ct;
 | 
						|
    LinkNode n;
 | 
						|
    char **arr, **ap;
 | 
						|
 | 
						|
    trashzle();
 | 
						|
    ct = countlinknodes(l);
 | 
						|
    ap = arr = (char **) zhalloc((countlinknodes(l) + 1) * sizeof(char **));
 | 
						|
 | 
						|
    for (n = (LinkNode) firstnode(l); n; incnode(n))
 | 
						|
	*ap++ = (char *)getdata(n);
 | 
						|
    *ap = NULL;
 | 
						|
    for (ap = arr; *ap; ap++)
 | 
						|
	if (strlen(*ap) > longest)
 | 
						|
	    longest = strlen(*ap);
 | 
						|
    t0 = ct;
 | 
						|
    longest++;
 | 
						|
    while (t0)
 | 
						|
	t0 /= 10, longest++;
 | 
						|
    /* to compensate for added ')' */
 | 
						|
    fct = (columns - 1) / (longest + 3);
 | 
						|
    if (fct == 0)
 | 
						|
	fct = 1;
 | 
						|
    else
 | 
						|
	fw = (columns - 1) / fct;
 | 
						|
    colsz = (ct + fct - 1) / fct;
 | 
						|
    for (t1 = start; t1 != colsz && t1 - start < lines - 2; t1++) {
 | 
						|
	ap = arr + t1;
 | 
						|
	do {
 | 
						|
	    int t2 = strlen(*ap) + 2, t3;
 | 
						|
 | 
						|
	    fprintf(stderr, "%d) %s", t3 = ap - arr + 1, *ap);
 | 
						|
	    while (t3)
 | 
						|
		t2++, t3 /= 10;
 | 
						|
	    for (; t2 < fw; t2++)
 | 
						|
		fputc(' ', stderr);
 | 
						|
	    for (t0 = colsz; t0 && *ap; t0--, ap++);
 | 
						|
	}
 | 
						|
	while (*ap);
 | 
						|
	fputc('\n', stderr);
 | 
						|
    }
 | 
						|
 | 
						|
 /* Below is a simple attempt at doing it the Korn Way..
 | 
						|
       ap = arr;
 | 
						|
       t0 = 0;
 | 
						|
       do {
 | 
						|
           t0++;
 | 
						|
           fprintf(stderr,"%d) %s\n",t0,*ap);
 | 
						|
           ap++;
 | 
						|
       }
 | 
						|
       while (*ap);*/
 | 
						|
    fflush(stderr);
 | 
						|
 | 
						|
    return t1 < colsz ? t1 : 0;
 | 
						|
}
 | 
						|
 | 
						|
/**/
 | 
						|
int
 | 
						|
execwhile(Estate state, int do_exec)
 | 
						|
{
 | 
						|
    Wordcode end, loop;
 | 
						|
    wordcode code = state->pc[-1];
 | 
						|
    int olderrexit, oldval, isuntil = (WC_WHILE_TYPE(code) == WC_WHILE_UNTIL);
 | 
						|
 | 
						|
    end = state->pc + WC_WHILE_SKIP(code);
 | 
						|
    olderrexit = noerrexit;
 | 
						|
    oldval = 0;
 | 
						|
    pushheap();
 | 
						|
    cmdpush(isuntil ? CS_UNTIL : CS_WHILE);
 | 
						|
    loops++;
 | 
						|
    loop = state->pc;
 | 
						|
    for (;;) {
 | 
						|
	state->pc = loop;
 | 
						|
	noerrexit = 1;
 | 
						|
	execlist(state, 1, 0);
 | 
						|
	noerrexit = olderrexit;
 | 
						|
	if (!((lastval == 0) ^ isuntil)) {
 | 
						|
	    if (breaks)
 | 
						|
		breaks--;
 | 
						|
	    lastval = oldval;
 | 
						|
	    break;
 | 
						|
	}
 | 
						|
	if (retflag) {
 | 
						|
	    lastval = oldval;
 | 
						|
	    break;
 | 
						|
	}
 | 
						|
	execlist(state, 1, 0);
 | 
						|
	if (breaks) {
 | 
						|
	    breaks--;
 | 
						|
	    if (breaks || !contflag)
 | 
						|
		break;
 | 
						|
	    contflag = 0;
 | 
						|
	}
 | 
						|
	if (errflag) {
 | 
						|
	    lastval = 1;
 | 
						|
	    break;
 | 
						|
	}
 | 
						|
	if (retflag)
 | 
						|
	    break;
 | 
						|
	freeheap();
 | 
						|
	oldval = lastval;
 | 
						|
    }
 | 
						|
    cmdpop();
 | 
						|
    popheap();
 | 
						|
    loops--;
 | 
						|
    state->pc = end;
 | 
						|
    return lastval;
 | 
						|
}
 | 
						|
 | 
						|
/**/
 | 
						|
int
 | 
						|
execrepeat(Estate state, int do_exec)
 | 
						|
{
 | 
						|
    Wordcode end, loop;
 | 
						|
    wordcode code = state->pc[-1];
 | 
						|
    int count, htok = 0;
 | 
						|
    char *tmp;
 | 
						|
 | 
						|
    end = state->pc + WC_REPEAT_SKIP(code);
 | 
						|
 | 
						|
    lastval = 0;
 | 
						|
    tmp = ecgetstr(state, EC_DUPTOK, &htok);
 | 
						|
    if (htok)
 | 
						|
	singsub(&tmp);
 | 
						|
    count = atoi(tmp);
 | 
						|
    pushheap();
 | 
						|
    cmdpush(CS_REPEAT);
 | 
						|
    loops++;
 | 
						|
    loop = state->pc;
 | 
						|
    while (count-- > 0) {
 | 
						|
	state->pc = loop;
 | 
						|
	execlist(state, 1, 0);
 | 
						|
	freeheap();
 | 
						|
	if (breaks) {
 | 
						|
	    breaks--;
 | 
						|
	    if (breaks || !contflag)
 | 
						|
		break;
 | 
						|
	    contflag = 0;
 | 
						|
	}
 | 
						|
	if (errflag) {
 | 
						|
	    lastval = 1;
 | 
						|
	    break;
 | 
						|
	}
 | 
						|
	if (retflag)
 | 
						|
	    break;
 | 
						|
    }
 | 
						|
    cmdpop();
 | 
						|
    popheap();
 | 
						|
    loops--;
 | 
						|
    state->pc = end;
 | 
						|
    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;
 | 
						|
    }
 | 
						|
    noerrexit = olderrexit;
 | 
						|
 | 
						|
    if (run) {
 | 
						|
	cmdpush(run == 2 ? CS_ELSE : (s ? CS_ELIFTHEN : CS_IFTHEN));
 | 
						|
	execlist(state, 1, do_exec);
 | 
						|
	cmdpop();
 | 
						|
    } else
 | 
						|
	lastval = 0;
 | 
						|
    state->pc = end;
 | 
						|
 | 
						|
    return lastval;
 | 
						|
}
 | 
						|
 | 
						|
/**/
 | 
						|
int
 | 
						|
execcase(Estate state, int do_exec)
 | 
						|
{
 | 
						|
    Wordcode end, next;
 | 
						|
    wordcode code = state->pc[-1];
 | 
						|
    char *word, *pat;
 | 
						|
    int npat, save;
 | 
						|
    Patprog *spprog, pprog;
 | 
						|
 | 
						|
    end = state->pc + WC_CASE_SKIP(code);
 | 
						|
 | 
						|
    word = ecgetstr(state, EC_DUP, NULL);
 | 
						|
    singsub(&word);
 | 
						|
    untokenize(word);
 | 
						|
    lastval = 0;
 | 
						|
 | 
						|
    cmdpush(CS_CASE);
 | 
						|
    while (state->pc < end) {
 | 
						|
	code = *state->pc++;
 | 
						|
	if (wc_code(code) != WC_CASE)
 | 
						|
	    break;
 | 
						|
 | 
						|
	pat = NULL;
 | 
						|
	pprog = NULL;
 | 
						|
	save = 0;
 | 
						|
	npat = state->pc[1];
 | 
						|
	spprog = state->prog->pats + npat;
 | 
						|
 | 
						|
	next = state->pc + WC_CASE_SKIP(code);
 | 
						|
 | 
						|
	if (isset(XTRACE)) {
 | 
						|
	    char *pat2, *opat;
 | 
						|
 | 
						|
	    opat = pat = ecgetstr(state, EC_DUP, NULL);
 | 
						|
	    singsub(&pat);
 | 
						|
	    save = (!(state->prog->flags & EF_HEAP) &&
 | 
						|
		    !strcmp(pat, opat) && *spprog != dummy_patprog2);
 | 
						|
 | 
						|
	    pat2 = dupstring(pat);
 | 
						|
	    untokenize(pat2);
 | 
						|
	    printprompt4();
 | 
						|
	    fprintf(xtrerr, "case %s (%s)\n", word, pat2);
 | 
						|
	    fflush(xtrerr);
 | 
						|
	    state->pc++;
 | 
						|
	} else
 | 
						|
	    state->pc += 2;
 | 
						|
 | 
						|
	if (*spprog != dummy_patprog1 && *spprog != dummy_patprog2)
 | 
						|
	    pprog = *spprog;
 | 
						|
 | 
						|
	if (!pprog) {
 | 
						|
	    if (!pat) {
 | 
						|
		char *opat;
 | 
						|
		int htok = 0;
 | 
						|
 | 
						|
		opat = pat = dupstring(ecrawstr(state->prog,
 | 
						|
						state->pc - 2, &htok));
 | 
						|
		if (htok)
 | 
						|
		    singsub(&pat);
 | 
						|
		save = (!(state->prog->flags & EF_HEAP) &&
 | 
						|
			!strcmp(pat, opat) && *spprog != dummy_patprog2);
 | 
						|
	    }
 | 
						|
	    if (!(pprog = patcompile(pat, (save ? PAT_ZDUP : PAT_STATIC),
 | 
						|
				     NULL)))
 | 
						|
		zerr("bad pattern: %s", pat, 0);
 | 
						|
	    else if (save)
 | 
						|
		*spprog = pprog;
 | 
						|
	}
 | 
						|
	if (pprog && pattry(pprog, word)) {
 | 
						|
	    execlist(state, 1, ((WC_CASE_TYPE(code) == WC_CASE_OR) &&
 | 
						|
				do_exec));
 | 
						|
	    while (!retflag && wc_code(code) == WC_CASE &&
 | 
						|
		   WC_CASE_TYPE(code) == WC_CASE_AND) {
 | 
						|
		state->pc = next;
 | 
						|
		code = *state->pc;
 | 
						|
		state->pc += 3;
 | 
						|
		next = state->pc + WC_CASE_SKIP(code) - 1;
 | 
						|
		execlist(state, 1, ((WC_CASE_TYPE(code) == WC_CASE_OR) &&
 | 
						|
				    do_exec));
 | 
						|
	    }
 | 
						|
	    break;
 | 
						|
	} else
 | 
						|
	    state->pc = next;
 | 
						|
    }
 | 
						|
    cmdpop();
 | 
						|
 | 
						|
    state->pc = end;
 | 
						|
 | 
						|
    return lastval;
 | 
						|
}
 |