Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: bug in getopts



Christopher T. White wrote:
> 
> Dear ZSH users and workers,
> 
> Forgive me if this has been addressed previously, but I haven't run into
> this particular situation before.
> 
> Getops seems to be broken in zsh version 3.1.0. 

It's broken in 3.0.2, too.

I looked into the sources and think I found the bug(s). Edit the file
zsh-3.1.0/Src/buitin.c, look for the function 'bin_getopts' and replace
that function by the attached version. I marked the changes with /*!! 
(sorry, I'm not yet familiar with the patch utility).

After rebuild ingand reinstalling zsh, getopts should work correctly.

Regards,
	Bernd

--- 
Bernd Eggink
Regionales Rechenzentrum der Universitaet Hamburg
eggink@xxxxxxxxxxxxxxxxxx
http://www.rrz.uni-hamburg.de/eggink/BEggink.html
int
bin_getopts(char *name, char **argv, char *ops, int func)
{
    int lenstr, lenoptstr, i;
    char *optstr = unmetafy(*argv++, &lenoptstr), *var = *argv++;
    char **args = (*argv) ? argv : pparams;
    static int optcind = 1, quiet;
    char *str, optbuf[2], *opch = optbuf + 1;

    /* zoptind keeps count of the current argument number */
    if (zoptind < 1)
	/* first call */
	zoptind = 1;
    if (zoptind == 1)
{ /*!! added*/
	quiet = 0;
    optbuf[0] = '+';
    zsfree(zoptarg);
    zoptarg = ztrdup("");
    setsparam(var, ztrdup(""));
    if (*optstr == ':') {
	quiet = 1;
	optstr++;
    }
}	/*!! added*/
    if (zoptind > arrlen(args))
	return 1;
    str = unmetafy(args[zoptind - 1], &lenstr);
    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;
    }
    /* Get the option character.  optcind records the current position within
    the argument. */
    if (!optcind)
	optcind = 1;
    *opch = str[optcind++];
    if (optcind == lenstr) {
	if(args[zoptind++])
	    str = unmetafy(args[zoptind - 1], &lenstr);
	optcind = 0;
    }
    /* look for option in the provided optstr */
    for (i = 0; i != lenoptstr; i++)
	if (*opch == optstr[i])
	    break;
    if (i == lenoptstr) {
	/* not a valid option */
	setsparam(var, ztrdup("?"));
	if (quiet) {
	    zsfree(zoptarg);
	    zoptarg = metafy(opch, 1, META_DUP);
	    return 0;
	}
	zerr("bad option: -%c", NULL, *opch);
	errflag = 0;
	return 0;
    }
    /* copy option into specified parameter, with + if required */
    setsparam(var, metafy(opch - (*str == '+'), 1 + (*str == '+'), META_DUP));
    /* handle case of an expected extra argument */
    if (optstr[i + 1] == ':') { /*!! changed 1 to i + 1 */
	if (!args[zoptind - 1]) {
	    /* no extra argument was provided */
	    if (quiet) {
		zsfree(zoptarg);
		zoptarg = metafy(opch, 1, META_DUP);
		setsparam(var, ztrdup(":"));
		return 0;
	    }
	    setsparam(var, ztrdup("?"));
	    zerr("argument expected after -%c option", NULL, *opch);
	    errflag = 0;
	    return 0;
	}
	/* skip over the extra argument */
	zsfree(zoptarg);
	zoptarg = metafy(str + optcind, lenstr - optcind, META_DUP);
	zoptind++;
	optcind = 0;
    }
    return 0;
}




Messages sorted by: Reverse Date, Date, Thread, Author