From b4ce09f88da8326b784735d6677da5909f34da6a Mon Sep 17 00:00:00 2001 From: Bart Schaefer Date: Tue, 31 May 2011 16:01:38 +0000 Subject: 29410: skip autoload persistence test when zsh/example is not available. --- Test/V01zmodload.ztst | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Test') diff --git a/Test/V01zmodload.ztst b/Test/V01zmodload.ztst index d74b0ef18..ea908e952 100644 --- a/Test/V01zmodload.ztst +++ b/Test/V01zmodload.ztst @@ -125,8 +125,10 @@ fi 0d:Autoload a module via a builtin + if [[ $mods[(r)zsh/example] == zsh/example ]]; then zmodload -u zsh/example builtin example + fi 0d:Autoloads are persistent (zmodload -u zsh/parameter -- cgit v1.2.3 From 16324d2ff347e96e43dd95780ff014d2183faf8d Mon Sep 17 00:00:00 2001 From: Mikael Magnusson Date: Fri, 3 Jun 2011 20:55:40 +0000 Subject: 29422: fix g:: test failing in some locales --- ChangeLog | 5 ++++- Test/D04parameter.ztst | 21 +++++++-------------- 2 files changed, 11 insertions(+), 15 deletions(-) (limited to 'Test') diff --git a/ChangeLog b/ChangeLog index 332bcdb20..3377ae3ba 100644 --- a/ChangeLog +++ b/ChangeLog @@ -6,6 +6,9 @@ * 29448: Completion/Unix/Command/_initctl: complete symlinks to files too. + * 29422: Test/D04parameter.ztst: Fix test for g:: to not depend + on the current locale. + 2011-06-03 Peter Stephenson * 29413: Doc/Zsh/builtins.yo, Src/builtin.c, Src/hist.c: print @@ -14939,5 +14942,5 @@ ***************************************************** * This is used by the shell to define $ZSH_PATCHLEVEL -* $Revision: 1.5358 $ +* $Revision: 1.5359 $ ***************************************************** diff --git a/Test/D04parameter.ztst b/Test/D04parameter.ztst index 6379c8cd0..378505e12 100644 --- a/Test/D04parameter.ztst +++ b/Test/D04parameter.ztst @@ -300,23 +300,16 @@ foo='\u65\123' print -r ${(g:o:)foo} - foo='\u65\0123' + foo='\u65\0123^X\C-x' print -r ${(g::)foo} - foo='\u65^X' - print -r ${(V)${(g:c:)foo}} - foo='\u65\C-x\M-a' - print -r ${(V)${(g:e:)foo}} - foo='\u65\123\C-x' - print -r ${(V)${(g:eo:)foo}} - foo=('\u65' '\0123' '^X\M-a') - print -r ${(V)${(g:e:)foo}} + foo='^X' + bar='\C-\130' + [[ ${(g:c:)foo} == ${(g:oe:)bar} ]] + echo $? 0:${(g)...} >eS ->eS ->e^X ->e^X\M-a ->eS^X ->e S ^X\M-a +>eS^X\C-x +>0 foo='I'\''m nearly out of my mind with tedium' bar=foo -- cgit v1.2.3 From 22af58bf2b5b695cdbfaf4b7cdf82bb09136860b Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Fri, 3 Jun 2011 22:03:43 +0000 Subject: 29451: ${##stuff} removes stuff from the head of $# --- ChangeLog | 5 ++++- Src/subst.c | 11 ++++++++++- Test/D04parameter.ztst | 10 +++++++++- 3 files changed, 23 insertions(+), 3 deletions(-) (limited to 'Test') diff --git a/ChangeLog b/ChangeLog index 3377ae3ba..5a727fd4e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -11,6 +11,9 @@ 2011-06-03 Peter Stephenson + * 29451: Src/subst.c, Test/D04parameter.ztst: ${##stuff} + removes stuff from the head of $#. + * 29413: Doc/Zsh/builtins.yo, Src/builtin.c, Src/hist.c: print -S takes a single argument, applies lexical history word splitting, and puts it on the history. @@ -14942,5 +14945,5 @@ ***************************************************** * This is used by the shell to define $ZSH_PATCHLEVEL -* $Revision: 1.5359 $ +* $Revision: 1.5360 $ ***************************************************** diff --git a/Src/subst.c b/Src/subst.c index f9c48404b..314489e49 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -2080,7 +2080,16 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub) || (cc = s[1]) == '*' || cc == Star || cc == '@' || cc == '?' || cc == Quest || cc == '$' || cc == String || cc == Qstring - || cc == '#' || cc == Pound + /* + * Me And My Squiggle: + * ${##} is the length of $#, but ${##foo} + * is $# with a "foo" removed from the start. + * If someone had defined the *@!@! language + * properly in the first place we wouldn't + * have this nonsense. + */ + || ((cc == '#' || cc == Pound) && + s[2] == Outbrace) || cc == '-' || (cc == ':' && s[2] == '-') || (isstring(cc) && (s[2] == Inbrace || s[2] == Inpar)))) { getlen = 1 + whichlen, s++; diff --git a/Test/D04parameter.ztst b/Test/D04parameter.ztst index 378505e12..8f95420dd 100644 --- a/Test/D04parameter.ztst +++ b/Test/D04parameter.ztst @@ -179,9 +179,17 @@ print ${##} set 1 2 3 4 5 6 7 8 9 10 print ${##} -0:${##} is length of $# + print ${##""} + print ${##1} + print ${##2} + print ${###<->} # oh, for pete's sake... +0:${##} is length of $#, and other tales of hash horror >1 >2 +>10 +>0 +>10 +> array=(once bitten twice shy) print IF${array}THEN -- cgit v1.2.3 From 6062529d3fc7c7d29c63d0726d2449d4b56f33ac Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Sun, 19 Jun 2011 20:12:00 +0000 Subject: 29492: add argument handling to anonymous functions --- ChangeLog | 5 +++- Doc/Zsh/func.yo | 14 +++++++---- Src/exec.c | 65 ++++++++++++++++++++++++++++++---------------------- Src/parse.c | 30 ++++++++++++++++++++++-- Src/text.c | 30 +++++++++++++++++++++--- Test/C04funcdef.ztst | 29 ++++++++++++++++++++++- 6 files changed, 133 insertions(+), 40 deletions(-) (limited to 'Test') diff --git a/ChangeLog b/ChangeLog index 446bff14b..8eca2d9cf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2011-06-19 Peter Stephenson + * 29492: Doc/Zsh/func.yo, Src/exec.c, Src/parse.c, Src/text.c, + Test/C04funcdef.ztst: add argument handling to anonymous functions. + * unposted: Src/Zle/zle_refresh.c: remove additional loop noticed by Mikael. @@ -15019,5 +15022,5 @@ ***************************************************** * This is used by the shell to define $ZSH_PATCHLEVEL -* $Revision: 1.5375 $ +* $Revision: 1.5376 $ ***************************************************** diff --git a/Doc/Zsh/func.yo b/Doc/Zsh/func.yo index 28bc6329a..89b956cb4 100644 --- a/Doc/Zsh/func.yo +++ b/Doc/Zsh/func.yo @@ -158,9 +158,13 @@ If no name is given for a function, it is `anonymous' and is handled specially. Either form of function definition may be used: a `tt(())' with no preceding name, or a `tt(function)' with an immediately following open brace. The function is executed immediately at the point of definition and -is not stored for future use. The function name is set to `tt((anon))' and -the parameter list passed to the function is empty. Note that this means +is not stored for future use. The function name is set to `tt((anon))'. + +Arguments to the function may be specified as words following the +closing brace defining the function, hence if there are none no +arguments (other than tt($0)) are set. Note that this means the argument list of any enclosing script or function is hidden. + Redirections may be applied to the anonymous function in the same manner as to a current-shell structure enclosed in braces. The main use of anonymous functions is to provide a scope for local variables. This is particularly @@ -172,13 +176,13 @@ For example, example(variable=outside function { local variable=inside - print "I am $variable" -} + print "I am $variable with arguments $*" +} this and that print "I am $variable") outputs the following: -example(I am inside +example(I am inside with arguments this and that I am outside) Note that function definitions with arguments that expand to nothing, diff --git a/Src/exec.c b/Src/exec.c index 2558185c8..87a167ba6 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -50,20 +50,20 @@ int noerrexit; * noerrs = 1: suppress error messages * noerrs = 2: don't set errflag on parse error, either */ - + /**/ mod_export int noerrs; - + /* do not save history on exec and exit */ /**/ int nohistsave; - + /* error/break flag */ - + /**/ mod_export int errflag; - + /* * State of trap return value. Value is from enum trap_state. */ @@ -88,23 +88,23 @@ int trap_state; * - non-negative in a trap once it was triggered. It should remain * non-negative until restored after execution of the trap. */ - + /**/ int trap_return; - + /* != 0 if this is a subshell */ - + /**/ int subsh; - + /* != 0 if we have a return pending */ - + /**/ mod_export int retflag; /**/ long lastval2; - + /* The table of file descriptors. A table element is zero if the * * corresponding fd is not used by the shell. It is greater than * * 1 if the fd is used by a <(...) or >(...) substitution and 1 if * @@ -148,12 +148,12 @@ int fdtable_flocks; mod_export int zleactive; /* pid of process undergoing 'process substitution' */ - + /**/ pid_t cmdoutpid; - + /* exit status of process undergoing 'process substitution' */ - + /**/ int cmdoutval; @@ -166,7 +166,7 @@ int cmdoutval; /**/ int use_cmdoutval; -/* The context in which a shell function is called, see SFC_* in zsh.h. */ +/* The context in which a shell function is called, see SFC_* in zsh.h. */ /**/ mod_export int sfcontext; @@ -239,7 +239,7 @@ parse_string(char *s, int reset_lineno) /**/ mod_export struct rlimit current_limits[RLIM_NLIMITS], limits[RLIM_NLIMITS]; - + /**/ mod_export int zsetlimit(int limnum, char *nam) @@ -340,7 +340,7 @@ zfork(struct timeval *tv) * * (when waiting for the grep, ignoring execpline2 for now). At this time, * zsh has built two job-table entries for it: one for the cat and one for - * the grep. If the user hits ^Z at this point (and jobbing is used), the + * the grep. If the user hits ^Z at this point (and jobbing is used), the * shell is notified that the grep was suspended. The list_pipe flag is * used to tell the execpline where it was waiting that it was in a pipeline * with a shell construct at the end (which may also be a shell function or @@ -351,7 +351,7 @@ zfork(struct timeval *tv) * shell (its pid and the text for it) in the job entry of the cat. The pid * is passed down in the list_pipe_pid variable. * But there is a problem: the suspended grep is a child of the parent shell - * and can't be adopted by the sub-shell. So the parent shell also has to + * and can't be adopted by the sub-shell. So the parent shell also has to * keep the information about this process (more precisely: this pipeline) * by keeping the job table entry it created for it. The fact that there * are two jobs which have to be treated together is remembered by setting @@ -528,10 +528,10 @@ isgooderr(int e, char *dir) { /* * Maybe the directory was unreadable, or maybe it wasn't - * even a directory. + * even a directory. */ return ((e != EACCES || !access(dir, X_OK)) && - e != ENOENT && e != ENOTDIR); + e != ENOENT && e != ENOTDIR); } /* @@ -639,7 +639,7 @@ execute(LinkList args, int flags, int defpath) break; } - /* for command -p, search the default path */ + /* for command -p, search the default path */ if (defpath) { char *s, pbuf[PATH_MAX]; char *dptr, *pe, *ps = DEFAULT_PATH; @@ -676,7 +676,7 @@ execute(LinkList args, int flags, int defpath) eno = ee; } else { - + if ((cn = (Cmdnam) cmdnamtab->getnode(cmdnamtab, arg0))) { char nn[PATH_MAX], *dptr; @@ -1312,9 +1312,9 @@ sublist_done: donetrap = 1; } if (lastval) { - int errreturn = isset(ERRRETURN) && + int errreturn = isset(ERRRETURN) && (isset(INTERACTIVE) || locallevel || sourcelevel); - int errexit = isset(ERREXIT) || + int errexit = isset(ERREXIT) || (isset(ERRRETURN) && !errreturn); if (errexit) { if (sigtrapped[SIGEXIT]) @@ -1536,7 +1536,7 @@ execpline(Estate state, wordcode slcode, int how, int last1) else if (pid) { char dummy; - lpforked = + lpforked = (killpg(jobtab[list_pipe_job].gleader, 0) == -1 ? 2 : 1); list_pipe_pid = pid; list_pipe_start = bgtime; @@ -3112,7 +3112,7 @@ execcmd(Estate state, int input, int output, int how, int last1) ESUB_PGRP | ESUB_FAKE; if (type != WC_SUBSH) flags |= ESUB_KEEPTRAP; - if ((do_exec || (type >= WC_CURSH && last1 == 1)) + if ((do_exec || (type >= WC_CURSH && last1 == 1)) && !forked) flags |= ESUB_REVERTPGRP; entersubsh(flags); @@ -4184,10 +4184,19 @@ execfuncdef(Estate state, UNUSED(int do_exec)) * Anonymous function, execute immediately. * Function name is "(anon)", parameter list is empty. */ - LinkList args = newlinklist(); + LinkList args; + + state->pc = end; + end += *state->pc++; + args = ecgetlist(state, *state->pc++, EC_DUPTOK, &htok); + + if (htok && args) + execsubst(args); + if (!args) + args = newlinklist(); shf->node.nam = "(anon)"; - addlinknode(args, shf->node.nam); + pushnode(args, shf->node.nam); execshfunc(shf, args); ret = lastval; diff --git a/Src/parse.c b/Src/parse.c index 4720dc3cf..5b6f09949 100644 --- a/Src/parse.c +++ b/Src/parse.c @@ -1480,12 +1480,25 @@ par_funcdef(void) ecbuf[p + num + 4] = ecnpats; ecbuf[p + 1] = num; - lineno += oldlineno; ecnpats = onp; ecssub = oecssub; ecnfunc++; ecbuf[p] = WCB_FUNCDEF(ecused - 1 - p); + + if (num == 0) { + /* Unnamed function */ + int parg = ecadd(0); + ecadd(0); + while (tok == STRING) { + ecstr(tokstr); + num++; + zshlex(); + } + ecbuf[parg] = ecused - parg; /*?*/ + ecbuf[parg+1] = num; + } + lineno += oldlineno; } /* @@ -1730,13 +1743,26 @@ par_simple(int *complex, int nr) ecbuf[p + argc + 3] = ecsoffs - so; ecbuf[p + argc + 4] = ecnpats; - lineno += oldlineno; ecnpats = onp; ecssub = oecssub; ecnfunc++; ecbuf[p] = WCB_FUNCDEF(ecused - 1 - p); + if (argc == 0) { + /* Unnamed function */ + int parg = ecadd(0); + ecadd(0); + while (tok == STRING) { + ecstr(tokstr); + argc++; + zshlex(); + } + ecbuf[parg] = ecused - parg; /*?*/ + ecbuf[parg+1] = argc; + } + lineno += oldlineno; + isfunc = 1; isnull = 0; break; diff --git a/Src/text.c b/Src/text.c index 669037a2d..f55553ed0 100644 --- a/Src/text.c +++ b/Src/text.c @@ -253,6 +253,7 @@ struct tstack { struct { char *strs; Wordcode end; + int nargs; } _funcdef; struct { Wordcode end; @@ -456,19 +457,31 @@ gettext2(Estate state) if (!s) { Wordcode p = state->pc; Wordcode end = p + WC_FUNCDEF_SKIP(code); + int nargs = *state->pc++; - taddlist(state, *state->pc++); + taddlist(state, nargs); + if (nargs) + taddstr(" "); if (tjob) { - taddstr(" () { ... }"); + taddstr("() { ... }"); state->pc = end; + if (!nargs) { + /* + * Unnamed fucntion. + * We're not going to pull any arguments off + * later, so skip them now... + */ + state->pc += *end; + } stack = 1; } else { - taddstr(" () {"); + taddstr("() {"); tindent++; taddnl(1); n = tpush(code, 1); n->u._funcdef.strs = state->strs; n->u._funcdef.end = end; + n->u._funcdef.nargs = nargs; state->strs += *state->pc; state->pc += 3; } @@ -478,6 +491,17 @@ gettext2(Estate state) dec_tindent(); taddnl(0); taddstr("}"); + if (s->u._funcdef.nargs == 0) { + /* Unnamed function with post-arguments */ + int nargs; + s->u._funcdef.end += *state->pc++; + nargs = *state->pc++; + if (nargs) { + taddstr(" "); + taddlist(state, nargs); + } + state->pc = s->u._funcdef.end; + } stack = 1; } break; diff --git a/Test/C04funcdef.ztst b/Test/C04funcdef.ztst index f71e5ce77..0cc5e5a2f 100644 --- a/Test/C04funcdef.ztst +++ b/Test/C04funcdef.ztst @@ -26,7 +26,7 @@ print regress expansion of function names } f$$ -0:Regression test: `function f$$ () { ... }' +0:Regression test: 'function f$$ () { ... }' >regress expansion of function names function foo () print bar @@ -109,6 +109,8 @@ >really useful >args +# ' deconfuse emacs + command_not_found_handler() { print "Your command:" >&2 print "$1" >&2 @@ -201,6 +203,31 @@ >Da de da >Do be do + () { print This has arguments $*; } of all sorts; print After the function + function { print More stuff $*; } and why not; print Yet more +0:Anonymous function with arguments +>This has arguments of all sorts +>After the function +>More stuff and why not +>Yet more + + fn() { + (){ print Anonymous function 1 $*; } with args + function { print Anonymous function 2 $*; } with more args + print Following bit + } + functions fn +0:Text representation of anonymous function with arguments +>fn () { +> () { +> print Anonymous function 1 $* +> } with args +> () { +> print Anonymous function 2 $* +> } with more args +> print Following bit +>} + %clean rm -f file.in file.out -- cgit v1.2.3 From ad29258c8c2785796d3149c6c230e55d9debc82b Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Fri, 1 Jul 2011 15:23:01 +0000 Subject: 29530: ${...?...} shouldn't cause an error with NO_EXEC option --- ChangeLog | 7 ++++++- Src/subst.c | 28 +++++++++++++++------------- Test/E01options.ztst | 4 ++++ 3 files changed, 25 insertions(+), 14 deletions(-) (limited to 'Test') diff --git a/ChangeLog b/ChangeLog index e4016aa3a..c2f1fd8a8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-07-01 Peter Stephenson + + * 29530: Src/subst.c, Test/E01options.ztst: ${..?..} shouldn't + cause an error with NO_EXEC option. + 2011-07-01 Frank Terbeck * 29518: Completion/Unix/Command/_git: Fall back to file @@ -15077,5 +15082,5 @@ ***************************************************** * This is used by the shell to define $ZSH_PATCHLEVEL -* $Revision: 1.5389 $ +* $Revision: 1.5390 $ ***************************************************** diff --git a/Src/subst.c b/Src/subst.c index e8a181129..1b0097001 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -2715,19 +2715,21 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub) case '?': case Quest: if (vunset) { - *idend = '\0'; - zerr("%s: %s", idbeg, *s ? s : "parameter not set"); - if (!interact) { - if (mypid == getpid()) { - /* - * paranoia: don't check for jobs, but there shouldn't - * be any if not interactive. - */ - stopmsg = 1; - zexit(1, 0); - } else - _exit(1); - } + if (isset(EXECOPT)) { + *idend = '\0'; + zerr("%s: %s", idbeg, *s ? s : "parameter not set"); + if (!interact) { + if (mypid == getpid()) { + /* + * paranoia: don't check for jobs, but there + * shouldn't be any if not interactive. + */ + stopmsg = 1; + zexit(1, 0); + } else + _exit(1); + } + } return NULL; } break; diff --git a/Test/E01options.ztst b/Test/E01options.ztst index 4b53840c6..1bbfdbda1 100644 --- a/Test/E01options.ztst +++ b/Test/E01options.ztst @@ -353,6 +353,10 @@ echo *NonExistentFile*) 0:NO_EXEC option should not do globbing + (setopt noexec + echo ${unset_var?Not an error}) +0:NO_EXEC should not test for unset variables + setopt NO_eval_lineno eval 'print $LINENO' setopt eval_lineno -- cgit v1.2.3 From b12242cb3f80991031a6f17a58296312f1bfa8ef Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Wed, 27 Jul 2011 19:14:16 +0000 Subject: 29561: missed file --- ChangeLog | 7 ++++++- Test/A04redirect.ztst | 3 +++ 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'Test') diff --git a/ChangeLog b/ChangeLog index 84a8cb7d3..4e2eb33b2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-07-27 Peter Stephenson + + * 29561: Test/A04redirect.ztst: this bit didn't get committed, + somehow. + 2011-07-27 Mikael Magnusson * 29618: Completion/Linux/Command/_ethtool, @@ -15165,5 +15170,5 @@ ***************************************************** * This is used by the shell to define $ZSH_PATCHLEVEL -* $Revision: 1.5408 $ +* $Revision: 1.5409 $ ***************************************************** diff --git a/Test/A04redirect.ztst b/Test/A04redirect.ztst index 4d96d8bb9..c2321a571 100644 --- a/Test/A04redirect.ztst +++ b/Test/A04redirect.ztst @@ -155,9 +155,12 @@ (exec 3<&- read foo <&-) 1:'<&-' redirection +?(eval):1: failed to close file descriptor 3: bad file descriptor +?(eval):2: failed to close file descriptor 0: bad file descriptor print foo >&- 0:'>&-' redirection +?(eval):1: failed to close file descriptor 1: bad file descriptor fn() { local foo; read foo; print $foo; } coproc fn -- cgit v1.2.3 From 7d1480af54e95e5a2165e8bb69937a6b0a1dc50a Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Thu, 28 Jul 2011 09:20:02 +0000 Subject: 29626: arguments to anonymous functions shouldn't be parsed as command words --- ChangeLog | 5 ++++- Src/params.c | 1 + Src/parse.c | 2 ++ Test/C04funcdef.ztst | 17 +++++++++++++++++ 4 files changed, 24 insertions(+), 1 deletion(-) (limited to 'Test') diff --git a/ChangeLog b/ChangeLog index 4edc62b61..57b269b31 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2011-07-28 Peter Stephenson + * 29626: Src/parse.c, Test/C04funcdef.ztst: arguments to + anonymous functions shouldn't be parsed as command words. + * 29602 and subsequent changes: Doc/Zsh/expn.yo: clarify meaning of filename extension in :r and :e modifiers (which were slightly inconsistent). @@ -15176,5 +15179,5 @@ ***************************************************** * This is used by the shell to define $ZSH_PATCHLEVEL -* $Revision: 1.5410 $ +* $Revision: 1.5411 $ ***************************************************** diff --git a/Src/params.c b/Src/params.c index 8a56766f8..fd0872130 100644 --- a/Src/params.c +++ b/Src/params.c @@ -4193,6 +4193,7 @@ arrfixenv(char *s, char **t) int zputenv(char *str) { + DPUTS(!str, "Attempt to put null string into environment."); #ifdef USE_SET_UNSET_ENV /* * If we are using unsetenv() to remove values from the diff --git a/Src/parse.c b/Src/parse.c index 5b6f09949..5b8f0af48 100644 --- a/Src/parse.c +++ b/Src/parse.c @@ -1465,6 +1465,7 @@ par_funcdef(void) ecssub = oecssub; YYERRORV(oecused); } + incmdpos = 0; zshlex(); } else if (unset(SHORTLOOPS)) { lineno += oldlineno; @@ -1720,6 +1721,7 @@ par_simple(int *complex, int nr) ecssub = oecssub; YYERROR(oecused); } + incmdpos = 0; zshlex(); } else { int ll, sl, c = 0; diff --git a/Test/C04funcdef.ztst b/Test/C04funcdef.ztst index 0cc5e5a2f..742d2d0a7 100644 --- a/Test/C04funcdef.ztst +++ b/Test/C04funcdef.ztst @@ -1,3 +1,8 @@ +%prep + + mkdir funcdef.tmp + cd funcdef.tmp + %test fn1() { return 1; } @@ -228,6 +233,18 @@ > print Following bit >} + touch yes no + () { echo $1 } (y|z)* + (echo here) + () { echo $* } some (y|z)* + () { echo empty };(echo here) +0:Anonymous function arguments and command arguments +>yes +>here +>some yes +>empty +>here + %clean rm -f file.in file.out -- cgit v1.2.3 From d48faef8cdff3c7c63c0a9164443e3d337aa1ec1 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Wed, 3 Aug 2011 18:45:17 +0000 Subject: 29633: more care with anonymous and other functions --- ChangeLog | 8 +++++++- Doc/Zsh/func.yo | 11 +++++++++-- Src/parse.c | 10 ++++++++-- Test/C04funcdef.ztst | 6 ++++++ 4 files changed, 30 insertions(+), 5 deletions(-) (limited to 'Test') diff --git a/ChangeLog b/ChangeLog index 3c0265440..c6209fca0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-08-03 Peter Stephenson + + * 29633: Doc/Zsh/func.yo, Src/parse.c, Test/C04funcdef.ztst: be + more careful that anonymous function syntax doesn't mess up + working syntax with other functions. + 2011-08-03 Peter Stephenson * 29635: Completion/Base/Widget/_complete_debug: Improve file @@ -15189,5 +15195,5 @@ ***************************************************** * This is used by the shell to define $ZSH_PATCHLEVEL -* $Revision: 1.5413 $ +* $Revision: 1.5414 $ ***************************************************** diff --git a/Doc/Zsh/func.yo b/Doc/Zsh/func.yo index 89b956cb4..7c391f80d 100644 --- a/Doc/Zsh/func.yo +++ b/Doc/Zsh/func.yo @@ -162,8 +162,15 @@ is not stored for future use. The function name is set to `tt((anon))'. Arguments to the function may be specified as words following the closing brace defining the function, hence if there are none no -arguments (other than tt($0)) are set. Note that this means -the argument list of any enclosing script or function is hidden. +arguments (other than tt($0)) are set. This is a difference from the +way other functions are parsed: normal function definitions may be +followed by certain keywords such as `tt(else)' or `tt(fi)', which will +be treated as arguments to anonymous functions, so that a newline or +semicolon is needed to force keyword interpretation. + +Note also that the argument list of any enclosing script or function is +hidden (as would be the case for any other function called at this +point). Redirections may be applied to the anonymous function in the same manner as to a current-shell structure enclosed in braces. The main use of anonymous diff --git a/Src/parse.c b/Src/parse.c index 5b8f0af48..e4d038b6e 100644 --- a/Src/parse.c +++ b/Src/parse.c @@ -1465,7 +1465,10 @@ par_funcdef(void) ecssub = oecssub; YYERRORV(oecused); } - incmdpos = 0; + if (num == 0) { + /* Anonymous function, possibly with arguments */ + incmdpos = 0; + } zshlex(); } else if (unset(SHORTLOOPS)) { lineno += oldlineno; @@ -1721,7 +1724,10 @@ par_simple(int *complex, int nr) ecssub = oecssub; YYERROR(oecused); } - incmdpos = 0; + if (argc == 0) { + /* Anonymous function, possibly with arguments */ + incmdpos = 0; + } zshlex(); } else { int ll, sl, c = 0; diff --git a/Test/C04funcdef.ztst b/Test/C04funcdef.ztst index 742d2d0a7..90f01e397 100644 --- a/Test/C04funcdef.ztst +++ b/Test/C04funcdef.ztst @@ -245,6 +245,12 @@ >empty >here + if true; then f() { echo foo1; } else f() { echo bar1; } fi; f + if false; then f() { echo foo2; } else f() { echo bar2; } fi; f +0:Compatibility with other shells when not anonymous functions +>foo1 +>bar2 + %clean rm -f file.in file.out -- cgit v1.2.3 From 548c4562fe5889ae8149c082c36ac9461babf0ec Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Thu, 11 Aug 2011 19:32:50 +0000 Subject: fix tests using zsh/datetime that I broke --- ChangeLog | 5 ++++- Src/params.c | 18 +++++++++++++++--- Test/V04features.ztst | 10 ++++++++++ 3 files changed, 29 insertions(+), 4 deletions(-) (limited to 'Test') diff --git a/ChangeLog b/ChangeLog index 822befc38..9632ab2b9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2011-08-11 Peter Stephenson + * Src/params.c: unposted: Src/params.c, Test/V04features.ztst: + fix some tests I broke. + * Src/subst.c: 29674: Src/Modules/datetime.c, Doc/Zsh/mod_datetime.yo: add $epochtime array. @@ -15229,5 +15232,5 @@ ***************************************************** * This is used by the shell to define $ZSH_PATCHLEVEL -* $Revision: 1.5419 $ +* $Revision: 1.5420 $ ***************************************************** diff --git a/Src/params.c b/Src/params.c index fd0872130..446cccc7e 100644 --- a/Src/params.c +++ b/Src/params.c @@ -3046,9 +3046,21 @@ mod_export void stdunsetfn(Param pm, UNUSED(int exp)) { switch (PM_TYPE(pm->node.flags)) { - case PM_SCALAR: pm->gsu.s->setfn(pm, NULL); break; - case PM_ARRAY: pm->gsu.a->setfn(pm, NULL); break; - case PM_HASHED: pm->gsu.h->setfn(pm, NULL); break; + case PM_SCALAR: + if (pm->gsu.s->setfn) + pm->gsu.s->setfn(pm, NULL); + break; + + case PM_ARRAY: + if (pm->gsu.a->setfn) + pm->gsu.a->setfn(pm, NULL); + break; + + case PM_HASHED: + if (pm->gsu.h->setfn) + pm->gsu.h->setfn(pm, NULL); + break; + default: if (!(pm->node.flags & PM_SPECIAL)) pm->u.str = NULL; diff --git a/Test/V04features.ztst b/Test/V04features.ztst index 240336611..2790456e2 100644 --- a/Test/V04features.ztst +++ b/Test/V04features.ztst @@ -17,18 +17,24 @@ 0:Loading modules with no features >-b:strftime >-p:EPOCHSECONDS +>-p:EPOCHREALTIME +>-p:epochtime zmodload -F zsh/datetime b:strftime zmodload -lF zsh/datetime 0:Enabling features >+b:strftime >-p:EPOCHSECONDS +>-p:EPOCHREALTIME +>-p:epochtime zmodload -F zsh/datetime +p:EPOCHSECONDS -b:strftime zmodload -lF zsh/datetime 0:Disabling features >-b:strftime >+p:EPOCHSECONDS +>-p:EPOCHREALTIME +>-p:epochtime zmodload -Fe zsh/datetime p:EPOCHSECONDS b:strftime 0:Testing existing features @@ -109,6 +115,8 @@ 0:Feature state with loading after error enabling >+b:strftime >-p:EPOCHSECONDS +>+p:EPOCHREALTIME +>+p:epochtime zmodload -F zsh/datetime p:EPOCHSECONDS zmodload -Fe zsh/datetime +p:EPOCHSECONDS @@ -159,3 +167,5 @@ 0:zmodload with no -F enables all features >+b:strftime >+p:EPOCHSECONDS +>+p:EPOCHREALTIME +>+p:epochtime -- cgit v1.2.3 From 815e52cdbf0a62bf795d5af8e7089aaca5709806 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Wed, 17 Aug 2011 19:00:08 +0000 Subject: users/16253, users/16255: a nulstring should be split like an empty string --- ChangeLog | 7 +++++-- Src/utils.c | 4 ++++ Test/D04parameter.ztst | 5 +++++ 3 files changed, 14 insertions(+), 2 deletions(-) (limited to 'Test') diff --git a/ChangeLog b/ChangeLog index bd9d9229b..76eb0d1dc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,9 @@ 2011-08-17 Peter Stephenson - * Anthony R Fletcher: users/16260: + * users/16253, users/16255: Src/utils.c, Test/D04parameter.ztst: + A nulstring should be split like an empty string. + + * Anthony R Fletcher: users/16260: Completion/Unix/Command/_systemctl: new completion. 2011-08-17 Nikolai Weibull @@ -15294,5 +15297,5 @@ ***************************************************** * This is used by the shell to define $ZSH_PATCHLEVEL -* $Revision: 1.5437 $ +* $Revision: 1.5438 $ ***************************************************** diff --git a/Src/utils.c b/Src/utils.c index 439b43aa9..c8d021c66 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -3176,6 +3176,10 @@ sepsplit(char *s, char *sep, int allownull, int heap) int n, sl; char *t, *tt, **r, **p; + /* Null string? Treat as empty string. */ + if (s[0] == Nularg && !s[1]) + s++; + if (!sep) return spacesplit(s, allownull, heap, 0); diff --git a/Test/D04parameter.ztst b/Test/D04parameter.ztst index 8f95420dd..71c79687f 100644 --- a/Test/D04parameter.ztst +++ b/Test/D04parameter.ztst @@ -1453,3 +1453,8 @@ print ${foo:5:-6} 1:Regression test for total length < 0 in array ?(eval):2: substring expression: 3 < 5 + + foo=(${(0)"$(print -n)"}) + print ${#foo} +0:Nularg removed from split empty string +>0 -- cgit v1.2.3 From 85b00bb0f7c60b9f4da5261633221cc200a0ab7f Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Wed, 17 Aug 2011 20:26:05 +0000 Subject: 29703: crash when failing to parse process substitutions --- ChangeLog | 4 +++- Src/exec.c | 10 +++++++++- Src/subst.c | 2 ++ Test/D03procsubst.ztst | 4 ++++ 4 files changed, 18 insertions(+), 2 deletions(-) (limited to 'Test') diff --git a/ChangeLog b/ChangeLog index 76eb0d1dc..fa352b0e2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2011-08-17 Peter Stephenson + * 29703: Src/exec.c, Src/subst.c, Test/D03procsubst.ztst: + * users/16253, users/16255: Src/utils.c, Test/D04parameter.ztst: A nulstring should be split like an empty string. @@ -15297,5 +15299,5 @@ ***************************************************** * This is used by the shell to define $ZSH_PATCHLEVEL -* $Revision: 1.5438 $ +* $Revision: 1.5439 $ ***************************************************** diff --git a/Src/exec.c b/Src/exec.c index a9164bc64..3c51a3d42 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -3755,7 +3755,15 @@ parsecmd(char *cmd, char **eptr) for (str = cmd + 2; *str && *str != Outpar; str++); if (!*str || cmd[1] != Inpar) { - zerr("oops."); + /* + * This can happen if the expression is being parsed + * inside another construct, e.g. as a value within ${..:..} etc. + * So print a proper error message instead of the not very + * useful but traditional "oops". + */ + char *errstr = dupstrpfx(cmd, 2); + untokenize(errstr); + zerr("unterminated `%s...)'", errstr); return NULL; } *str = '\0'; diff --git a/Src/subst.c b/Src/subst.c index 1b0097001..66e0bbe77 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -162,6 +162,8 @@ stringsubst(LinkList list, LinkNode node, int ssub, int asssub) subst = getproc(str, &rest); /* <(...) or >(...) */ else subst = getoutputfile(str, &rest); /* =(...) */ + if (errflag) + return NULL; if (!subst) subst = ""; diff --git a/Test/D03procsubst.ztst b/Test/D03procsubst.ztst index 37a67630f..602b1da15 100644 --- a/Test/D03procsubst.ztst +++ b/Test/D03procsubst.ztst @@ -84,3 +84,7 @@ ) 0:=(...) preceded by other stuff has no special effect >everything,=(here is left),alone + + print something=${:-=(echo 'C,D),(F,G)'} +1: Graceful handling of bad substitution in enclosed context +?(eval):1: unterminated `=(...)' -- cgit v1.2.3 From af071465b1ef324f35741c681529f39b88a95f51 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Sun, 28 Aug 2011 17:06:27 +0000 Subject: 29731: fix read -AE, test that and read -Ae --- ChangeLog | 5 ++++- Src/builtin.c | 4 ++-- Test/B04read.ztst | 17 +++++++++++++++++ 3 files changed, 23 insertions(+), 3 deletions(-) (limited to 'Test') diff --git a/ChangeLog b/ChangeLog index 58e06d4da..80de37809 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2011-08-28 Peter Stephenson + * 29731: Src/builtin.c, Test/B04read.ztst: fix output from `read + -AE' and test that and `read -Ae'. + * users/16289: Doc/Zsh/expn.yo, Src/exec.c, Src/jobs.c: don't delete temporary files when disowning and document this. @@ -15335,5 +15338,5 @@ ***************************************************** * This is used by the shell to define $ZSH_PATCHLEVEL -* $Revision: 1.5446 $ +* $Revision: 1.5447 $ ***************************************************** diff --git a/Src/builtin.c b/Src/builtin.c index 9b34ef7c0..175607644 100644 --- a/Src/builtin.c +++ b/Src/builtin.c @@ -5549,7 +5549,7 @@ bin_read(char *name, char **args, Options ops, UNUSED(int func)) *bptr = '\0'; #endif /* dispose of word appropriately */ - if (OPT_ISSET(ops,'e') || OPT_ISSET(ops,'E')) { + if (OPT_ISSET(ops,'e')) { zputs(buf, stdout); putchar('\n'); } @@ -5581,7 +5581,7 @@ bin_read(char *name, char **args, Options ops, UNUSED(int func)) : (char **)zalloc((al + 1) * sizeof(char *))); for (pp = p, n = firstnode(readll); n; incnode(n)) { - if (OPT_ISSET(ops,'e') || OPT_ISSET(ops,'E')) { + if (OPT_ISSET(ops,'E')) { zputs((char *) getdata(n), stdout); putchar('\n'); } diff --git a/Test/B04read.ztst b/Test/B04read.ztst index ad427dc0d..25c3d4173 100644 --- a/Test/B04read.ztst +++ b/Test/B04read.ztst @@ -93,3 +93,20 @@ read foo) <<one +>two +>three +>one:two:three + + array=() + read -Ae array <<<'four five six' + print ${(j.:.)array} +0:Behaviour of -A and -e combination +>four +>five +>six +> -- cgit v1.2.3 From 3dba9a8614e15292ef27cf81c202a39a37e4fff7 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Thu, 15 Sep 2011 14:04:51 +0000 Subject: 29776: fix case of double quotes in double-quote-style parsing where end character is something else --- ChangeLog | 6 +++++- Src/lex.c | 2 +- Test/D08cmdsubst.ztst | 8 ++++++++ 3 files changed, 14 insertions(+), 2 deletions(-) (limited to 'Test') diff --git a/ChangeLog b/ChangeLog index e05d71c6d..b52361aa6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2011-09-15 Peter Stephenson + * 29776 (modified as noted): Src/lex.c, Test/D08cmdsubst.ztst: + double quotes are not special in double-quote-style parsing + if the end character is something else. + * 29773: Marco Hinz: Completion/Unix/Type/_perl_modules: complete some missed modules. @@ -15413,5 +15417,5 @@ ***************************************************** * This is used by the shell to define $ZSH_PATCHLEVEL -* $Revision: 1.5466 $ +* $Revision: 1.5467 $ ***************************************************** diff --git a/Src/lex.c b/Src/lex.c index 51aaa76ef..90c4effd9 100644 --- a/Src/lex.c +++ b/Src/lex.c @@ -1567,7 +1567,7 @@ dquote_parse(char endchar, int sub) err = (!brct-- && math); break; case '"': - if (intick || ((endchar == ']' || !endchar) && !bct)) + if (intick || (endchar != '"' && !bct)) break; if (bct) { add(Dnull); diff --git a/Test/D08cmdsubst.ztst b/Test/D08cmdsubst.ztst index 9962c6cad..5661b0aaa 100644 --- a/Test/D08cmdsubst.ztst +++ b/Test/D08cmdsubst.ztst @@ -98,3 +98,11 @@ echo `echo $?` 0:Non-empty command substitution inherits status >1 + + echo $(( ##\" )) + echo $(echo \") + echo $((echo \"); echo OK) +0:Handling of backslash double quote in parenthesised substitutions +>34 +>" +>" OK -- cgit v1.2.3 From 2f3c16d40fe1e8c6aa351224fd50530024c4f5c6 Mon Sep 17 00:00:00 2001 From: Phil Pennock Date: Mon, 24 Oct 2011 11:31:25 +0000 Subject: 29838: metafy/unmetafy strings for PCRE matching (UTF-8 fixes) --- ChangeLog | 10 ++++- Src/Modules/pcre.c | 61 ++++++++++++++++++++++-------- Test/V07pcre.ztst | 106 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 160 insertions(+), 17 deletions(-) create mode 100644 Test/V07pcre.ztst (limited to 'Test') diff --git a/ChangeLog b/ChangeLog index 934fb881f..47fc89954 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2011-10-24 Phil Pennock + + * 29838: Src/Modules/pcre.c: metafy/unmetafy strings, to + correctly handle non-ASCII characters in UTF-8 for regexp + matches. + + * unposted: Test/V07pcre.ztst: some PCRE tests + 2011-10-23 Peter Stephenson * users/16492: MACHINES: OpenIndiana issue. @@ -15484,5 +15492,5 @@ ***************************************************** * This is used by the shell to define $ZSH_PATCHLEVEL -* $Revision: 1.5481 $ +* $Revision: 1.5482 $ ***************************************************** diff --git a/Src/Modules/pcre.c b/Src/Modules/pcre.c index e1a897944..e36013163 100644 --- a/Src/Modules/pcre.c +++ b/Src/Modules/pcre.c @@ -77,6 +77,7 @@ bin_pcre_compile(char *nam, char **args, Options ops, UNUSED(int func)) { int pcre_opts = 0, pcre_errptr; const char *pcre_error; + char *target; if(OPT_ISSET(ops,'a')) pcre_opts |= PCRE_ANCHORED; if(OPT_ISSET(ops,'i')) pcre_opts |= PCRE_CASELESS; @@ -92,8 +93,13 @@ bin_pcre_compile(char *nam, char **args, Options ops, UNUSED(int func)) if (pcre_pattern) pcre_free(pcre_pattern); - pcre_pattern = pcre_compile(*args, pcre_opts, &pcre_error, &pcre_errptr, NULL); + target = ztrdup(*args); + unmetafy(target, NULL); + + pcre_pattern = pcre_compile(target, pcre_opts, &pcre_error, &pcre_errptr, NULL); + free(target); + if (pcre_pattern == NULL) { zwarnnam(nam, "error in regex: %s", pcre_error); @@ -161,7 +167,7 @@ zpcre_get_substrings(char *arg, int *ovec, int ret, char *matchvar, sprintf(offset_all, "%d %d", ovec[0], ovec[1]); setsparam("ZPCRE_OP", ztrdup(offset_all)); } - match_all = ztrdup(captures[0]); + match_all = metafy(captures[0], -1, META_DUP); setsparam(matchvar, match_all); /* * If we're setting match, mbegin, mend we only do @@ -169,7 +175,15 @@ zpcre_get_substrings(char *arg, int *ovec, int ret, char *matchvar, * (c.f. regex.c). */ if (!want_begin_end || nelem) { - matches = zarrdup(&captures[capture_start]); + char **x, **y; + y = &captures[capture_start]; + matches = x = (char **) zalloc(sizeof(char *) * (arrlen(y) + 1)); + do { + if (*y) + *x++ = metafy(*y, -1, META_DUP); + else + *x++ = NULL; + } while (*y++); setaparam(substravar, matches); } @@ -255,6 +269,7 @@ bin_pcre_match(char *nam, char **args, Options ops, UNUSED(int func)) { int ret, capcount, *ovec, ovecsize, c; char *matched_portion = NULL; + char *plaintext = NULL; char *receptacle = NULL; int return_value = 1; /* The subject length and offset start are both int values in pcre_exec */ @@ -278,7 +293,7 @@ bin_pcre_match(char *nam, char **args, Options ops, UNUSED(int func)) } /* For the entire match, 'Return' the offset byte positions instead of the matched string */ if(OPT_ISSET(ops,'b')) want_offset_pair = 1; - + if(!*args) { zwarnnam(nam, "not enough arguments"); } @@ -288,26 +303,28 @@ bin_pcre_match(char *nam, char **args, Options ops, UNUSED(int func)) zwarnnam(nam, "error %d in fullinfo", ret); return 1; } - + ovecsize = (capcount+1)*3; ovec = zalloc(ovecsize*sizeof(int)); - - subject_len = (int)strlen(*args); + + plaintext = ztrdup(*args); + unmetafy(plaintext, NULL); + subject_len = (int)strlen(plaintext); if (offset_start < 0 || offset_start >= subject_len) ret = PCRE_ERROR_NOMATCH; else - ret = pcre_exec(pcre_pattern, pcre_hints, *args, subject_len, offset_start, 0, ovec, ovecsize); + ret = pcre_exec(pcre_pattern, pcre_hints, plaintext, subject_len, offset_start, 0, ovec, ovecsize); if (ret==0) return_value = 0; else if (ret==PCRE_ERROR_NOMATCH) /* no match */; else if (ret>0) { - zpcre_get_substrings(*args, ovec, ret, matched_portion, receptacle, + zpcre_get_substrings(plaintext, ovec, ret, matched_portion, receptacle, want_offset_pair, 0, 0); return_value = 0; } else { - zwarnnam(nam, "error in pcre_exec"); + zwarnnam(nam, "error in pcre_exec [%d]", ret); } if (ovec) @@ -322,7 +339,8 @@ cond_pcre_match(char **a, int id) { pcre *pcre_pat; const char *pcre_err; - char *lhstr, *rhre, *avar=NULL; + char *lhstr, *rhre, *lhstr_plain, *rhre_plain, *avar=NULL; + char *p; int r = 0, pcre_opts = 0, pcre_errptr, capcnt, *ov, ovsize; int return_value = 0; @@ -331,6 +349,10 @@ cond_pcre_match(char **a, int id) lhstr = cond_str(a,0,0); rhre = cond_str(a,1,0); + lhstr_plain = ztrdup(lhstr); + rhre_plain = ztrdup(rhre); + unmetafy(lhstr_plain, NULL); + unmetafy(rhre_plain, NULL); pcre_pat = NULL; ov = NULL; @@ -339,7 +361,7 @@ cond_pcre_match(char **a, int id) switch(id) { case CPCRE_PLAIN: - pcre_pat = pcre_compile(rhre, pcre_opts, &pcre_err, &pcre_errptr, NULL); + pcre_pat = pcre_compile(rhre_plain, pcre_opts, &pcre_err, &pcre_errptr, NULL); if (pcre_pat == NULL) { zwarn("failed to compile regexp /%s/: %s", rhre, pcre_err); break; @@ -347,7 +369,7 @@ cond_pcre_match(char **a, int id) pcre_fullinfo(pcre_pat, NULL, PCRE_INFO_CAPTURECOUNT, &capcnt); ovsize = (capcnt+1)*3; ov = zalloc(ovsize*sizeof(int)); - r = pcre_exec(pcre_pat, NULL, lhstr, strlen(lhstr), 0, 0, ov, ovsize); + r = pcre_exec(pcre_pat, NULL, lhstr_plain, strlen(lhstr_plain), 0, 0, ov, ovsize); /* r < 0 => error; r==0 match but not enough size in ov * r > 0 => (r-1) substrings found; r==1 => no substrings */ @@ -356,13 +378,16 @@ cond_pcre_match(char **a, int id) return_value = 1; break; } - else if (r==PCRE_ERROR_NOMATCH) return 0; /* no match */ + else if (r==PCRE_ERROR_NOMATCH) { + return_value = 0; /* no match */ + break; + } else if (r<0) { - zwarn("pcre_exec() error: %d", r); + zwarn("pcre_exec() error [%d]", r); break; } else if (r>0) { - zpcre_get_substrings(lhstr, ov, r, NULL, avar, 0, + zpcre_get_substrings(lhstr_plain, ov, r, NULL, avar, 0, isset(BASHREMATCH), !isset(BASHREMATCH)); return_value = 1; @@ -371,6 +396,10 @@ cond_pcre_match(char **a, int id) break; } + if (lhstr_plain) + free(lhstr_plain); + if(rhre_plain) + free(rhre_plain); if (pcre_pat) pcre_free(pcre_pat); if (ov) diff --git a/Test/V07pcre.ztst b/Test/V07pcre.ztst new file mode 100644 index 000000000..4dd173557 --- /dev/null +++ b/Test/V07pcre.ztst @@ -0,0 +1,106 @@ +%prep + + zmodload zsh/pcre + setopt rematch_pcre +# Find a UTF-8 locale. + setopt multibyte +# Don't let LC_* override our choice of locale. + unset -m LC_\* + mb_ok= + langs=(en_{US,GB}.{UTF-,utf}8 en.UTF-8 + $(locale -a 2>/dev/null | egrep 'utf8|UTF-8')) + for LANG in $langs; do + if [[ é = ? ]]; then + mb_ok=1 + break; + fi + done + if [[ -z $mb_ok ]]; then + ZTST_unimplemented="no UTF-8 locale or multibyte mode is not implemented" + else + print -u $ZTST_fd Testing PCRE multibyte with locale $LANG + mkdir multibyte.tmp && cd multibyte.tmp + fi + +%test + + [[ 'foo→bar' =~ .([^[:ascii:]]). ]] + print $MATCH + print $match[1] +0:Basic non-ASCII regexp matching +>o→b +>→ + + [[ foo =~ f.+ ]] ; print $? + [[ foo =~ x.+ ]] ; print $? + [[ ! foo =~ f.+ ]] ; print $? + [[ ! foo =~ x.+ ]] ; print $? + [[ foo =~ f.+ && bar =~ b.+ ]] ; print $? + [[ foo =~ x.+ && bar =~ b.+ ]] ; print $? + [[ foo =~ f.+ && bar =~ x.+ ]] ; print $? + [[ ! foo =~ f.+ && bar =~ b.+ ]] ; print $? + [[ foo =~ f.+ && ! bar =~ b.+ ]] ; print $? + [[ ! ( foo =~ f.+ && bar =~ b.+ ) ]] ; print $? + [[ ! foo =~ x.+ && bar =~ b.+ ]] ; print $? + [[ foo =~ x.+ && ! bar =~ b.+ ]] ; print $? + [[ ! ( foo =~ x.+ && bar =~ b.+ ) ]] ; print $? +0:Regex result inversion detection +>0 +>1 +>1 +>0 +>0 +>1 +>1 +>1 +>1 +>1 +>0 +>1 +>0 + +# Note that PCRE_ANCHORED only means anchored at the start +# Also note that we don't unset MATCH/match on failed match (and it's an +# open issue as to whether or not we should) + pcre_compile '.(→.)' + pcre_match foo→bar + print $? $MATCH $match ; unset MATCH match + pcre_match foo.bar + print $? $MATCH $match ; unset MATCH match + pcre_match foo†bar + print $? $MATCH $match ; unset MATCH match + pcre_match foo→†ar + print $? $MATCH $match ; unset MATCH match + pcre_study + pcre_match foo→bar + print $? $MATCH $match ; unset MATCH match + pcre_compile -a '.(→.)' + pcre_match foo→bar + print $? $MATCH $match ; unset MATCH match + pcre_match o→bar + print $? $MATCH $match ; unset MATCH match + pcre_match o→b + print $? $MATCH $match ; unset MATCH match + pcre_compile 'x.(→.)' + pcre_match xo→t + print $? $MATCH $match ; unset MATCH match + pcre_match Xo→t + print $? $MATCH $match ; unset MATCH match + pcre_compile -i 'x.(→.)' + pcre_match xo→t + print $? $MATCH $match ; unset MATCH match + pcre_match Xo→t + print $? $MATCH $match ; unset MATCH match +0:pcre_compile interface testing: basic, anchored & case-insensitive +>0 o→b →b +>1 +>1 +>0 o→† →† +>0 o→b →b +>1 +>0 o→b →b +>0 o→b →b +>0 xo→t →t +>1 +>0 xo→t →t +>0 Xo→t →t -- cgit v1.2.3 From faa02346a8b23ff0c6694b616c92e93b8e76cd8b Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Wed, 26 Oct 2011 18:48:13 +0000 Subject: 29844, 29845: remove bogus error on closing fd's 0 to 9; update test --- ChangeLog | 7 ++++++- Src/exec.c | 14 ++++++++++++-- Test/A04redirect.ztst | 7 +++++-- 3 files changed, 23 insertions(+), 5 deletions(-) (limited to 'Test') diff --git a/ChangeLog b/ChangeLog index 7cc2d1329..529d25293 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-10-26 Peter Stephenson + + * 29844, 29845: Src/exec.c, Test/A04redirect.ztst: remove bogus + error on closing fd's 0 to 9; update test. + 2011-10-26 Peter Stephenson * 29865: Src/Modules/pcre.mdd: don't compile if no pcre-config. @@ -15506,5 +15511,5 @@ ***************************************************** * This is used by the shell to define $ZSH_PATCHLEVEL -* $Revision: 1.5486 $ +* $Revision: 1.5487 $ ***************************************************** diff --git a/Src/exec.c b/Src/exec.c index 3d0731b3e..2c644e6b7 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -2912,6 +2912,7 @@ execcmd(Estate state, int input, int output, int how, int last1) } addfd(forked, save, mfds, fn->fd1, fn->fd2, 1, fn->varid); } else { + int closed; if (fn->type != REDIR_HERESTR && xpandredir(fn, redir)) continue; if (errflag) { @@ -3002,11 +3003,20 @@ execcmd(Estate state, int input, int output, int how, int last1) * Note we may attempt to close an fd beyond max_zsh_fd: * OK as long as we never look in fdtable for it. */ - if (!forked && fn->fd1 < 10 && save[fn->fd1] == -2) + closed = 0; + if (!forked && fn->fd1 < 10 && save[fn->fd1] == -2) { save[fn->fd1] = movefd(fn->fd1); + if (save[fn->fd1] >= 0) { + /* + * The original fd is now closed, we don't need + * to do it below. + */ + closed = 1; + } + } if (fn->fd1 < 10) closemn(mfds, fn->fd1); - if (zclose(fn->fd1) < 0) { + if (!closed && zclose(fn->fd1) < 0) { zwarn("failed to close file descriptor %d: %e", fn->fd1, errno); } diff --git a/Test/A04redirect.ztst b/Test/A04redirect.ztst index c2321a571..e58102664 100644 --- a/Test/A04redirect.ztst +++ b/Test/A04redirect.ztst @@ -156,11 +156,14 @@ read foo <&-) 1:'<&-' redirection ?(eval):1: failed to close file descriptor 3: bad file descriptor -?(eval):2: failed to close file descriptor 0: bad file descriptor print foo >&- 0:'>&-' redirection -?(eval):1: failed to close file descriptor 1: bad file descriptor + + (exec >&- + print foo) +0:'>&-' with attempt to use closed fd +?(eval):2: write error: bad file descriptor fn() { local foo; read foo; print $foo; } coproc fn -- cgit v1.2.3 From fe15a9e2bbf5b87962c0e4b2246e39f293ccf593 Mon Sep 17 00:00:00 2001 From: Phil Pennock Date: Wed, 26 Oct 2011 23:28:26 +0000 Subject: 29867: pcre/ZTST_unimplemented change from Bart --- ChangeLog | 8 +++++++- Test/V07pcre.ztst | 6 +++++- 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'Test') diff --git a/ChangeLog b/ChangeLog index 529d25293..bbe820cfb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-10-26 Phil Pennock + + * 29867: Bart Schaefer: Test/V07pcre.ztst: exit early with + unimplemented status if zsh/pcre not available; combined with + Peter's 29865 fix, should make PCRE testing robust. + 2011-10-26 Peter Stephenson * 29844, 29845: Src/exec.c, Test/A04redirect.ztst: remove bogus @@ -15511,5 +15517,5 @@ ***************************************************** * This is used by the shell to define $ZSH_PATCHLEVEL -* $Revision: 1.5487 $ +* $Revision: 1.5488 $ ***************************************************** diff --git a/Test/V07pcre.ztst b/Test/V07pcre.ztst index 4dd173557..f5b05deaa 100644 --- a/Test/V07pcre.ztst +++ b/Test/V07pcre.ztst @@ -1,6 +1,10 @@ %prep - zmodload zsh/pcre + if ! zmodload zsh/pcre 2>/dev/null + then + ZTST_unimplemented="the zsh/pcre module is not available" + return 0 + fi setopt rematch_pcre # Find a UTF-8 locale. setopt multibyte -- cgit v1.2.3