zsh-workers
 help / color / mirror / code / Atom feed
From: "Bart Schaefer" <schaefer@candle.brasslantern.com>
To: zsh-workers@sunsite.auc.dk
Subject: "getopts" bugs and bad interactions with "shift"
Date: Tue, 23 Nov 1999 18:08:32 +0000	[thread overview]
Message-ID: <991123180832.ZM29676@candle.brasslantern.com> (raw)

Consider:

function oops() {
    while getopts :m: f
    do
	echo $OPTIND is $f with $OPTARG
	shift $((OPTIND - 1))
    done
}

3.0.7 gives:

zagzig% oops -m 0664 something
3 is m with 0664
zagzig% 

3.1.6-pws-9 gives:

zagzig% oops -m 0664 something 
2 is m with 0664
2 is ? with t
zagzig% 

There are two problems here: (1) OPTIND is different. (2) Parsing didn't
stop soon enough; it should have returned nonzero once -m was shifted off.
You can see the latter by changing the optstring to :m:t:, which gives

2 is m with 0664
2 is t with hing

I originally thought both had something to do with 7765,  but it behaves
like this at least as far back as 3.1.6-pws-4 (I didn't try any older).

I believe the following has something to do with (2), though this can't be
the entire issue, because I should be able to "fool" 3.0.7 by putting '-'
at the beginnings of selected words; yet I find I can't.

In 3.0 (which lacks the getopts rewrite from 3.1.2-zefram-3), this test
is used:

    if ((*str != '+' && *str != '-') || optcind >= lenstr ||
	(lenstr == 2 && str[0] == '-' && str[1] == '-')) {
	/* current argument doesn't contain options, or optcind is impossibly
	large */
	if (*str == '+' || *str == '-')
	    zoptind++;
	optcind = 0;
	return 1;
    }

But 3.1.x for x > 2 uses:

    if(optcind >= lenstr) {
	optcind = 0;
	if(!args[zoptind++])
	    return 1;
	str = unmetafy(dupstring(args[zoptind - 1]), &lenstr);
    }
    if(!optcind) {
	if(lenstr < 2 || (*str != '-' && *str != '+'))
	    return 1;
	if(lenstr == 2 && str[0] == '-' && str[1] == '-') {
	    zoptind++;
	    return 1;
	}
	optcind++;
    }

Note that the test of (*str != '-' && *str != '+') isn't done unless the
index into the string is zero, but the index isn't reset to zero unless
it's at or past the end of the string to begin with.

(At the very least, optcind should be getting reset to 0 whenever an
explicit assignment to OPTIND is done.)

However, this brings up the question of whether "getopts" and "shift" are
even -intended- to play nicely together.  I thought briefly about putting
an "optcind = 0;" into bin_shift(), but that doesn't cover this case:

    while getopts :m: f
    do
	argv[0,OPTIND-1]=()
    done

Nor this:

    array=($*)
    while getopts :m: f $array
    do
	array[OPTIND]=()
    done

Finally, there's the question of exactly what OPTIND is supposed to be.
The documentation for both versions says:

OPTIND <S>
     The index of the last option argument processed by the getopts
     command.

But when you assign to OPTIND, you assign the index of the *next* option
to be processed by the getopts command -- and the 3.0.7 behavior is to
leave OPTIND set to that *next* index.  3.1.6, on the other hand, uses
(optcind >= lenstr) to pre-increment zoptind, which leads to this third
bug when the presumed option argument is the empty string (-pws-9 again):

zagzig% oops "" -m 0664 something 
3 is m with 0664
zagzig% 

Question:  Is "getopts" based on some standard or emulated behavior of
some other shell, or is it strictly a zsh thing?  If the latter, I think
we should change the documentation and the 3.1.6 behavior of OPTIND to
match the 3.0.7 behavior, which fixes (1) and should make it much easier
to fix (2) if in fact we decide that's supposed to work at all.

I think the third bug will disappear as a side-effect of fixing OPTIND.

Comments?

-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com


             reply	other threads:[~1999-11-23 18:08 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
1999-11-23 18:08 Bart Schaefer [this message]
1999-11-23 18:22 ` Adam Spiers
1999-11-23 21:40   ` Bart Schaefer
1999-11-23 22:17     ` zsh 3.0.7 hogs memory James Kirkpatrick
1999-11-24  5:35       ` Bart Schaefer
1999-11-24 16:25         ` James Kirkpatrick
1999-11-30 15:42         ` James Kirkpatrick
1999-11-30 16:03           ` Bart Schaefer
1999-11-23 20:36 ` "getopts" bugs and bad interactions with "shift" Zefram
1999-11-24 11:50 Sven Wischnowsky
1999-11-24 17:44 ` Bart Schaefer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=991123180832.ZM29676@candle.brasslantern.com \
    --to=schaefer@candle.brasslantern.com \
    --cc=zsh-workers@sunsite.auc.dk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).