summaryrefslogtreecommitdiff
path: root/Src/loop.c
diff options
context:
space:
mode:
Diffstat (limited to 'Src/loop.c')
-rw-r--r--Src/loop.c421
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;
+}
+