summaryrefslogtreecommitdiff
path: root/Src/loop.c
diff options
context:
space:
mode:
Diffstat (limited to 'Src/loop.c')
-rw-r--r--Src/loop.c380
1 files changed, 271 insertions, 109 deletions
diff --git a/Src/loop.c b/Src/loop.c
index 5fbf2b841..d0280207a 100644
--- a/Src/loop.c
+++ b/Src/loop.c
@@ -43,47 +43,79 @@ int contflag;
/* # of break levels */
/**/
-int breaks;
-
+mod_export int breaks;
+
/**/
int
-execfor(Cmd cmd)
+execfor(Estate state, int do_exec)
{
- List list;
- Forcmd node;
- char *str;
- int val;
- LinkList args;
+ 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);
- node = cmd->u.forcmd;
- args = cmd->args;
- if (node->condition) {
- str = node->name;
+ 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)
+ if (errflag) {
+ state->pc = end;
return lastval = errflag;
- } else if (!node->inflag) {
+ }
+ 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, ztrdup(*x));
+ addlinknode(args, dupstring(*x));
}
lastval = 0;
loops++;
pushheap();
+ cmdpush(CS_FOR);
+ loop = state->pc;
for (;;) {
- if (node->condition) {
- str = dupstring(node->condition);
- singsub(&str);
+ if (iscond) {
+ if (ctok) {
+ str = dupstring(cond);
+ singsub(&str);
+ } else
+ str = cond;
if (!errflag) {
while (iblank(*str))
str++;
- if (*str)
- val = matheval(str);
- else
+ if (*str) {
+ if (isset(XTRACE)) {
+ printprompt4();
+ fprintf(xtrerr, "%s\n", str);
+ fflush(xtrerr);
+ }
+ val = mathevali(str);
+ } else
val = 1;
}
if (errflag) {
@@ -95,22 +127,36 @@ execfor(Cmd cmd)
if (!val)
break;
} else {
- str = (char *) ugetnode(args);
- if (!str)
+ if (!args || !(str = (char *) ugetnode(args)))
break;
- setsparam(node->name, ztrdup(str));
+ if (isset(XTRACE)) {
+ printprompt4();
+ fprintf(xtrerr, "%s=%s\n", name, str);
+ fflush(xtrerr);
+ }
+ setsparam(name, ztrdup(str));
}
- list = (List) dupstruct(node->list);
- execlist(list, 1, (cmd->flags & CFLAG_EXEC) && empty(args));
+ state->pc = loop;
+ execlist(state, 1, do_exec && args && empty(args));
if (breaks) {
breaks--;
if (breaks || !contflag)
break;
contflag = 0;
}
- if (node->condition && !errflag) {
- str = dupstring(node->advance);
- singsub(&str);
+ 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);
}
@@ -123,44 +169,67 @@ execfor(Cmd cmd)
freeheap();
}
popheap();
+ cmdpop();
loops--;
+ state->pc = end;
return lastval;
}
/**/
int
-execselect(Cmd cmd)
+execselect(Estate state, int do_exec)
{
- List list;
- Forcmd node;
- char *str, *s;
- LinkList args;
+ Wordcode end, loop;
+ wordcode code = state->pc[-1];
+ char *str, *s, *name;
LinkNode n;
- int i;
+ int i, usezle;
FILE *inp;
+ size_t more;
+ LinkList args;
+
+ end = state->pc + WC_FOR_SKIP(code);
+ name = ecgetstr(state, EC_NODUP, NULL);
- node = cmd->u.forcmd;
- args = cmd->args;
- if (!node->inflag) {
+ if (WC_SELECT_TYPE(code) == WC_SELECT_PPARAM) {
char **x;
args = newlinklist();
for (x = pparams; *x; x++)
- addlinknode(args, ztrdup(*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 (empty(args))
+ if (!args || empty(args)) {
+ state->pc = end;
return 1;
+ }
loops++;
lastval = 0;
pushheap();
- inp = fdopen(dup((SHTTY == -1) ? 0 : SHTTY), "r");
- selectlist(args);
+ 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 (interact && SHTTY != -1 && isset(USEZLE)) {
+ 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);
@@ -181,7 +250,7 @@ execselect(Cmd cmd)
*s = '\0';
if (*str)
break;
- selectlist(args);
+ more = selectlist(args, more);
}
setsparam("REPLY", ztrdup(str));
i = atoi(str);
@@ -194,9 +263,9 @@ execselect(Cmd cmd)
else
str = "";
}
- setsparam(node->name, ztrdup(str));
- list = (List) dupstruct(node->list);
- execlist(list, 1, 0);
+ setsparam(name, ztrdup(str));
+ state->pc = loop;
+ execlist(state, 1, 0);
freeheap();
if (breaks) {
breaks--;
@@ -204,21 +273,23 @@ execselect(Cmd cmd)
break;
contflag = 0;
}
- if (errflag)
+ if (retflag || errflag)
break;
}
done:
+ cmdpop();
popheap();
fclose(inp);
loops--;
+ state->pc = end;
return lastval;
}
/* And this is used to print select lists. */
/**/
-static void
-selectlist(LinkList l)
+size_t
+selectlist(LinkList l, size_t start)
{
size_t longest = 1, fct, fw = 0, colsz, t0, t1, ct;
LinkNode n;
@@ -226,7 +297,7 @@ selectlist(LinkList l)
trashzle();
ct = countlinknodes(l);
- ap = arr = (char **)alloc((countlinknodes(l) + 1) * sizeof(char **));
+ ap = arr = (char **) zhalloc((countlinknodes(l) + 1) * sizeof(char **));
for (n = (LinkNode) firstnode(l); n; incnode(n))
*ap++ = (char *)getdata(n);
@@ -245,7 +316,7 @@ selectlist(LinkList l)
else
fw = (columns - 1) / fct;
colsz = (ct + fct - 1) / fct;
- for (t1 = 0; t1 != colsz; t1++) {
+ for (t1 = start; t1 != colsz && t1 - start < lines - 2; t1++) {
ap = arr + t1;
do {
int t2 = strlen(*ap) + 2, t3;
@@ -271,70 +342,86 @@ selectlist(LinkList l)
}
while (*ap);*/
fflush(stderr);
+
+ return t1 < colsz ? t1 : 0;
}
/**/
int
-execwhile(Cmd cmd)
+execwhile(Estate state, int do_exec)
{
- List list;
- struct whilecmd *node;
- int olderrexit, oldval;
+ 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;
- node = cmd->u.whilecmd;
oldval = 0;
pushheap();
+ cmdpush(isuntil ? CS_UNTIL : CS_WHILE);
loops++;
+ loop = state->pc;
for (;;) {
- list = (List) dupstruct(node->cont);
+ state->pc = loop;
noerrexit = 1;
- execlist(list, 1, 0);
+ execlist(state, 1, 0);
noerrexit = olderrexit;
- if (!((lastval == 0) ^ node->cond)) {
+ if (!((lastval == 0) ^ isuntil)) {
if (breaks)
breaks--;
lastval = oldval;
break;
}
- list = (List) dupstruct(node->loop);
- execlist(list, 1, 0);
+ if (retflag) {
+ lastval = oldval;
+ break;
+ }
+ execlist(state, 1, 0);
if (breaks) {
breaks--;
if (breaks || !contflag)
break;
contflag = 0;
}
- freeheap();
if (errflag) {
lastval = 1;
break;
}
+ if (retflag)
+ break;
+ freeheap();
oldval = lastval;
}
+ cmdpop();
popheap();
loops--;
+ state->pc = end;
return lastval;
}
/**/
int
-execrepeat(Cmd cmd)
+execrepeat(Estate state, int do_exec)
{
- List list;
- int count;
+ Wordcode end, loop;
+ wordcode code = state->pc[-1];
+ int count, htok = 0;
+ char *tmp;
+
+ end = state->pc + WC_REPEAT_SKIP(code);
lastval = 0;
- if (empty(cmd->args) || nextnode(firstnode(cmd->args))) {
- zerr("bad argument for repeat", NULL, 0);
- return 1;
- }
- count = atoi(peekfirst(cmd->args));
+ tmp = ecgetstr(state, EC_DUPTOK, &htok);
+ if (htok)
+ singsub(&tmp);
+ count = atoi(tmp);
pushheap();
+ cmdpush(CS_REPEAT);
loops++;
- while (count--) {
- list = (List) dupstruct(cmd->u.list);
- execlist(list, 1, 0);
+ loop = state->pc;
+ while (count-- > 0) {
+ state->pc = loop;
+ execlist(state, 1, 0);
freeheap();
if (breaks) {
breaks--;
@@ -346,76 +433,151 @@ execrepeat(Cmd cmd)
lastval = 1;
break;
}
+ if (retflag)
+ break;
}
+ cmdpop();
popheap();
loops--;
+ state->pc = end;
return lastval;
}
/**/
int
-execif(Cmd cmd)
+execif(Estate state, int do_exec)
{
- struct ifcmd *node;
- int olderrexit;
- List *i, *t;
+ Wordcode end, next;
+ wordcode code = state->pc[-1];
+ int olderrexit, s = 0, run = 0;
olderrexit = noerrexit;
- node = cmd->u.ifcmd;
- i = node->ifls;
- t = node->thenls;
+ end = state->pc + WC_IF_SKIP(code);
if (!noerrexit)
noerrexit = 1;
- while (*i) {
- execlist(*i, 1, 0);
- if (!lastval)
+ 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;
- i++;
- t++;
+ }
+ 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 (*t)
- execlist(*t, 1, cmd->flags & CFLAG_EXEC);
- else
+ 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(Cmd cmd)
+execcase(Estate state, int do_exec)
{
- struct casecmd *node;
- char *word;
- List *l;
- char **p;
+ Wordcode end, next;
+ wordcode code = state->pc[-1];
+ char *word, *pat;
+ int npat, save;
+ Patprog *spprog, pprog;
- node = cmd->u.casecmd;
- l = node->lists;
- p = node->pats;
+ end = state->pc + WC_CASE_SKIP(code);
- word = *p++;
+ word = ecgetstr(state, EC_DUP, NULL);
singsub(&word);
untokenize(word);
lastval = 0;
- if (node) {
- while (*p) {
- char *pat = *p + 1;
+ 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);
- if (matchpat(word, pat)) {
- do {
- execlist(*l++, 1, **p == ';' && (cmd->flags & CFLAG_EXEC));
- } while(**p++ == '&' && *p);
- break;
+ 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);
}
- p++;
- l++;
+ 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;
}
-