[TUHS] Command line options and complexity

Steffen Nurpmeso steffen at sdaoden.eu
Fri Mar 13 05:24:38 AEST 2020

John P. Linderman wrote in
<CAC0cEp_fQsq6-EaG-nhvXTvZij+PSab5PNTEx7WhNjYwnFVnaw at mail.gmail.com>:
 |My error. I was looking at getopt(1) rather than getopt(3). Of course \
 |optind is documented, it's the way to find non-flag arguments.

 |I don't know why the Hancock authors chose to make rsort into a subroutine \
 |rather than just piping into the command. Perhaps something to do with \
 |the software release process?

I really like a lot of such old code, and reading it.  One can
only learn from it.  Even though i discovered all this in
(Free)BSD land, after coming over from Linux, I loved reading
those "old-hand" comment blocks, it was inspiration and kindled
something here.  For the few pieces of code that i am prowd of aka
that i thought were worth it i followed their example.  This
rsort.c is however more verbose and spiritful than anything i ever
wrote.  I keep it in my box of precious things.

getopt(3) on the other hand is portable but terrible.  Just on the
10th i resorted a small SCSI MMC-3 cdda access tool (~50 KB
C source are necessary for that in 2020, missing Solaris and
MacOS, but including CD-TEXT and all that!!) to it because people
are used to option and/or argument joining etc, but it lost long
option support.

Not worth commenting a lot, but here is an option parser of 6359
bytes when development verification code and dump_doc() are not
counted, but is uses a carrier struct, supports long options, and
documentation strings as part of long option strings (one .RODATA
entry).  FreeBSD's standard compatible and thus naked
lib/libc/stdlib/getopt.c is 4312 bytes.  And GNU's getopt_long is
huge and even permutates arguments.

At least getopt(3) is predictable once a user gets it.  Things are
different for sed(1)s -i and some sccs commands i have forgotten.
I think it has even be tried to standardize optional arguments in
that respect, but i would argue this is not a good direction to
go, consider for example "sed -ie".  Isn't this asking for
troubles without accompanying comments.

 *   static char const a_sopts[] = "A:h#";
 *   static char const * const a_lopts[] = {
 *      "account:;A;" N_("execute an `account' command"),
 *      "long-help;\201;" N_("this listing"),
 *      NIL
 *   };
 *   struct su_avopt avo;
 *   su_avopt_setup(&avo, --argc, C(char const*const*,++argv),
 *      a_sopts, a_lopts);
 *   while((i = su_avopt_parse(&avo)) != su_AVOPT_STATE_DONE){
 *      switch(i){
 *      case 'A':
 *         "account_name" = avo.avo_current_arg;
 *         break;
 *      case 'h':
 *      case S(char,S(u8,'\201')):
 *         a_main_usage(n_stdout);
 *         if(i != 'h'){
 *            fprintf(n_stdout, "\nLong options:\n");
 *            su_avopt_dump_doc(&avo, &a_main_dump_doc, S(up,n_stdout));
 *         }
 *         exit(0);
 *   argc = avo.avo_argc;
 *   argv = C(char**,avo.avo_argv);

|Der Kragenbaer,                The moon bear,
|der holt sich munter           he cheerfully and one by one
|einen nach dem anderen runter  wa.ks himself off
|(By Robert Gernhardt)

More information about the TUHS mailing list