From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 3547 invoked by alias); 28 May 2015 17:18:09 -0000 Mailing-List: contact zsh-workers-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Workers List List-Post: List-Help: X-Seq: 35318 Received: (qmail 5653 invoked from network); 28 May 2015 17:18:06 -0000 X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_HI, RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL,SPF_HELO_PASS autolearn=ham autolearn_force=no version=3.4.0 X-AuditID: cbfec7f5-f794b6d000001495-ae-55674dc900d3 Date: Thu, 28 May 2015 18:17:40 +0100 From: Peter Stephenson To: zsh-workers@zsh.org Subject: Re: getopts doesn't update OPTIND when called from function Message-id: <20150528181740.20267791@pwslap01u.europe.root.pri> In-reply-to: <55673FD8.7010301@inlv.org> References: <55673FD8.7010301@inlv.org> Organization: Samsung Cambridge Solution Centre X-Mailer: Claws Mail 3.7.9 (GTK+ 2.22.0; i386-redhat-linux-gnu) MIME-version: 1.0 Content-type: text/plain; charset=US-ASCII Content-transfer-encoding: 7bit X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFjrILMWRmVeSWpSXmKPExsVy+t/xq7onfdNDDR5MlrI42PyQyYHRY9XB D0wBjFFcNimpOZllqUX6dglcGVNv1RRclK44vuIecwNjh1gXIweHhICJxPH9Ml2MnECmmMSF e+vZuhi5OIQEljJKnJ94AcqZwSTx+OYsFghnG6PEn2+/2UBaWARUJXZtnsQIYrMJGEpM3TQb zBYREJc4u/Y8C4gtLOAiMWnvekaQbbwC9hL9j0xBwpwCGhIbzs1hB7GFBNQlXjY+YwKx+QX0 Ja7+/cQEcZG9xMwrZ8BG8goISvyYfA9sJLOAlsTmbU2sELa8xOY1b5lh5ty4u5t9AqPQLCQt s5C0zELSsoCReRWjaGppckFxUnqukV5xYm5xaV66XnJ+7iZGSMB+3cG49JjVIUYBDkYlHl6F OWmhQqyJZcWVuYcYJTiYlUR41ezSQ4V4UxIrq1KL8uOLSnNSiw8xSnOwKInzztz1PkRIID2x JDU7NbUgtQgmy8TBKdXAOO/nUanbF+865Dt1sFyw8Vq74W5Of5GRUQn382WfPl+ZHOI9pWri UfFjGh+0snu7y/pvsMt+fz5nT1bp4WfOG3mUowWWNAW/yZ+pFHTi9HXGppjJ3Kqr/yzkM74U Yd88P+vtTdsLi95e7Xhc4PNeu8PIouoP8yc23Tuv3P5dl5q7W3lFxLuyBCWW4oxEQy3mouJE AG+DiupUAgAA On Thu, 28 May 2015 18:18:32 +0200 Martijn Dekker wrote: > I'm writing a shell function that extends the functionality of the > 'getopts' builtin. For that to work, it is necessary to call the > 'getopts' builtin from the shell function. > > The POSIX standard specifies that OPTIND and OPTARG are global > variables, even if the positional parameters are local to the > function.[*] This makes it possible to call 'getopts' from a function by > simply passing the global positional parameters along by adding "$@". > > My problem is that zsh does not update the global OPTIND variable when > getopts is called from a function, which defeats my function on zsh. (It > does update the global OPTARG variable, though.) This is documented behaviour (well, sort of -- the documentation didn't say quite what we actually do) so this needs another compatibility fix. POSIX_BUILTINS seems appropriate. diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo index a2c03bc..f8e4edf 100644 --- a/Doc/Zsh/builtins.yo +++ b/Doc/Zsh/builtins.yo @@ -866,7 +866,8 @@ vindex(OPTARG, use of) The first option to be examined may be changed by explicitly assigning to tt(OPTIND). tt(OPTIND) has an initial value of tt(1), and is -normally reset to tt(1) upon exit from a shell function. tt(OPTARG) +normally set to tt(1) upon entry to a shell function and restored +upon exit (this is disabled by the tt(POSIX_BUILTINS) option). tt(OPTARG) is not reset and retains its value from the most recent call to tt(getopts). If either of tt(OPTIND) or tt(OPTARG) is explicitly unset, it remains unset, and the index or option argument is not diff --git a/Doc/Zsh/options.yo b/Doc/Zsh/options.yo index 032423d..4c0ae12 100644 --- a/Doc/Zsh/options.yo +++ b/Doc/Zsh/options.yo @@ -2038,6 +2038,10 @@ tt(unset). In addition, various error conditions associated with the above builtins or tt(exec) cause a non-interactive shell to exit and an interactive shell to return to its top-level processing. + +Furthermore, the tt(getopts) builtin behaves in a POSIX-compatible +fashion in that the associated variable tt(OPTIND) is not made +local to functions. ) pindex(POSIX_IDENTIFIERS) pindex(NO_POSIX_IDENTIFIERS) diff --git a/Src/builtin.c b/Src/builtin.c index a9afb45..18c22f2 100644 --- a/Src/builtin.c +++ b/Src/builtin.c @@ -4713,6 +4713,10 @@ bin_shift(char *name, char **argv, Options ops, UNUSED(int func)) return ret; } +/* + * Position of getopts option within OPTIND argument with multiple options. + */ + /**/ int optcind; diff --git a/Src/exec.c b/Src/exec.c index 527d611..9f163a6 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -4910,9 +4910,11 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval) if (!(flags & PM_UNDEFINED)) scriptname = dupstring(name); oldzoptind = zoptind; - zoptind = 1; oldoptcind = optcind; - optcind = 0; + if (!isset(POSIXBUILTINS)) { + zoptind = 1; + optcind = 0; + } /* We need to save the current options even if LOCALOPTIONS is * * not currently set. That's because if it gets set in the * @@ -5049,8 +5051,10 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval) argzero = oargv0; } pparams = pptab; - optcind = oldoptcind; - zoptind = oldzoptind; + if (!isset(POSIXBUILTINS)) { + zoptind = oldzoptind; + optcind = oldoptcind; + } scriptname = oldscriptname; oflags = ooflags;