Recent

Author Topic: In GetOpt identify which long option has missing argument  (Read 1365 times)

jollytall

  • Sr. Member
  • ****
  • Posts: 319
In GetOpt identify which long option has missing argument
« on: October 12, 2021, 12:55:31 pm »
I use GetOpts and the example program as shown on https://www.freepascal.org/docs-html/rtl/getopts/getopt.html.

--create and -c are sort of the same thing, both requiring an argument. If I miss it I get an error both from the GetOpts unit and from the program.
Code: [Select]
>./testopt --cre
./testopt: option create requires an argument
Error with opt : ?

>./testopt -c
./testopt: option requires an argument -- c
Error with opt : c
It is interesting how the first errors (hardcoded in the GetOpts unit) differ. While for long options it gives a clear full sentence, for the short option it is in itself a bit misleading, using -- and a space before the option c. I would expect the two error messages to work the same way. My taste would be using also some quotation around the option and the proper number of hyphens before the option, like
Code: [Select]
./testopt: option '--create' requires an argument
./testopt: option '-c' requires an argument
but it is a matter of taste. Still, in whatever format, I would recommend to change it a bit and make the two similar.

But this is not my main point. In a real program the programmer most probably will suppress the first error message by
Code: Pascal  [Select][+][-]
  1.  opterr:=false;
, so the error can be handed more "discretely".
The problem is that in case of a long option the calling program does not get back from the GetOpts unit the option creating the error. This is why the example program is only showing a "?".

I tried everything possible, but could not get it. Using a ":" in the ShortOpts first character (or second if the first is a "-" or a "+"), at least splits the return value of GetLongOpts into "?" and ":" depending whether the (long) option is unknown or the argument is missing, but still the name of the option giving the error is not returned. It is clear that the function itself still knows the option with the missing parameter, but it is not returned in OptionIndex in case of an error.
I would recommend, or ask, to update the GetLongOpts function to return in OptionIndex the index of the long option if the option is found but the argument is missing.

Two more things:

I think in the example program it is not ideal to return #0 for long options if they have no short equivalent. If the ShortOpts starts with a "-" indicating that non-options should be returned in their sequence, they also get a #0 return value and it gets confusing. Just try changing ShortOpts to '-abc:d:012' and call
Code: [Select]
>./testopt -ver xyz
Long option : verbose
Long option : verbose
This is because both return #0, but xyz does not update the OptionIndex so the last value is used.
This is not an error, I know, just a bit misleading example program.

It seems even in the design of getopt there is a little error. It is not Pascal related. I found a very good document, worth reading if you want to understand GetOpt: https://azrael.digipen.edu/~mmead/www/mg/getopt/index.html.
If a long option is used as a Flag, i.e. the flag value is not nil, the value set to the value field is not the return value of GetLongOpts like normally, but only the updated value of the variable used as flag. The return value of GetLongOpts is #0 in this case. Consequently if one uses both Flag purpose long options and non-options in their sequential position, both gives back #0 and can only be differentiated by checking OptArg. It would have been smarter to use e.g. #0 for non-options, #1 for flags (or just return the flag value, what is often #1 anyway) and then programmers could still use e.g. #2 for long options without short equivalent, so the three would be well differentiated.

 

TinyPortal © 2005-2018