From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 9098 invoked from network); 10 Sep 1999 10:22:57 -0000 Received: from ns2.primenet.com.au (HELO primenet.com.au) (?XRk4HQOk/cbkPDsCbRBX+zN2iPetEHNA?@203.24.36.3) by ns1.primenet.com.au with SMTP; 10 Sep 1999 10:22:57 -0000 Received: (qmail 14653 invoked from network); 10 Sep 1999 09:22:54 -0000 Received: from sunsite.auc.dk (130.225.51.30) by ns2.primenet.com.au with SMTP; 10 Sep 1999 09:22:54 -0000 Received: (qmail 5279 invoked by alias); 10 Sep 1999 09:21:44 -0000 Mailing-List: contact zsh-workers-help@sunsite.auc.dk; run by ezmlm Precedence: bulk X-No-Archive: yes X-Seq: 7765 Received: (qmail 5272 invoked from network); 10 Sep 1999 09:21:44 -0000 Message-Id: <199909100921.LAA90878@hydra.ifh.de> X-Authentication-Warning: hydra.ifh.de: pws owned process doing -bs To: zsh-workers@sunsite.auc.dk (Zsh hackers list) Subject: PATCH: 3.1.6-pws-3: more getopts bugs Date: Fri, 10 Sep 1999 11:21:24 +0200 From: Peter Stephenson I haven't been using getopts in the zf* functions because people keep reporting bugs in it. Looks like I was right. Here are bugs number 343 and 344. 1. The counter for how far we are into a single option argument doesn't get rest when OPTIND goes back to 1 (i.e. when a new function is started), only if OPTIND is set explicitly to 0. (How can this possibly have escaped notice for almost a decade?) One way to see this is: badfn() { local opt while getopts :abc opt; do [[ $opt = '?' ]] && print "Bad option $OPTARG" && return 1 done return 0 } badfn -X badfn -X The first time you get the error message as expected, the second time you don't because getopts thinks it's already at the end of the option list. 2. The manual page claims the option variable gets set to '?' even if an error message was printed by getopts itself (i.e. no initial colon). Guess what? To see that, remove the : and watch the second line not get executed. --- Src/builtin.c.optc Tue Sep 7 09:24:00 1999 +++ Src/builtin.c Fri Sep 10 10:33:45 1999 @@ -2936,6 +2936,9 @@ return ret; } +/**/ +int optcind; + /* getopts: automagical option handling for shell scripts */ /**/ @@ -2945,7 +2948,6 @@ int lenstr, lenoptstr, quiet, lenoptbuf; char *optstr = unmetafy(*argv++, &lenoptstr), *var = *argv++; char **args = (*argv) ? argv : pparams; - static int optcind = 0; char *str, optbuf[2] = " ", *p, opch; /* zoptind keeps count of the current argument number. The * @@ -2994,8 +2996,8 @@ p = "?"; err: zsfree(zoptarg); + setsparam(var, ztrdup(p)); if(quiet) { - setsparam(var, ztrdup(p)); zoptarg = metafy(optbuf, lenoptbuf, META_DUP); } else { zerr(*p == '?' ? "bad option: -%c" : --- Src/exec.c.optc Wed Sep 1 14:32:50 1999 +++ Src/exec.c Fri Sep 10 10:28:32 1999 @@ -2918,7 +2918,7 @@ * was executed. */ { char **tab, **x, *oargv0 = NULL; - int oldzoptind, oldlastval; + int oldzoptind, oldlastval, oldoptcind; char saveopts[OPT_SIZE], *oldscriptname; int obreaks = breaks; @@ -2935,6 +2935,8 @@ scriptname = dupstring(name); oldzoptind = zoptind; zoptind = 1; + oldoptcind = optcind; + 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 * @@ -2974,6 +2976,7 @@ zsfree(argzero); argzero = oargv0; } + optcind = oldoptcind; zoptind = oldzoptind; scriptname = oldscriptname; pparams = tab; -- Peter Stephenson Tel: +39 050 844536 WWW: http://www.ifh.de/~pws/ Dipartimento di Fisica, Via Buonarroti 2, 56127 Pisa, Italy