====== getopt(): Parse command-line opions ======
* [[https://www.gnu.org/software/libc/manual/html_node/Getopt.html|Parsing program options using getopt]]
* [[https://man7.org/linux/man-pages/man3/getopt.3.html|getopt(3) — Linux manual page]]
* [[https://azrael.digipen.edu/~mmead/www/mg/getopt/index.html|Mead's Guide to getopt]]
----
===== Simple Usage =====
// man 3 getopt
// gcc -Wall -Wextra -Werror -pedantic -std=c99 getopt.c
#include
#include
#include
#include
int main(int argc, char *argv[])
{
int opt;
while ((opt = getopt(argc, argv, "abX")) != -1) {
switch (opt) {
case 'a':
printf("Option -a provided\n");
break;
case 'b':
printf("Option -b provided\n");
break;
case 'X':
printf("Option -X provided\n");
break;
}
}
return EXIT_SUCCESS;
}
$ ./a.out -b
Option -b provided
$ ./a.out -b -X -a
Option -b provided
Option -X provided
Option -a provided
$ ./a.out -bXa
Option -b provided
Option -X provided
Option -a provided
$ ./a.out -a b X
Option -a provided
$ ./a.out -t
./a.out: invalid option -- 't'
$ ./a.out a b c
// Option Arguments
#include
#include
#include
#include
int main(int argc, char *argv[])
{
int opt;
while ((opt = getopt(argc, argv, "a:b:X")) != -1) {
switch (opt) {
case 'a':
printf("Option -a provided with argument: %s\n", optarg);
break;
case 'b':
printf("Option -b provided with argument: %s\n", optarg);
break;
case 'X':
printf("Option -X provided\n");
break;
}
}
return EXIT_SUCCESS;
}
$ gcc -Wall -Wextra -Werror -pedantic -std=c99 getopt.c
$ ./a.out -a one -b two -X
Option -a provided with argument: one
Option -b provided with argument: two
Option -X provided
$ ./a.out -aone -btwo
Option -a provided with argument: one
Option -b provided with argument: two
$ ./a.out -X -a
Option -X provided
./a.out: option requires an argument -- 'a'
$ ./a.out -a -X
Option -a provided with argument: -X
// Unknown Options and Missing Option Arguments
// To disable the automatic error printing, simply put a colon as
// the first character in optstring
#include
#include
#include
#include
int main(int argc, char *argv[])
{
int opt;
// Notice the leading : in the option string
while ((opt = getopt(argc, argv, ":a:b:X")) != -1) {
switch (opt) {
case 'a':
printf("Option -a provided with argument: %s\n", optarg);
break;
case 'b':
printf("Option -b provided with argument: %s\n", optarg);
break;
case 'X':
printf("Option -X provided\n");
break;
case '?':
printf("Unknown option: %c\n", optopt);
break;
case ':':
printf("Missing argument for: %c\n", optopt);
break;
}
}
return EXIT_SUCCESS;
}
$ gcc -Wall -Wextra -Werror -pedantic -std=c99 getopt.c
$ ./a.out -a
Missing argument for: a
$ ./a.out -t
Unknown option: t
$ ./a.out -a one -t -X -b
Option -a provided with argument: one
Unknown option: t
Option -X provided
Missing argument for: b
$ ./a.out -a one,two,three
Option -a provided with argument: one,two,three
$ ./a.out -a "one two three"
Option -a provided with argument: one two three
// Non-Option Arguments
// The default is to permute the contents of argv while scanning it
// so that eventually all the non-options are at the end. This allows
// options to be given in any order, even with programs that were not
// written to expect this.
#include
#include
#include
#include
int main(int argc, char *argv[])
{
int opt;
// Notice the leading : in the option string
while ((opt = getopt(argc, argv, ":a:b:X")) != -1) {
switch (opt) {
case 'a':
printf("Option -a provided with argument: %s\n", optarg);
break;
case 'b':
printf("Option -b provided with argument: %s\n", optarg);
break;
case 'X':
printf("Option -X provided\n");
break;
case '?':
printf("Unknown option: %c\n", optopt);
break;
case ':':
printf("Missing argument for: %c\n", optopt);
break;
}
}
if (optind < argc) {
printf("Non-option args: ");
while (optind < argc)
printf("%s ", argv[optind++]);
printf("\n");
}
return EXIT_SUCCESS;
}
$ ./a.out x -a one y -X z
Option -a provided with argument: one
Option -X provided
Non-option args: x y z
$ ./a.out x y z -a one -b two
Option -a provided with argument: one
Option -b provided with argument: two
Non-option args: x y z
// Non-Option Arguments
// If the options argument string begins with a hyphen (‘-’), this is
// treated specially. It permits arguments that are not options to be
// returned as if they were associated with option character ‘\1’.
#include
#include
#include
#include
int main(int argc, char *argv[])
{
int opt;
// Notice the leading minus sign - in the option string below
// Remember that the number one in single quotes '1' is not the
// same as the number one without quotes. '1' is ASCII 49
while ((opt = getopt(argc, argv, "-:a:b:X")) != -1) {
switch (opt) {
case 'a':
printf("Option -a provided with argument: %s\n", optarg);
break;
case 'b':
printf("Option -b provided with argument: %s\n", optarg);
break;
case 'X':
printf("Option -X provided\n");
break;
case '?':
printf("Unknown option: %c\n", optopt);
break;
case ':':
printf("Missing argument for: %c\n", optopt);
break;
case 1:
printf("Non-option arg: %s\n", optarg);
break;
}
}
return EXIT_SUCCESS;
}
$ gcc -Wall -Wextra -Werror -pedantic -std=c99 getopt.c
$ ./a.out x y z -a foo
Non-option arg: x
Non-option arg: y
Non-option arg: z
Option -a provided with argument: foo
$ ./a.out x -a foo y -b bar z -X w
Non-option arg: x
Option -a provided with argument: foo
Non-option arg: y
Option -b provided with argument: bar
Non-option arg: z
Option -X provided
Non-option arg: w
$ ./a.out -t x -a foo -M y -b bar z -X w -b
Unknown option: t
Non-option arg: x
Option -a provided with argument: foo
Unknown option: M
Non-option arg: y
Option -b provided with argument: bar
Non-option arg: z
Option -X provided
Non-option arg: w
Missing argument for: b
----
===== POSIX Non-Option Arguments =====
// Non-Option Arguments
// POSIX demands the following behavior: the first non-option stops option
// processing. This mode is selected by either setting the environment
// variable POSIXLY_CORRECT or beginning the options argument string
// with a plus sign (‘+’).
// Pejman:
// POSIXLY_CORRECT did not change anything
//#define POSIXLY_CORRECT
// this line changed the behavior to POSIX
#define _XOPEN_SOURCE
#include
#include
#include
#include
int main(int argc, char *argv[])
{
int opt;
// Notice the leading : in the option string
while ((opt = getopt(argc, argv, ":a:b:X")) != -1) { // or simply use "+:a:b:X"
switch (opt) {
case 'a':
printf("Option -a provided with argument: %s\n", optarg);
break;
case 'b':
printf("Option -b provided with argument: %s\n", optarg);
break;
case 'X':
printf("Option -X provided\n");
break;
case '?':
printf("Unknown option: %c\n", optopt);
break;
case ':':
printf("Missing argument for: %c\n", optopt);
break;
}
}
if (optind < argc) {
printf("Non-option args: ");
while (optind < argc)
printf("%s ", argv[optind++]);
printf("\n");
}
return EXIT_SUCCESS;
}
$ gcc -Wall -Wextra -Werror -pedantic -std=c99 getopt.c
$ ./a.out x -a one y -X
Non-option args: x -a one y -X
$ ./a.out x y z -a one -b two
Non-option args: x y z -a one -b two
$ ./a.out -a one -b two x y z
Option -a provided with argument: one
Option -b provided with argument: two
Non-option args: x y z