1
0
mirror of git://git.code.sf.net/p/zsh/code synced 2024-11-19 13:33:52 +01:00
zsh/Src/loop.c
1999-04-15 18:05:38 +00:00

422 lines
7.8 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 */
/**/
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;
}