did anyone ever use it this way, or are you getting ahead of yourself.

Scott Cheloha <scottchel...@gmail.com> wrote:

> Hi,
> 
> head(1) takes line count arguments in two ways.  The legacy (1977)
> syntax is "-count" [1].  The "new" (1992) syntax is "-n count" [2].
> In either case, "count" must be a positive decimal value.
> 
> Somewhere along the way, support for the legacy syntax was neutered.
> At present it only works as expected if -count is the first option
> argument to head(1), i.e. this works:
> 
>       $ head -20 file
> 
> but this is an error:
> 
>       $ head -20 -25 file
> 
> I'm not a fan of this.  If we're going to support the legacy syntax I
> think it should behave like option arguments for other utilities.  You
> should be able to specify -count multiple times.  We do this for
> tail(1), which has a similar legacy syntax problem.
> 
> The easiest way to transparently support such invocations is to use
> the GNU double-colon extension for getopt(3).  We then rebuild the
> number string with asprintf(3), parse it with strtonum(3), and free
> the string.
> 
> Before:
> 
> $ jot 10 | head -5 -6
> head: unknown option -- 6
> usage: head [-count | -n count] [file ...]
> 
> After:
> 
> $ jot 10 | head -5 -6
> 1
> 2
> 3
> 4
> 5
> 6
> 
> --
> 
> ok?
> 
> [1] 
> https://svnweb.freebsd.org/csrg/usr.bin/head/head.c?revision=1026&view=markup
> 
> [2] 
> https://svnweb.freebsd.org/csrg/usr.bin/head/head.c?revision=52824&view=markup
> 
> Index: head.c
> ===================================================================
> RCS file: /cvs/src/usr.bin/head/head.c,v
> retrieving revision 1.22
> diff -u -p -r1.22 head.c
> --- head.c    10 Oct 2021 15:57:25 -0000      1.22
> +++ head.c    10 Oct 2021 16:44:01 -0000
> @@ -49,27 +49,30 @@ int
>  main(int argc, char *argv[])
>  {
>       const char *errstr;
> +     char *str;
>       FILE    *fp;
>       long    cnt;
>       int     ch, firsttime;
>       long    linecnt = 10;
> -     int     status = 0;
> +     int error, status = 0;
>  
>       if (pledge("stdio rpath", NULL) == -1)
>               err(1, "pledge");
>  
> -     /* handle obsolete -number syntax */
> -     if (argc > 1 && argv[1][0] == '-' &&
> -         isdigit((unsigned char)argv[1][1])) {
> -             linecnt = strtonum(argv[1] + 1, 1, LONG_MAX, &errstr);
> -             if (errstr != NULL)
> -                     errx(1, "count is %s: %s", errstr, argv[1] + 1);
> -             argc--;
> -             argv++;
> -     }
> -
> -     while ((ch = getopt(argc, argv, "n:")) != -1) {
> +#define OPTSTR "0::1::2::3::4::5::6::7::8::9::n:"
> +     while ((ch = getopt(argc, argv, OPTSTR)) != -1) {
>               switch (ch) {
> +             case '0': case '1': case '2': case '3': case '4':
> +             case '5': case '6': case '7': case '8': case '9':
> +                     error = asprintf(&str, "%c%s",
> +                         ch, (optarg == NULL) ? "" : optarg);
> +                     if (error == -1)
> +                             err(1, "asprintf");
> +                     linecnt = strtonum(str, 1, LONG_MAX, &errstr);
> +                     if (errstr != NULL)
> +                             errx(1, "count is %s: %s", errstr, str);
> +                     free(str);
> +                     break;
>               case 'n':
>                       linecnt = strtonum(optarg, 1, LONG_MAX, &errstr);
>                       if (errstr != NULL)
> 

Reply via email to