15030: multi-parameter `for' loops

This commit is contained in:
Peter Stephenson 2001-06-25 16:07:51 +00:00
parent bbd2a98f41
commit 1897a361bf
5 changed files with 85 additions and 39 deletions

View File

@ -1,3 +1,10 @@
2001-06-25 Peter Stephenson <pws@csr.com>
* 15030: Doc/Zsh/grammar.yo, Src/loop.c, Src/parse.c, Src/text.c:
`for' loops can take multiple parameter names before the `in'
or left parenthesis, each of which takes one word from the list
on each iteration.
2001-06-25 Sven Wischnowsky <wischnow@zsh.org>
* user/3940: Src/Zle/zle_tricky.c: make expand-word not always

View File

@ -149,12 +149,21 @@ If each tt(elif) var(list) returns nonzero, the tt(else) var(list) is executed.
findex(for)
cindex(for loops)
cindex(loops, for)
item(tt(for) var(name) [ tt(in) var(word) ... var(term) ] tt(do) var(list) tt(done))(
item(tt(for) var(name) ... [ tt(in) var(word) ... ] var(term) tt(do) var(list) tt(done))(
where var(term) is at least one newline or tt(;).
Expand the list of var(word)s, and set the parameter
var(name) to each of them in turn, executing
var(list) each time. If the tt(in) var(word) is omitted,
use the positional parameters instead of the var(word)s.
More than one parameter var(name) can appear before the list of
var(word)s. If var(N) var(name)s are given, then on each execution of the
loop the next tt(N) var(word)s are assigned to the corresponding
parameters. If there are more var(name)s than remaining var(word)s, the
remaining parameters are each set to the empty string. Execution of the
loop ends when there is no remaining var(word) to assign to the first
var(name). It is only possible for tt(in) to appear as the first var(name)
in the list, else it will be treated as marking the end of the list.
)
item(tt(for LPAR()LPAR()) [var(expr1)] tt(;) [var(expr2)] tt(;) [var(expr3)] tt(RPAR()RPAR() do) var(list) tt(done))(
The arithmetic expression var(expr1) is evaluated first (see
@ -289,17 +298,17 @@ does em(not), since the test is not suitably delimited.
item(tt(if) var(list) var(sublist))(
A short form of the alternate `if'.
)
item(tt(for) var(name) tt(LPAR()) var(word) ... tt(RPAR()) var(sublist))(
item(tt(for) var(name) ... tt(LPAR()) var(word) ... tt(RPAR()) var(sublist))(
A short form of tt(for).
)
item(tt(for) var(name) [ tt(in) var(word) ... var(term) ] var(sublist))(
item(tt(for) var(name) ... [ tt(in) var(word) ... ] var(term) var(sublist))(
where var(term) is at least one newline or tt(;).
Another short form of tt(for).
)
item(tt(for LPAR()LPAR()) [var(expr1)] tt(;) [var(expr2)] tt(;) [var(expr3)] tt(RPAR()RPAR()) var(sublist))(
A short form of the arithmetic tt(for) command.
)
item(tt(foreach) var(name) tt(LPAR()) var(word) ... tt(RPAR()) var(list) tt(end))(
item(tt(foreach) var(name) ... tt(LPAR()) var(word) ... tt(RPAR()) var(list) tt(end))(
Another form of tt(for).
)
item(tt(while) var(list) tt({) var(list) tt(}))(

View File

@ -52,15 +52,15 @@ execfor(Estate state, int do_exec)
Wordcode end, loop;
wordcode code = state->pc[-1];
int iscond = (WC_FOR_TYPE(code) == WC_FOR_COND), ctok = 0, atok = 0;
int last = 0;
char *name, *str, *cond = NULL, *advance = NULL;
zlong val = 0;
LinkList args = NULL;
LinkList vars = NULL, args = NULL;
name = ecgetstr(state, EC_NODUP, NULL);
end = state->pc + WC_FOR_SKIP(code);
if (iscond) {
str = dupstring(name);
str = dupstring(ecgetstr(state, EC_NODUP, NULL));
singsub(&str);
if (isset(XTRACE)) {
char *str2 = dupstring(str);
@ -77,28 +77,32 @@ execfor(Estate state, int do_exec)
}
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;
vars = ecgetlist(state, *state->pc++, EC_NODUP, NULL);
args = newlinklist();
for (x = pparams; *x; x++)
addlinknode(args, dupstring(*x));
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, dupstring(*x));
}
}
lastval = 0;
loops++;
pushheap();
cmdpush(CS_FOR);
loop = state->pc;
for (;;) {
while (!last) {
if (iscond) {
if (ctok) {
str = dupstring(cond);
@ -127,14 +131,29 @@ execfor(Estate state, int do_exec)
if (!val)
break;
} else {
if (!args || !(str = (char *) ugetnode(args)))
break;
if (isset(XTRACE)) {
printprompt4();
fprintf(xtrerr, "%s=%s\n", name, str);
fflush(xtrerr);
LinkNode node;
int count = 0;
for (node = firstnode(vars); node; incnode(node))
{
name = (char *)getdata(node);
if (!args || !(str = (char *) ugetnode(args)))
{
if (count) {
str = "";
last = 1;
} else
break;
}
if (isset(XTRACE)) {
printprompt4();
fprintf(xtrerr, "%s=%s\n", name, str);
fflush(xtrerr);
}
setsparam(name, ztrdup(str));
count++;
}
setsparam(name, ztrdup(str));
if (!count)
break;
}
state->pc = loop;
execlist(state, 1, do_exec && args && empty(args));

View File

@ -878,7 +878,7 @@ static void
par_for(int *complex)
{
int oecused = ecused, csh = (tok == FOREACH), p, sel = (tok == SELECT);
int type;
int type, ona = noaliases;
p = ecadd(0);
@ -903,19 +903,32 @@ par_for(int *complex)
yylex();
type = WC_FOR_COND;
} else {
int posix_in;
int np, n, posix_in;
infor = 0;
if (tok != STRING || !isident(tokstr))
YYERRORV(oecused);
ecstr(tokstr);
np = ecadd(0);
n = 0;
incmdpos = 1;
yylex();
noaliases = 1;
for (;;) {
n++;
ecstr(tokstr);
yylex();
if (tok != STRING || !strcmp(tokstr, "in") || sel)
break;
if (!isident(tokstr))
{
noaliases = ona;
YYERRORV(oecused);
}
}
noaliases = ona;
ecbuf[np] = n;
posix_in = isnewlin;
while (isnewlin)
yylex();
if (tok == STRING && !strcmp(tokstr, "in")) {
int np, n;
yylex();
if (tok == STRING && !strcmp(tokstr, "in")) {
incmdpos = 0;
yylex();
np = ecadd(0);
@ -925,8 +938,6 @@ par_for(int *complex)
ecbuf[np] = n;
type = (sel ? WC_SELECT_LIST : WC_FOR_LIST);
} else if (!posix_in && tok == INPAR) {
int np, n;
incmdpos = 0;
yylex();
np = ecadd(0);

View File

@ -415,7 +415,7 @@ gettext2(Estate state)
taddstr(ecgetstr(state, EC_NODUP, NULL));
taddstr(")) do");
} else {
taddstr(ecgetstr(state, EC_NODUP, NULL));
taddlist(state, *state->pc++);
if (WC_FOR_TYPE(code) == WC_FOR_LIST) {
taddstr(" in ");
taddlist(state, *state->pc++);