/*
 * $Id: loop.c,v 1.9 1995/05/02 04:16:17 coleman Exp coleman $
 *
 * loop.c - loop execution
 *
 * This file is part of zsh, the Z shell.
 *
 * Copyright (c) 1992-1995 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 its documentation 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.h"

/**/
int
execfor(Cmd cmd)
{
    List list;
    Forcmd node;
    char *str;
    Lklist args;
    int cj = thisjob;

    loops++;
    lastval = 0;
    node = cmd->u.forcmd;
    args = cmd->args;
    if (!node->inflag) {
	char **x;

	args = newlist();
	for (x = pparams; *x; x++)
	    addnode(args, ztrdup(*x));
    }
    pushheap();
    while ((str = (char *)ugetnode(args))) {
	setsparam(node->name, ztrdup(str));
	list = (List) dupstruct(node->list);
	execlist(list, 0);
	if (breaks) {
	    breaks--;
	    if (breaks || !contflag)
		break;
	    contflag = 0;
	}
	if (errflag) {
	    lastval = 1;
	    break;
	}
	freeheap();
    }
    popheap();
    thisjob = cj;
    loops--;
    return lastval;
}

/**/
int
execselect(Cmd cmd)
{
    List list;
    Forcmd node;
    char *str, *s;
    Lklist args;
    Lknode n;
    int cj = thisjob, t0;
    FILE *inp;

    node = cmd->u.forcmd;
    args = cmd->args;
    if (!node->inflag) {
	char **x;

	args = newlist();
	for (x = pparams; *x; x++)
	    addnode(args, ztrdup(*x));
    }
    if (empty(args))
	return 1;
    loops++;
    lastval = 0;
    pushheap();
    inp = fdopen(dup((SHTTY == -1) ? 0 : SHTTY), "r");
    for (;;) {
	do {
	    selectlist(args);
	    if (!full(bufstack)) {
	    	if (interact && SHTTY != -1 && isset(USEZLE))
		    str = (char *)zleread(prompt3, NULL);
	    	else {
		    int pptlen;
		    str = putprompt(prompt3, &pptlen, NULL, 1);
		    fwrite(str, pptlen, 1, stderr);
		    fflush(stderr);
		    str = fgets(zalloc(256), 256, inp);
	    	}
	    } else
		str = (char *)getnode(bufstack);
	    if (!str || errflag) {
		if (breaks)
		    breaks--;
		fprintf(stderr, "\n");
		fflush(stderr);
		goto done;
	    }
	    if ((s = strchr(str, '\n')))
		*s = '\0';
	}
	while (!*str);
	setsparam("REPLY", ztrdup(str));
	t0 = atoi(str);
	if (!t0)
	    str = "";
	else {
	    for (t0--, n = firstnode(args); n && t0; incnode(n), t0--);
	    if (n)
		str = (char *)getdata(n);
	    else
		str = "";
	}
	setsparam(node->name, ztrdup(str));
	list = (List) dupstruct(node->list);
	execlist(list, 0);
	freeheap();
	if (breaks) {
	    breaks--;
	    if (breaks || !contflag)
		break;
	    contflag = 0;
	}
	if (errflag)
	    break;
    }
  done:
    popheap();
    fclose(inp);
    thisjob = cj;
    loops--;
    return lastval;
}

/**/
int
execwhile(Cmd cmd)
{
    List list;
    struct whilecmd *node;
    int cj = thisjob, osl = sourcelevel;

    node = cmd->u.whilecmd;
    lastval = 0;
    pushheap();
    loops++;
    for (;;) {
	int oldval = lastval;

	list = (List) dupstruct(node->cont);
	sourcelevel |= 32768;
	execlist(list, 0);
	sourcelevel = osl;
	if (!((lastval == 0) ^ node->cond)) {
	    if (breaks)
		breaks--;
	    lastval = oldval;
	    break;
	}
	list = (List) dupstruct(node->loop);
	execlist(list, 0);
	if (breaks) {
	    breaks--;
	    if (breaks || !contflag)
		break;
	    contflag = 0;
	}
	freeheap();
	if (errflag) {
	    lastval = 1;
	    break;
	}
    }
    popheap();
    thisjob = cj;
    loops--;
    return lastval;
}

/**/
int
execrepeat(Cmd cmd)
{
    List list;
    int cj = thisjob, 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, 0);
	freeheap();
	if (breaks) {
	    breaks--;
	    if (breaks || !contflag)
		break;
	    contflag = 0;
	}
	if (errflag) {
	    lastval = 1;
	    break;
	}
    }
    popheap();
    thisjob = cj;
    loops--;
    return lastval;
}

/**/
int
execif(Cmd cmd)
{
    struct ifcmd *node;
    int cj = thisjob, osl = sourcelevel;
    List *i, *t;

    node = cmd->u.ifcmd;
    i = node->ifls;
    t = node->thenls;

    sourcelevel |= 32768;
    while (*i) {
	execlist(*i, 0);
	if (!lastval)
	    break;
	i++;
	t++;
    }
    sourcelevel = osl;

    if (*t)
	execlist(*t, 0);
    else
	lastval = 0;

    thisjob = cj;
    return lastval;
}

/**/
int
execcase(Cmd cmd)
{
    struct casecmd *node;
    char *word;
    Lklist args;
    int cj = thisjob;
    List *l;
    char **p;

    node = cmd->u.casecmd;
    args = cmd->args;
    l = node->lists;
    p = node->pats;

    lastval = 0;
    if (firstnode(args) && nextnode(firstnode(args))) {
	zerr("too many arguments to case", NULL, 0);
	return 1;
    }
    if (empty(args))
	word = dupstring("");
    else
	word = (char *)peekfirst(args);

    if (node) {
	while (*p) {
	    singsub(p);
	    if (matchpat(word, *p))
		break;
	    p++;
	    l++;
	}
	if (*l)
	    execlist(*l, 0);
    }
    thisjob = cj;
    return lastval;
}

