diff options
Diffstat (limited to 'Src/loop.c')
-rw-r--r-- | Src/loop.c | 421 |
1 files changed, 421 insertions, 0 deletions
diff --git a/Src/loop.c b/Src/loop.c new file mode 100644 index 000000000..5fbf2b841 --- /dev/null +++ b/Src/loop.c @@ -0,0 +1,421 @@ +/* + * 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 */ + +/**/ +int breaks; + +/**/ +int +execfor(Cmd cmd) +{ + List list; + Forcmd node; + char *str; + int val; + LinkList args; + + node = cmd->u.forcmd; + args = cmd->args; + if (node->condition) { + str = node->name; + singsub(&str); + if (!errflag) + matheval(str); + if (errflag) + return lastval = errflag; + } else if (!node->inflag) { + char **x; + + args = newlinklist(); + for (x = pparams; *x; x++) + addlinknode(args, ztrdup(*x)); + } + lastval = 0; + loops++; + pushheap(); + for (;;) { + if (node->condition) { + str = dupstring(node->condition); + singsub(&str); + if (!errflag) { + while (iblank(*str)) + str++; + if (*str) + val = matheval(str); + else + val = 1; + } + if (errflag) { + if (breaks) + breaks--; + lastval = 1; + break; + } + if (!val) + break; + } else { + str = (char *) ugetnode(args); + if (!str) + break; + setsparam(node->name, ztrdup(str)); + } + list = (List) dupstruct(node->list); + execlist(list, 1, (cmd->flags & CFLAG_EXEC) && empty(args)); + if (breaks) { + breaks--; + if (breaks || !contflag) + break; + contflag = 0; + } + if (node->condition && !errflag) { + str = dupstring(node->advance); + singsub(&str); + if (!errflag) + matheval(str); + } + if (errflag) { + if (breaks) + breaks--; + lastval = 1; + break; + } + freeheap(); + } + popheap(); + loops--; + return lastval; +} + +/**/ +int +execselect(Cmd cmd) +{ + List list; + Forcmd node; + char *str, *s; + LinkList args; + LinkNode n; + int i; + FILE *inp; + + node = cmd->u.forcmd; + args = cmd->args; + if (!node->inflag) { + char **x; + + args = newlinklist(); + for (x = pparams; *x; x++) + addlinknode(args, ztrdup(*x)); + } + if (empty(args)) + return 1; + loops++; + lastval = 0; + pushheap(); + inp = fdopen(dup((SHTTY == -1) ? 0 : SHTTY), "r"); + selectlist(args); + for (;;) { + for (;;) { + if (empty(bufstack)) { + if (interact && SHTTY != -1 && isset(USEZLE)) { + isfirstln = 1; + str = (char *)zleread(prompt3, NULL, 0); + } 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; + selectlist(args); + } + 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(node->name, ztrdup(str)); + list = (List) dupstruct(node->list); + execlist(list, 1, 0); + freeheap(); + if (breaks) { + breaks--; + if (breaks || !contflag) + break; + contflag = 0; + } + if (errflag) + break; + } + done: + popheap(); + fclose(inp); + loops--; + return lastval; +} + +/* And this is used to print select lists. */ + +/**/ +static void +selectlist(LinkList l) +{ + size_t longest = 1, fct, fw = 0, colsz, t0, t1, ct; + LinkNode n; + char **arr, **ap; + + trashzle(); + ct = countlinknodes(l); + ap = arr = (char **)alloc((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 = 0; t1 != colsz; 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); +} + +/**/ +int +execwhile(Cmd cmd) +{ + List list; + struct whilecmd *node; + int olderrexit, oldval; + + olderrexit = noerrexit; + node = cmd->u.whilecmd; + oldval = 0; + pushheap(); + loops++; + for (;;) { + list = (List) dupstruct(node->cont); + noerrexit = 1; + execlist(list, 1, 0); + noerrexit = olderrexit; + if (!((lastval == 0) ^ node->cond)) { + if (breaks) + breaks--; + lastval = oldval; + break; + } + list = (List) dupstruct(node->loop); + execlist(list, 1, 0); + if (breaks) { + breaks--; + if (breaks || !contflag) + break; + contflag = 0; + } + freeheap(); + if (errflag) { + lastval = 1; + break; + } + oldval = lastval; + } + popheap(); + loops--; + return lastval; +} + +/**/ +int +execrepeat(Cmd cmd) +{ + List list; + int count; + + lastval = 0; + if (empty(cmd->args) || nextnode(firstnode(cmd->args))) { + zerr("bad argument for repeat", NULL, 0); + return 1; + } + count = atoi(peekfirst(cmd->args)); + pushheap(); + loops++; + while (count--) { + list = (List) dupstruct(cmd->u.list); + execlist(list, 1, 0); + freeheap(); + if (breaks) { + breaks--; + if (breaks || !contflag) + break; + contflag = 0; + } + if (errflag) { + lastval = 1; + break; + } + } + popheap(); + loops--; + return lastval; +} + +/**/ +int +execif(Cmd cmd) +{ + struct ifcmd *node; + int olderrexit; + List *i, *t; + + olderrexit = noerrexit; + node = cmd->u.ifcmd; + i = node->ifls; + t = node->thenls; + + if (!noerrexit) + noerrexit = 1; + while (*i) { + execlist(*i, 1, 0); + if (!lastval) + break; + i++; + t++; + } + noerrexit = olderrexit; + + if (*t) + execlist(*t, 1, cmd->flags & CFLAG_EXEC); + else + lastval = 0; + + return lastval; +} + +/**/ +int +execcase(Cmd cmd) +{ + struct casecmd *node; + char *word; + List *l; + char **p; + + node = cmd->u.casecmd; + l = node->lists; + p = node->pats; + + word = *p++; + singsub(&word); + untokenize(word); + lastval = 0; + + if (node) { + while (*p) { + char *pat = *p + 1; + singsub(&pat); + if (matchpat(word, pat)) { + do { + execlist(*l++, 1, **p == ';' && (cmd->flags & CFLAG_EXEC)); + } while(**p++ == '&' && *p); + break; + } + p++; + l++; + } + } + return lastval; +} + |