mirror of
git://git.code.sf.net/p/zsh/code
synced 2024-09-22 03:40:47 +02:00
15030: multi-parameter `for' loops
This commit is contained in:
parent
bbd2a98f41
commit
1897a361bf
@ -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
|
||||
|
@ -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(}))(
|
||||
|
67
Src/loop.c
67
Src/loop.c
@ -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));
|
||||
|
31
Src/parse.c
31
Src/parse.c
@ -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);
|
||||
|
@ -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++);
|
||||
|
Loading…
Reference in New Issue
Block a user