Subject: Re: Sample code in getopt(3)
To: None <tech-userlevel@netbsd.org>
From: der Mouse <mouse@Rodents.Montreal.QC.CA>
List: tech-userlevel
Date: 06/24/2003 20:06:25
> while ((c = getopt(argc, argv, "0123456789")) != -1) {
>         switch (c) {
>         case '0': case '1': case '2': case '3': case '4':
>         case '5': case '6': case '7': case '8': case '9':
>                 p = argv[optind - 1];
>                 if (p[0] == '-' && p[1] == ch && !p[2])
>                         length = atoi(++p);
>                 else
>                         length = atoi(argv[optind] + 1);
>                 break;
>         }
> }

> Can anyone explain what the second branch of the "if" is for, and how
> to trigger it?

It makes no sense to me.  My first reaction is that it's intended to
handle multi-digit arguments (which won't trip the first case because
of the !p[2] test), but in that case it needs to be [optind-1], and as
you point out gets confused when a digit option is merged in the same
argument as a non-digit option.

This looks like sample code dashed off with little thought and no
testing.  I think the right thing is to sit down and define exactly
what the intended semantics are, then implement them.  If it can't be
done with getopt, either don't use getopt or revise the spec.  (In
either case, the broken example code should be fixed or eliminated from
the manpage, of course.)

Part of the problem is that using getopt like this is ambiguous.  Is
"foo -56" supposed to be equivalent to "foo -5 -6"?  getopt simply is
not suitable for cases like this where options can sometimes be
multiple characters long (as opposed to options with arguments, which
is another schizoid area of getopt); trying to shoehorn it into a fit
is going to be uncomfortable at best, and I'm not surprised it breaks
something.

/~\ The ASCII				der Mouse
\ / Ribbon Campaign
 X  Against HTML	       mouse@rodents.montreal.qc.ca
/ \ Email!	     7D C8 61 52 5D E7 2D 39  4E F1 31 3E E8 B3 27 4B