Have a problem with parsing options using "getopt_long"

Go To Last Post
10 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi all,

I am working on a program that will take command line options and work with a file. The program usage is like this:

program -a -b --linelength=12 filename

Note that the "12" can be any number, but it's a required argument for the option "linelength".

My problem is, if I omit the linelength argument and the filename comes next, then I don't get the "option requires an argument" error, but rather the getopt tries to use the filename as the argument, effectively resulting in this:

program -a -b --linelength=filename

Then, of course, because there is no filename, that generates an error.

I am sure I'm doing something wrong or missing something, because the code should be "smart enough" to avoid this. Any ideas?

Here's (hopefully) the relevant part:

// parse arguments
while ((opt = getopt_long (argc, argv, optstr, lopts, (int *)(0))) != EOF)
{
  switch (opt) {
    case 'c': {
      colors = 1;
      break;
    }
    case 'h': {
      return show_help();
    }
    case 'i': {
      ignore_case = 1;
      break;
    }
    case 'l': {
      lineLength = strtol (optarg, (char **) (0), 10);
      break;
    }
    case 'm': {
      mode = maximized;
      lineLength = 0;
      break;
    }
    case 's': {
      mode = bySector;
      break;
    }
    case '?': {
      if (optopt == 'l') {
        fprintf (stderr, "option -%c requires an argument\n", optopt);
        return 1;
      }
    }
    default: {
      break;
    }
  }
}

if (optind < argc)
{
  fileName = argv[optind];
}

Thanks!

 

 

Gentlemen may prefer Blondes, but Real Men prefer Redheads!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What is at "lopts". The manual says this is an array of struct{}.

 

Anyway I would have thought this kind of Posix question was best asked on StackOverflow?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The behavior you see is what is intended.  This is from the manual page: A long option may take a parameter, of the form --arg=param or --arg param.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

getopt_long believes in strings.

It does not know that the argument for

linelength needs to represent a number,

nor can it be told.

To check it, additional code is needed.

Moderation in all things. -- ancient proverb

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

What is at "lopts". The manual says this is an array of struct{}.

 

Anyway I would have thought this kind of Posix question was best asked on StackOverflow?

 

I didn't think the struct was important to my question. Here it is:

 

static struct option lopts[] = {
#ifdef HAVE_COLORS
    { "color",           no_argument,       0, 'c' },
#endif
    { "help",            no_argument,       0, 'h' },
    { "ignorecase",      no_argument,       0, 'i' },
    { "linelength",      required_argument, 0, 'l' },
    { "maximize",        no_argument,       0, 'm' },
    { "sector",          no_argument,       0, 's' },
#if defined(__STDC__) && __STDC__
    { (const char *)0,   0,                 0, '\0' },
#else
    { (char *)0,         0,                 0, '\0' },
#endif
};
const char *optstr =
#ifdef HAVE_COLORS
    "c"
#endif
    "hil:ms?";

 

And, why ask on Stack Overflow? I wanted to ask here.

 

Gentlemen may prefer Blondes, but Real Men prefer Redheads!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


Krupski wrote:
And, why ask on Stack Overflow? I wanted to ask here.
Because you are asking about a Posix OS function on an AVR microcontroller site. Or are you saying you have an AVR running an OS with command line processing? I simply suggested SO because that is where "experts" in the use of Posix OS functions are most likely to be found.

 

It would be a bit like me asking about tuning a car engine here - sure I might stumble across someone who happens to know but I would likely get more mileage on a car engineers forum !

 

I just tried a google along the lines of what you are asking about and guess where the first lot of top hits happen to be found...

 

Last Edited: Wed. Jun 30, 2021 - 04:54 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

Krupski wrote:
And, why ask on Stack Overflow? I wanted to ask here.
Because you are asking about a Posix OS function on an AVR microcontroller site. Or are you saying you have an AVR running an OS with command line processing? I simply suggested SO because that is where "experts" in the use of Posix OS functions are most likely to be found.

 

It would be a bit like me asking about tuning a car engine here - sure I might stumble across someone who happens to know but I would likely get more mileage on a car engineers forum !

 

I just tried a google along the lines of what you are asking about and guess where the first lot of top hits happen to be found...

 

 

Sorry... guess I missed the "AVR" part of "Compilers and General Programming". I asked here because I usually get quick and correct answers/ideas.

 

 

Gentlemen may prefer Blondes, but Real Men prefer Redheads!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


Krupski wrote:

Sorry... guess I missed the "AVR" part of "Compilers and General Programming".

 

When you go up a couple levels on the Web page you are posting on, you find

Note the "AVR" under AVRFREAKS.  (well, there >>is<< the Atmel as well)

 

 

 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It is perfectly legal to have :

--linelength=123

--linelength 123

 

You will evaluate the 123 as non-zero and be quite happy.

 

--linelength filename

 

will evaluate "filename" as zero.   Which you can flag as an error.

 

It all depends on how nice you want to be to your punters.   People will always make typos.   You need to handle the typical errors without p*ssing off the punters.

 

If you want people to type a command line you should make it easy.   Which is probably why Unix V7 had short names.

If the "command line program" is invoked by a shell script you rely on the shellscript author spelling things correctly and documenting.   Which is probably why you see --long_descriptive_argument_name

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

david.prentice wrote:
--linelength filename

 

will evaluate "filename" as zero.   Which you can flag as an error.

But might not want to.

Zero is sometimes used to indicate no limit.

In that case, checking whether *endptr points to a null is the more reliable guide.

Even if zero is not allowed, one might want to give different

error messages for an explicit zero and a string without digits.

 

 

BTW I'd use strtoul.

Moderation in all things. -- ancient proverb