X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=tests%2Ftest-getopt_long.h;h=9d55c653250869acc4dfa1fb1bf953d1671e0c3f;hb=77cef2022004c4066e805da09a83b2c77f17bdd3;hp=d0d16fa67791228f9b23ec2f81d736869d3c338e;hpb=82381b9e5b37125305709d412d8322b35e5c4796;p=gnulib.git diff --git a/tests/test-getopt_long.h b/tests/test-getopt_long.h index d0d16fa67..9d55c6532 100644 --- a/tests/test-getopt_long.h +++ b/tests/test-getopt_long.h @@ -1,5 +1,5 @@ /* Test of command line argument processing. - Copyright (C) 2009 Free Software Foundation, Inc. + Copyright (C) 2009-2012 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,13 +18,15 @@ static int a_seen; static int b_seen; +static int q_seen; static const struct option long_options_required[] = { { "alpha", no_argument, NULL, 'a' }, { "beta", no_argument, &b_seen, 1 }, { "prune", required_argument, NULL, 'p' }, - { "quetsche", required_argument, NULL, 'q' }, + { "quetsche", required_argument, &q_seen, 1 }, + { "xtremely-",no_argument, NULL, 1003 }, { "xtra", no_argument, NULL, 1001 }, { "xtreme", no_argument, NULL, 1002 }, { "xtremely", no_argument, NULL, 1003 }, @@ -36,54 +38,63 @@ static const struct option long_options_optional[] = { "alpha", no_argument, NULL, 'a' }, { "beta", no_argument, &b_seen, 1 }, { "prune", optional_argument, NULL, 'p' }, - { "quetsche", optional_argument, NULL, 'q' }, + { "quetsche", optional_argument, &q_seen, 1 }, { NULL, 0, NULL, 0 } }; static void getopt_long_loop (int argc, const char **argv, - const char *options, const struct option *long_options, - const char **p_value, const char **q_value, - int *non_options_count, const char **non_options, - int *unrecognized) + const char *options, const struct option *long_options, + const char **p_value, const char **q_value, + int *non_options_count, const char **non_options, + int *unrecognized) { - int option_index; + int option_index = -1; int c; opterr = 0; + q_seen = 0; while ((c = getopt_long (argc, (char **) argv, options, long_options, - &option_index)) - != -1) + &option_index)) + != -1) { switch (c) - { - case 0: - /* An option with a non-NULL flag pointer was processed. */ - break; - case 'a': - a_seen++; - break; - case 'b': - b_seen = 1; - break; - case 'p': - *p_value = optarg; - break; - case 'q': - *q_value = optarg; - break; - case '\1': - /* Must only happen with option '-' at the beginning. */ - ASSERT (options[0] == '-'); - non_options[(*non_options_count)++] = optarg; - break; - case '?': - *unrecognized = optopt; - break; - default: - *unrecognized = c; - break; - } + { + case 0: + /* An option with a non-NULL flag pointer was processed. */ + if (q_seen) + *q_value = optarg; + break; + case 'a': + a_seen++; + break; + case 'b': + b_seen = 1; + break; + case 'p': + *p_value = optarg; + break; + case 'q': + *q_value = optarg; + break; + case '\1': + /* Must only happen with option '-' at the beginning. */ + ASSERT (options[0] == '-'); + non_options[(*non_options_count)++] = optarg; + break; + case ':': + /* Must only happen with option ':' at the beginning. */ + ASSERT (options[0] == ':' + || ((options[0] == '-' || options[0] == '+') + && options[1] == ':')); + /* fall through */ + case '?': + *unrecognized = optopt; + break; + default: + *unrecognized = c; + break; + } } } @@ -111,6 +122,7 @@ test_getopt_long (void) argv[argc++] = "program"; argv[argc++] = "--x"; + argv[argc] = NULL; optind = 1; opterr = 0; c = do_getopt_long (argc, argv, "ab", long_options_required, &option_index); @@ -125,6 +137,7 @@ test_getopt_long (void) argv[argc++] = "program"; argv[argc++] = "--xt"; + argv[argc] = NULL; optind = 1; opterr = 0; c = do_getopt_long (argc, argv, "ab", long_options_required, &option_index); @@ -139,6 +152,7 @@ test_getopt_long (void) argv[argc++] = "program"; argv[argc++] = "--xtr"; + argv[argc] = NULL; optind = 1; opterr = 0; c = do_getopt_long (argc, argv, "ab", long_options_required, &option_index); @@ -153,6 +167,7 @@ test_getopt_long (void) argv[argc++] = "program"; argv[argc++] = "--xtra"; + argv[argc] = NULL; optind = 1; opterr = 0; c = do_getopt_long (argc, argv, "ab", long_options_required, &option_index); @@ -166,6 +181,7 @@ test_getopt_long (void) argv[argc++] = "program"; argv[argc++] = "--xtre"; + argv[argc] = NULL; optind = 1; opterr = 0; c = do_getopt_long (argc, argv, "ab", long_options_required, &option_index); @@ -180,6 +196,7 @@ test_getopt_long (void) argv[argc++] = "program"; argv[argc++] = "--xtrem"; + argv[argc] = NULL; optind = 1; opterr = 0; c = do_getopt_long (argc, argv, "ab", long_options_required, &option_index); @@ -194,6 +211,7 @@ test_getopt_long (void) argv[argc++] = "program"; argv[argc++] = "--xtreme"; + argv[argc] = NULL; optind = 1; opterr = 0; c = do_getopt_long (argc, argv, "ab", long_options_required, &option_index); @@ -207,6 +225,7 @@ test_getopt_long (void) argv[argc++] = "program"; argv[argc++] = "--xtremel"; + argv[argc] = NULL; optind = 1; opterr = 0; c = do_getopt_long (argc, argv, "ab", long_options_required, &option_index); @@ -220,14 +239,102 @@ test_getopt_long (void) argv[argc++] = "program"; argv[argc++] = "--xtremely"; + argv[argc] = NULL; optind = 1; opterr = 0; c = do_getopt_long (argc, argv, "ab", long_options_required, &option_index); ASSERT (c == 1003); } - /* Test processing of boolean options. */ - for (start = OPTIND_MIN; start <= 1; start++) + /* Check that -W handles unknown options. */ + { + int argc = 0; + const char *argv[10]; + int option_index; + int c; + + argv[argc++] = "program"; + argv[argc++] = "-W"; + argv[argc] = NULL; + optind = 1; + opterr = 0; + c = do_getopt_long (argc, argv, "W;", long_options_required, &option_index); + ASSERT (c == '?'); + ASSERT (optopt == 'W'); + } + { + int argc = 0; + const char *argv[10]; + int option_index; + int c; + + argv[argc++] = "program"; + argv[argc++] = "-Wunknown"; + argv[argc] = NULL; + optind = 1; + opterr = 0; + c = do_getopt_long (argc, argv, "W;", long_options_required, &option_index); + /* glibc and BSD behave differently here, but for now, we allow + both behaviors since W support is not frequently used. */ + if (c == '?') + { + ASSERT (optopt == 0); + ASSERT (optarg == NULL); + } + else + { + ASSERT (c == 'W'); + ASSERT (strcmp (optarg, "unknown") == 0); + } + } + { + int argc = 0; + const char *argv[10]; + int option_index; + int c; + + argv[argc++] = "program"; + argv[argc++] = "-W"; + argv[argc++] = "unknown"; + argv[argc] = NULL; + optind = 1; + opterr = 0; + c = do_getopt_long (argc, argv, "W;", long_options_required, &option_index); + /* glibc and BSD behave differently here, but for now, we allow + both behaviors since W support is not frequently used. */ + if (c == '?') + { + ASSERT (optopt == 0); + ASSERT (optarg == NULL); + } + else + { + ASSERT (c == 'W'); + ASSERT (strcmp (optarg, "unknown") == 0); + } + } + + /* Test that 'W' does not dump core: + http://sourceware.org/bugzilla/show_bug.cgi?id=12922 */ + { + int argc = 0; + const char *argv[10]; + int option_index; + int c; + + argv[argc++] = "program"; + argv[argc++] = "-W"; + argv[argc++] = "dummy"; + argv[argc] = NULL; + optind = 1; + opterr = 0; + c = do_getopt_long (argc, argv, "W;", NULL, &option_index); + ASSERT (c == 'W'); + ASSERT (optind == 2); + } + + /* Test processing of boolean short options. */ + for (start = 0; start <= 1; start++) { const char *p_value = NULL; const char *q_value = NULL; @@ -243,10 +350,11 @@ test_getopt_long (void) argv[argc++] = "-a"; argv[argc++] = "foo"; argv[argc++] = "bar"; + argv[argc] = NULL; optind = start; getopt_long_loop (argc, argv, "ab", long_options_required, - &p_value, &q_value, - &non_options_count, non_options, &unrecognized); + &p_value, &q_value, + &non_options_count, non_options, &unrecognized); ASSERT (a_seen == 1); ASSERT (b_seen == 0); ASSERT (p_value == NULL); @@ -255,7 +363,7 @@ test_getopt_long (void) ASSERT (unrecognized == 0); ASSERT (optind == 2); } - for (start = OPTIND_MIN; start <= 1; start++) + for (start = 0; start <= 1; start++) { const char *p_value = NULL; const char *q_value = NULL; @@ -272,10 +380,11 @@ test_getopt_long (void) argv[argc++] = "-a"; argv[argc++] = "foo"; argv[argc++] = "bar"; + argv[argc] = NULL; optind = start; getopt_long_loop (argc, argv, "ab", long_options_required, - &p_value, &q_value, - &non_options_count, non_options, &unrecognized); + &p_value, &q_value, + &non_options_count, non_options, &unrecognized); ASSERT (a_seen == 1); ASSERT (b_seen == 1); ASSERT (p_value == NULL); @@ -284,7 +393,7 @@ test_getopt_long (void) ASSERT (unrecognized == 0); ASSERT (optind == 3); } - for (start = OPTIND_MIN; start <= 1; start++) + for (start = 0; start <= 1; start++) { const char *p_value = NULL; const char *q_value = NULL; @@ -300,10 +409,11 @@ test_getopt_long (void) argv[argc++] = "-ba"; argv[argc++] = "foo"; argv[argc++] = "bar"; + argv[argc] = NULL; optind = start; getopt_long_loop (argc, argv, "ab", long_options_required, - &p_value, &q_value, - &non_options_count, non_options, &unrecognized); + &p_value, &q_value, + &non_options_count, non_options, &unrecognized); ASSERT (a_seen == 1); ASSERT (b_seen == 1); ASSERT (p_value == NULL); @@ -312,7 +422,7 @@ test_getopt_long (void) ASSERT (unrecognized == 0); ASSERT (optind == 2); } - for (start = OPTIND_MIN; start <= 1; start++) + for (start = 0; start <= 1; start++) { const char *p_value = NULL; const char *q_value = NULL; @@ -329,10 +439,11 @@ test_getopt_long (void) argv[argc++] = "-a"; argv[argc++] = "foo"; argv[argc++] = "bar"; + argv[argc] = NULL; optind = start; getopt_long_loop (argc, argv, "ab", long_options_required, - &p_value, &q_value, - &non_options_count, non_options, &unrecognized); + &p_value, &q_value, + &non_options_count, non_options, &unrecognized); ASSERT (a_seen == 2); ASSERT (b_seen == 1); ASSERT (p_value == NULL); @@ -342,8 +453,196 @@ test_getopt_long (void) ASSERT (optind == 3); } - /* Test processing of options with arguments. */ - for (start = OPTIND_MIN; start <= 1; start++) + /* Test processing of boolean long options. */ + for (start = 0; start <= 1; start++) + { + const char *p_value = NULL; + const char *q_value = NULL; + int non_options_count = 0; + const char *non_options[10]; + int unrecognized = 0; + int argc = 0; + const char *argv[10]; + a_seen = 0; + b_seen = 0; + + argv[argc++] = "program"; + argv[argc++] = "--alpha"; + argv[argc++] = "foo"; + argv[argc++] = "bar"; + argv[argc] = NULL; + optind = start; + getopt_long_loop (argc, argv, "ab", long_options_required, + &p_value, &q_value, + &non_options_count, non_options, &unrecognized); + ASSERT (a_seen == 1); + ASSERT (b_seen == 0); + ASSERT (p_value == NULL); + ASSERT (q_value == NULL); + ASSERT (non_options_count == 0); + ASSERT (unrecognized == 0); + ASSERT (optind == 2); + } + for (start = 0; start <= 1; start++) + { + const char *p_value = NULL; + const char *q_value = NULL; + int non_options_count = 0; + const char *non_options[10]; + int unrecognized = 0; + int argc = 0; + const char *argv[10]; + a_seen = 0; + b_seen = 0; + + argv[argc++] = "program"; + argv[argc++] = "--beta"; + argv[argc++] = "--alpha"; + argv[argc++] = "foo"; + argv[argc++] = "bar"; + argv[argc] = NULL; + optind = start; + getopt_long_loop (argc, argv, "ab", long_options_required, + &p_value, &q_value, + &non_options_count, non_options, &unrecognized); + ASSERT (a_seen == 1); + ASSERT (b_seen == 1); + ASSERT (p_value == NULL); + ASSERT (q_value == NULL); + ASSERT (non_options_count == 0); + ASSERT (unrecognized == 0); + ASSERT (optind == 3); + } + for (start = 0; start <= 1; start++) + { + const char *p_value = NULL; + const char *q_value = NULL; + int non_options_count = 0; + const char *non_options[10]; + int unrecognized = 0; + int argc = 0; + const char *argv[10]; + a_seen = 0; + b_seen = 0; + + argv[argc++] = "program"; + argv[argc++] = "--alpha"; + argv[argc++] = "--beta"; + argv[argc++] = "--alpha"; + argv[argc++] = "--beta"; + argv[argc++] = "foo"; + argv[argc++] = "bar"; + argv[argc] = NULL; + optind = start; + getopt_long_loop (argc, argv, "ab", long_options_required, + &p_value, &q_value, + &non_options_count, non_options, &unrecognized); + ASSERT (a_seen == 2); + ASSERT (b_seen == 1); + ASSERT (p_value == NULL); + ASSERT (q_value == NULL); + ASSERT (non_options_count == 0); + ASSERT (unrecognized == 0); + ASSERT (optind == 5); + } + + /* Test processing of boolean long options via -W. */ + for (start = 0; start <= 1; start++) + { + const char *p_value = NULL; + const char *q_value = NULL; + int non_options_count = 0; + const char *non_options[10]; + int unrecognized = 0; + int argc = 0; + const char *argv[10]; + a_seen = 0; + b_seen = 0; + + argv[argc++] = "program"; + argv[argc++] = "-Walpha"; + argv[argc++] = "foo"; + argv[argc++] = "bar"; + argv[argc] = NULL; + optind = start; + getopt_long_loop (argc, argv, "abW;", long_options_required, + &p_value, &q_value, + &non_options_count, non_options, &unrecognized); + ASSERT (a_seen == 1); + ASSERT (b_seen == 0); + ASSERT (p_value == NULL); + ASSERT (q_value == NULL); + ASSERT (non_options_count == 0); + ASSERT (unrecognized == 0); + ASSERT (optind == 2); + } + for (start = 0; start <= 1; start++) + { + const char *p_value = NULL; + const char *q_value = NULL; + int non_options_count = 0; + const char *non_options[10]; + int unrecognized = 0; + int argc = 0; + const char *argv[10]; + a_seen = 0; + b_seen = 0; + + argv[argc++] = "program"; + argv[argc++] = "-W"; + argv[argc++] = "beta"; + argv[argc++] = "-W"; + argv[argc++] = "alpha"; + argv[argc++] = "foo"; + argv[argc++] = "bar"; + argv[argc] = NULL; + optind = start; + getopt_long_loop (argc, argv, "aW;b", long_options_required, + &p_value, &q_value, + &non_options_count, non_options, &unrecognized); + ASSERT (a_seen == 1); + ASSERT (b_seen == 1); + ASSERT (p_value == NULL); + ASSERT (q_value == NULL); + ASSERT (non_options_count == 0); + ASSERT (unrecognized == 0); + ASSERT (optind == 5); + } + for (start = 0; start <= 1; start++) + { + const char *p_value = NULL; + const char *q_value = NULL; + int non_options_count = 0; + const char *non_options[10]; + int unrecognized = 0; + int argc = 0; + const char *argv[10]; + a_seen = 0; + b_seen = 0; + + argv[argc++] = "program"; + argv[argc++] = "-Walpha"; + argv[argc++] = "-Wbeta"; + argv[argc++] = "-Walpha"; + argv[argc++] = "-Wbeta"; + argv[argc++] = "foo"; + argv[argc++] = "bar"; + argv[argc] = NULL; + optind = start; + getopt_long_loop (argc, argv, "W;ab", long_options_required, + &p_value, &q_value, + &non_options_count, non_options, &unrecognized); + ASSERT (a_seen == 2); + ASSERT (b_seen == 1); + ASSERT (p_value == NULL); + ASSERT (q_value == NULL); + ASSERT (non_options_count == 0); + ASSERT (unrecognized == 0); + ASSERT (optind == 5); + } + + /* Test processing of short options with arguments. */ + for (start = 0; start <= 1; start++) { const char *p_value = NULL; const char *q_value = NULL; @@ -358,10 +657,11 @@ test_getopt_long (void) argv[argc++] = "program"; argv[argc++] = "-pfoo"; argv[argc++] = "bar"; + argv[argc] = NULL; optind = start; getopt_long_loop (argc, argv, "p:q:", long_options_required, - &p_value, &q_value, - &non_options_count, non_options, &unrecognized); + &p_value, &q_value, + &non_options_count, non_options, &unrecognized); ASSERT (a_seen == 0); ASSERT (b_seen == 0); ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0); @@ -370,7 +670,7 @@ test_getopt_long (void) ASSERT (unrecognized == 0); ASSERT (optind == 2); } - for (start = OPTIND_MIN; start <= 1; start++) + for (start = 0; start <= 1; start++) { const char *p_value = NULL; const char *q_value = NULL; @@ -386,10 +686,11 @@ test_getopt_long (void) argv[argc++] = "-p"; argv[argc++] = "foo"; argv[argc++] = "bar"; + argv[argc] = NULL; optind = start; getopt_long_loop (argc, argv, "p:q:", long_options_required, - &p_value, &q_value, - &non_options_count, non_options, &unrecognized); + &p_value, &q_value, + &non_options_count, non_options, &unrecognized); ASSERT (a_seen == 0); ASSERT (b_seen == 0); ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0); @@ -398,7 +699,7 @@ test_getopt_long (void) ASSERT (unrecognized == 0); ASSERT (optind == 3); } - for (start = OPTIND_MIN; start <= 1; start++) + for (start = 0; start <= 1; start++) { const char *p_value = NULL; const char *q_value = NULL; @@ -416,10 +717,11 @@ test_getopt_long (void) argv[argc++] = "baz"; argv[argc++] = "-pfoo"; argv[argc++] = "bar"; + argv[argc] = NULL; optind = start; getopt_long_loop (argc, argv, "abp:q:", long_options_required, - &p_value, &q_value, - &non_options_count, non_options, &unrecognized); + &p_value, &q_value, + &non_options_count, non_options, &unrecognized); ASSERT (a_seen == 1); ASSERT (b_seen == 1); ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0); @@ -429,8 +731,8 @@ test_getopt_long (void) ASSERT (optind == 5); } - /* Test processing of options with optional arguments. */ - for (start = OPTIND_MIN; start <= 1; start++) + /* Test processing of long options with arguments. */ + for (start = 0; start <= 1; start++) { const char *p_value = NULL; const char *q_value = NULL; @@ -443,12 +745,13 @@ test_getopt_long (void) b_seen = 0; argv[argc++] = "program"; - argv[argc++] = "-pfoo"; + argv[argc++] = "--p=foo"; argv[argc++] = "bar"; + argv[argc] = NULL; optind = start; - getopt_long_loop (argc, argv, "p::q::", long_options_optional, - &p_value, &q_value, - &non_options_count, non_options, &unrecognized); + getopt_long_loop (argc, argv, "p:q:", long_options_required, + &p_value, &q_value, + &non_options_count, non_options, &unrecognized); ASSERT (a_seen == 0); ASSERT (b_seen == 0); ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0); @@ -457,7 +760,545 @@ test_getopt_long (void) ASSERT (unrecognized == 0); ASSERT (optind == 2); } - for (start = OPTIND_MIN; start <= 1; start++) + for (start = 0; start <= 1; start++) + { + const char *p_value = NULL; + const char *q_value = NULL; + int non_options_count = 0; + const char *non_options[10]; + int unrecognized = 0; + int argc = 0; + const char *argv[10]; + a_seen = 0; + b_seen = 0; + + argv[argc++] = "program"; + argv[argc++] = "--p"; + argv[argc++] = "foo"; + argv[argc++] = "bar"; + argv[argc] = NULL; + optind = start; + getopt_long_loop (argc, argv, "p:q:", long_options_required, + &p_value, &q_value, + &non_options_count, non_options, &unrecognized); + ASSERT (a_seen == 0); + ASSERT (b_seen == 0); + ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0); + ASSERT (q_value == NULL); + ASSERT (non_options_count == 0); + ASSERT (unrecognized == 0); + ASSERT (optind == 3); + } + for (start = 0; start <= 1; start++) + { + const char *p_value = NULL; + const char *q_value = NULL; + int non_options_count = 0; + const char *non_options[10]; + int unrecognized = 0; + int argc = 0; + const char *argv[10]; + a_seen = 0; + b_seen = 0; + + argv[argc++] = "program"; + argv[argc++] = "-ab"; + argv[argc++] = "--q"; + argv[argc++] = "baz"; + argv[argc++] = "--p=foo"; + argv[argc++] = "bar"; + argv[argc] = NULL; + optind = start; + getopt_long_loop (argc, argv, "abp:q:", long_options_required, + &p_value, &q_value, + &non_options_count, non_options, &unrecognized); + ASSERT (a_seen == 1); + ASSERT (b_seen == 1); + ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0); + ASSERT (q_value != NULL && strcmp (q_value, "baz") == 0); + ASSERT (non_options_count == 0); + ASSERT (unrecognized == 0); + ASSERT (optind == 5); + } + + /* Test processing of long options with arguments via -W. */ + for (start = 0; start <= 1; start++) + { + const char *p_value = NULL; + const char *q_value = NULL; + int non_options_count = 0; + const char *non_options[10]; + int unrecognized = 0; + int argc = 0; + const char *argv[10]; + a_seen = 0; + b_seen = 0; + + argv[argc++] = "program"; + argv[argc++] = "-Wp=foo"; + argv[argc++] = "bar"; + argv[argc] = NULL; + optind = start; + getopt_long_loop (argc, argv, "p:q:W;", long_options_required, + &p_value, &q_value, + &non_options_count, non_options, &unrecognized); + ASSERT (a_seen == 0); + ASSERT (b_seen == 0); + ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0); + ASSERT (q_value == NULL); + ASSERT (non_options_count == 0); + ASSERT (unrecognized == 0); + ASSERT (optind == 2); + } + for (start = 0; start <= 1; start++) + { + const char *p_value = NULL; + const char *q_value = NULL; + int non_options_count = 0; + const char *non_options[10]; + int unrecognized = 0; + int argc = 0; + const char *argv[10]; + a_seen = 0; + b_seen = 0; + + argv[argc++] = "program"; + argv[argc++] = "-W"; + argv[argc++] = "p"; + argv[argc++] = "foo"; + argv[argc++] = "bar"; + argv[argc] = NULL; + optind = start; + getopt_long_loop (argc, argv, "p:W;q:", long_options_required, + &p_value, &q_value, + &non_options_count, non_options, &unrecognized); + ASSERT (a_seen == 0); + ASSERT (b_seen == 0); + ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0); + ASSERT (q_value == NULL); + ASSERT (non_options_count == 0); + ASSERT (unrecognized == 0); + ASSERT (optind == 4); + } + for (start = 0; start <= 1; start++) + { + const char *p_value = NULL; + const char *q_value = NULL; + int non_options_count = 0; + const char *non_options[10]; + int unrecognized = 0; + int argc = 0; + const char *argv[10]; + a_seen = 0; + b_seen = 0; + + argv[argc++] = "program"; + argv[argc++] = "-ab"; + argv[argc++] = "-Wq"; + argv[argc++] = "baz"; + argv[argc++] = "-W"; + argv[argc++] = "p=foo"; + argv[argc++] = "bar"; + argv[argc] = NULL; + optind = start; + getopt_long_loop (argc, argv, "W;abp:q:", long_options_required, + &p_value, &q_value, + &non_options_count, non_options, &unrecognized); + ASSERT (a_seen == 1); + ASSERT (b_seen == 1); + ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0); + ASSERT (q_value != NULL && strcmp (q_value, "baz") == 0); + ASSERT (non_options_count == 0); + ASSERT (unrecognized == 0); + ASSERT (optind == 6); + } + + /* Test processing of short options with optional arguments. */ + for (start = 0; start <= 1; start++) + { + const char *p_value = NULL; + const char *q_value = NULL; + int non_options_count = 0; + const char *non_options[10]; + int unrecognized = 0; + int argc = 0; + const char *argv[10]; + a_seen = 0; + b_seen = 0; + + argv[argc++] = "program"; + argv[argc++] = "-pfoo"; + argv[argc++] = "bar"; + argv[argc] = NULL; + optind = start; + getopt_long_loop (argc, argv, "p::q::", long_options_optional, + &p_value, &q_value, + &non_options_count, non_options, &unrecognized); + ASSERT (a_seen == 0); + ASSERT (b_seen == 0); + ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0); + ASSERT (q_value == NULL); + ASSERT (non_options_count == 0); + ASSERT (unrecognized == 0); + ASSERT (optind == 2); + } + for (start = 0; start <= 1; start++) + { + const char *p_value = NULL; + const char *q_value = NULL; + int non_options_count = 0; + const char *non_options[10]; + int unrecognized = 0; + int argc = 0; + const char *argv[10]; + a_seen = 0; + b_seen = 0; + + argv[argc++] = "program"; + argv[argc++] = "-p"; + argv[argc++] = "foo"; + argv[argc++] = "bar"; + argv[argc] = NULL; + optind = start; + getopt_long_loop (argc, argv, "p::q::", long_options_optional, + &p_value, &q_value, + &non_options_count, non_options, &unrecognized); + ASSERT (a_seen == 0); + ASSERT (b_seen == 0); + ASSERT (p_value == NULL); + ASSERT (q_value == NULL); + ASSERT (non_options_count == 0); + ASSERT (unrecognized == 0); + ASSERT (optind == 2); + } + for (start = 0; start <= 1; start++) + { + const char *p_value = NULL; + const char *q_value = NULL; + int non_options_count = 0; + const char *non_options[10]; + int unrecognized = 0; + int argc = 0; + const char *argv[10]; + a_seen = 0; + b_seen = 0; + + argv[argc++] = "program"; + argv[argc++] = "-p"; + argv[argc++] = "-a"; + argv[argc++] = "bar"; + argv[argc] = NULL; + optind = start; + getopt_long_loop (argc, argv, "abp::q::", long_options_optional, + &p_value, &q_value, + &non_options_count, non_options, &unrecognized); + ASSERT (a_seen == 1); + ASSERT (b_seen == 0); + ASSERT (p_value == NULL); + ASSERT (q_value == NULL); + ASSERT (non_options_count == 0); + ASSERT (unrecognized == 0); + ASSERT (optind == 3); + } + + /* Test processing of long options with optional arguments. */ + for (start = 0; start <= 1; start++) + { + const char *p_value = NULL; + const char *q_value = NULL; + int non_options_count = 0; + const char *non_options[10]; + int unrecognized = 0; + int argc = 0; + const char *argv[10]; + a_seen = 0; + b_seen = 0; + + argv[argc++] = "program"; + argv[argc++] = "--p=foo"; + argv[argc++] = "bar"; + argv[argc] = NULL; + optind = start; + getopt_long_loop (argc, argv, "p::q::", long_options_optional, + &p_value, &q_value, + &non_options_count, non_options, &unrecognized); + ASSERT (a_seen == 0); + ASSERT (b_seen == 0); + ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0); + ASSERT (q_value == NULL); + ASSERT (non_options_count == 0); + ASSERT (unrecognized == 0); + ASSERT (optind == 2); + } + for (start = 0; start <= 1; start++) + { + const char *p_value = NULL; + const char *q_value = NULL; + int non_options_count = 0; + const char *non_options[10]; + int unrecognized = 0; + int argc = 0; + const char *argv[10]; + a_seen = 0; + b_seen = 0; + + argv[argc++] = "program"; + argv[argc++] = "--p"; + argv[argc++] = "foo"; + argv[argc++] = "bar"; + argv[argc] = NULL; + optind = start; + getopt_long_loop (argc, argv, "p::q::", long_options_optional, + &p_value, &q_value, + &non_options_count, non_options, &unrecognized); + ASSERT (a_seen == 0); + ASSERT (b_seen == 0); + ASSERT (p_value == NULL); + ASSERT (q_value == NULL); + ASSERT (non_options_count == 0); + ASSERT (unrecognized == 0); + ASSERT (optind == 2); + } + for (start = 0; start <= 1; start++) + { + const char *p_value = NULL; + const char *q_value = NULL; + int non_options_count = 0; + const char *non_options[10]; + int unrecognized = 0; + int argc = 0; + const char *argv[10]; + a_seen = 0; + b_seen = 0; + + argv[argc++] = "program"; + argv[argc++] = "--p="; + argv[argc++] = "foo"; + argv[argc++] = "bar"; + argv[argc] = NULL; + optind = start; + getopt_long_loop (argc, argv, "p::q::", long_options_optional, + &p_value, &q_value, + &non_options_count, non_options, &unrecognized); + ASSERT (a_seen == 0); + ASSERT (b_seen == 0); + ASSERT (p_value != NULL && *p_value == '\0'); + ASSERT (q_value == NULL); + ASSERT (non_options_count == 0); + ASSERT (unrecognized == 0); + ASSERT (optind == 2); + } + for (start = 0; start <= 1; start++) + { + const char *p_value = NULL; + const char *q_value = NULL; + int non_options_count = 0; + const char *non_options[10]; + int unrecognized = 0; + int argc = 0; + const char *argv[10]; + a_seen = 0; + b_seen = 0; + + argv[argc++] = "program"; + argv[argc++] = "--p"; + argv[argc++] = "-a"; + argv[argc++] = "bar"; + argv[argc] = NULL; + optind = start; + getopt_long_loop (argc, argv, "abp::q::", long_options_optional, + &p_value, &q_value, + &non_options_count, non_options, &unrecognized); + ASSERT (a_seen == 1); + ASSERT (b_seen == 0); + ASSERT (p_value == NULL); + ASSERT (q_value == NULL); + ASSERT (non_options_count == 0); + ASSERT (unrecognized == 0); + ASSERT (optind == 3); + } + + /* Test processing of long options with optional arguments via -W. */ + for (start = 0; start <= 1; start++) + { + const char *p_value = NULL; + const char *q_value = NULL; + int non_options_count = 0; + const char *non_options[10]; + int unrecognized = 0; + int argc = 0; + const char *argv[10]; + a_seen = 0; + b_seen = 0; + + argv[argc++] = "program"; + argv[argc++] = "-Wp=foo"; + argv[argc++] = "bar"; + argv[argc] = NULL; + optind = start; + getopt_long_loop (argc, argv, "p::q::W;", long_options_optional, + &p_value, &q_value, + &non_options_count, non_options, &unrecognized); + ASSERT (a_seen == 0); + ASSERT (b_seen == 0); + ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0); + ASSERT (q_value == NULL); + ASSERT (non_options_count == 0); + ASSERT (unrecognized == 0); + ASSERT (optind == 2); + } + for (start = 0; start <= 1; start++) + { + const char *p_value = NULL; + const char *q_value = NULL; + int non_options_count = 0; + const char *non_options[10]; + int unrecognized = 0; + int argc = 0; + const char *argv[10]; + a_seen = 0; + b_seen = 0; + + argv[argc++] = "program"; + argv[argc++] = "-Wp"; + argv[argc++] = "foo"; + argv[argc++] = "bar"; + argv[argc] = NULL; + optind = start; + getopt_long_loop (argc, argv, "p::q::W;", long_options_optional, + &p_value, &q_value, + &non_options_count, non_options, &unrecognized); + ASSERT (a_seen == 0); + ASSERT (b_seen == 0); + ASSERT (p_value == NULL); + ASSERT (q_value == NULL); + ASSERT (non_options_count == 0); + ASSERT (unrecognized == 0); + ASSERT (optind == 2); + } + for (start = 0; start <= 1; start++) + { + const char *p_value = NULL; + const char *q_value = NULL; + int non_options_count = 0; + const char *non_options[10]; + int unrecognized = 0; + int argc = 0; + const char *argv[10]; + a_seen = 0; + b_seen = 0; + + argv[argc++] = "program"; + argv[argc++] = "-Wp="; + argv[argc++] = "foo"; + argv[argc++] = "bar"; + argv[argc] = NULL; + optind = start; + getopt_long_loop (argc, argv, "W;p::q::", long_options_optional, + &p_value, &q_value, + &non_options_count, non_options, &unrecognized); + ASSERT (a_seen == 0); + ASSERT (b_seen == 0); + ASSERT (p_value != NULL && *p_value == '\0'); + ASSERT (q_value == NULL); + ASSERT (non_options_count == 0); + ASSERT (unrecognized == 0); + ASSERT (optind == 2); + } + for (start = 0; start <= 1; start++) + { + const char *p_value = NULL; + const char *q_value = NULL; + int non_options_count = 0; + const char *non_options[10]; + int unrecognized = 0; + int argc = 0; + const char *argv[10]; + a_seen = 0; + b_seen = 0; + + argv[argc++] = "program"; + argv[argc++] = "-W"; + argv[argc++] = "p="; + argv[argc++] = "foo"; + argv[argc++] = "bar"; + argv[argc] = NULL; + optind = start; + getopt_long_loop (argc, argv, "W;p::q::", long_options_optional, + &p_value, &q_value, + &non_options_count, non_options, &unrecognized); + ASSERT (a_seen == 0); + ASSERT (b_seen == 0); + ASSERT (p_value != NULL && *p_value == '\0'); + ASSERT (q_value == NULL); + ASSERT (non_options_count == 0); + ASSERT (unrecognized == 0); + ASSERT (optind == 3); + } + for (start = 0; start <= 1; start++) + { + const char *p_value = NULL; + const char *q_value = NULL; + int non_options_count = 0; + const char *non_options[10]; + int unrecognized = 0; + int argc = 0; + const char *argv[10]; + a_seen = 0; + b_seen = 0; + + argv[argc++] = "program"; + argv[argc++] = "-W"; + argv[argc++] = "p"; + argv[argc++] = "-a"; + argv[argc++] = "bar"; + argv[argc] = NULL; + optind = start; + getopt_long_loop (argc, argv, "W;abp::q::", long_options_optional, + &p_value, &q_value, + &non_options_count, non_options, &unrecognized); + ASSERT (a_seen == 1); + ASSERT (b_seen == 0); + /* ASSERT (p_value == NULL); */ + ASSERT (q_value == NULL); + ASSERT (non_options_count == 0); + ASSERT (unrecognized == 0); + ASSERT (optind == 4); + } + + /* Check that invalid options are recognized. */ + for (start = 0; start <= 1; start++) + { + const char *p_value = NULL; + const char *q_value = NULL; + int non_options_count = 0; + const char *non_options[10]; + int unrecognized = 0; + int argc = 0; + const char *argv[10]; + a_seen = 0; + b_seen = 0; + + argv[argc++] = "program"; + argv[argc++] = "-p"; + argv[argc++] = "foo"; + argv[argc++] = "-x"; + argv[argc++] = "-a"; + argv[argc++] = "bar"; + argv[argc] = NULL; + optind = start; + getopt_long_loop (argc, argv, "abp:q:", long_options_required, + &p_value, &q_value, + &non_options_count, non_options, &unrecognized); + ASSERT (a_seen == 1); + ASSERT (b_seen == 0); + ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0); + ASSERT (q_value == NULL); + ASSERT (non_options_count == 0); + ASSERT (unrecognized == 'x'); + ASSERT (optind == 5); + } + for (start = 0; start <= 1; start++) { const char *p_value = NULL; const char *q_value = NULL; @@ -472,20 +1313,25 @@ test_getopt_long (void) argv[argc++] = "program"; argv[argc++] = "-p"; argv[argc++] = "foo"; + argv[argc++] = "-:"; + argv[argc++] = "-a"; argv[argc++] = "bar"; + argv[argc] = NULL; optind = start; - getopt_long_loop (argc, argv, "p::q::", long_options_optional, - &p_value, &q_value, - &non_options_count, non_options, &unrecognized); - ASSERT (a_seen == 0); + getopt_long_loop (argc, argv, "abp:q:", long_options_required, + &p_value, &q_value, + &non_options_count, non_options, &unrecognized); + ASSERT (a_seen == 1); ASSERT (b_seen == 0); - ASSERT (p_value == NULL); + ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0); ASSERT (q_value == NULL); ASSERT (non_options_count == 0); - ASSERT (unrecognized == 0); - ASSERT (optind == 2); + ASSERT (unrecognized == ':'); + ASSERT (optind == 5); } - for (start = OPTIND_MIN; start <= 1; start++) + + /* Check that unexpected arguments are recognized. */ + for (start = 0; start <= 1; start++) { const char *p_value = NULL; const char *q_value = NULL; @@ -499,23 +1345,23 @@ test_getopt_long (void) argv[argc++] = "program"; argv[argc++] = "-p"; - argv[argc++] = "-a"; + argv[argc++] = "foo"; + argv[argc++] = "--a="; argv[argc++] = "bar"; + argv[argc] = NULL; optind = start; - getopt_long_loop (argc, argv, "abp::q::", long_options_optional, - &p_value, &q_value, - &non_options_count, non_options, &unrecognized); - ASSERT (a_seen == 1); + getopt_long_loop (argc, argv, "abp:q:", long_options_required, + &p_value, &q_value, + &non_options_count, non_options, &unrecognized); + ASSERT (a_seen == 0); ASSERT (b_seen == 0); - ASSERT (p_value == NULL); + ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0); ASSERT (q_value == NULL); ASSERT (non_options_count == 0); - ASSERT (unrecognized == 0); - ASSERT (optind == 3); + ASSERT (unrecognized == 'a'); + ASSERT (optind == 4); } - - /* Check that invalid options are recognized. */ - for (start = OPTIND_MIN; start <= 1; start++) + for (start = 0; start <= 1; start++) { const char *p_value = NULL; const char *q_value = NULL; @@ -530,24 +1376,26 @@ test_getopt_long (void) argv[argc++] = "program"; argv[argc++] = "-p"; argv[argc++] = "foo"; - argv[argc++] = "-x"; - argv[argc++] = "-a"; + argv[argc++] = "--b="; argv[argc++] = "bar"; + argv[argc] = NULL; optind = start; getopt_long_loop (argc, argv, "abp:q:", long_options_required, - &p_value, &q_value, - &non_options_count, non_options, &unrecognized); - ASSERT (a_seen == 1); + &p_value, &q_value, + &non_options_count, non_options, &unrecognized); + ASSERT (a_seen == 0); ASSERT (b_seen == 0); ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0); ASSERT (q_value == NULL); ASSERT (non_options_count == 0); - ASSERT (unrecognized == 'x'); - ASSERT (optind == 5); + /* When flag is non-zero, glibc sets optopt anyway, but BSD + leaves optopt unchanged. */ + ASSERT (unrecognized == 1 || unrecognized == 0); + ASSERT (optind == 4); } /* Check that by default, non-options arguments are moved to the end. */ - for (start = OPTIND_MIN; start <= 1; start++) + for (start = 0; start <= 1; start++) { const char *p_value = NULL; const char *q_value = NULL; @@ -566,10 +1414,11 @@ test_getopt_long (void) argv[argc++] = "duck"; argv[argc++] = "-a"; argv[argc++] = "bar"; + argv[argc] = NULL; optind = start; getopt_long_loop (argc, argv, "abp:q:", long_options_required, - &p_value, &q_value, - &non_options_count, non_options, &unrecognized); + &p_value, &q_value, + &non_options_count, non_options, &unrecognized); ASSERT (strcmp (argv[0], "program") == 0); ASSERT (strcmp (argv[1], "-p") == 0); ASSERT (strcmp (argv[2], "billy") == 0); @@ -577,6 +1426,7 @@ test_getopt_long (void) ASSERT (strcmp (argv[4], "donald") == 0); ASSERT (strcmp (argv[5], "duck") == 0); ASSERT (strcmp (argv[6], "bar") == 0); + ASSERT (argv[7] == NULL); ASSERT (a_seen == 1); ASSERT (b_seen == 0); ASSERT (p_value != NULL && strcmp (p_value, "billy") == 0); @@ -587,7 +1437,7 @@ test_getopt_long (void) } /* Check that '--' ends the argument processing. */ - for (start = OPTIND_MIN; start <= 1; start++) + for (start = 0; start <= 1; start++) { const char *p_value = NULL; const char *q_value = NULL; @@ -611,10 +1461,11 @@ test_getopt_long (void) argv[argc++] = "-q"; argv[argc++] = "johnny"; argv[argc++] = "bar"; + argv[argc] = NULL; optind = start; getopt_long_loop (argc, argv, "abp:q:", long_options_required, - &p_value, &q_value, - &non_options_count, non_options, &unrecognized); + &p_value, &q_value, + &non_options_count, non_options, &unrecognized); ASSERT (strcmp (argv[0], "program") == 0); ASSERT (strcmp (argv[1], "-p") == 0); ASSERT (strcmp (argv[2], "billy") == 0); @@ -627,6 +1478,7 @@ test_getopt_long (void) ASSERT (strcmp (argv[9], "-q") == 0); ASSERT (strcmp (argv[10], "johnny") == 0); ASSERT (strcmp (argv[11], "bar") == 0); + ASSERT (argv[12] == NULL); ASSERT (a_seen == 1); ASSERT (b_seen == 0); ASSERT (p_value != NULL && strcmp (p_value, "billy") == 0); @@ -637,7 +1489,7 @@ test_getopt_long (void) } /* Check that the '-' flag causes non-options to be returned in order. */ - for (start = OPTIND_MIN; start <= 1; start++) + for (start = 0; start <= 1; start++) { const char *p_value = NULL; const char *q_value = NULL; @@ -656,10 +1508,11 @@ test_getopt_long (void) argv[argc++] = "duck"; argv[argc++] = "-a"; argv[argc++] = "bar"; + argv[argc] = NULL; optind = start; getopt_long_loop (argc, argv, "-abp:q:", long_options_required, - &p_value, &q_value, - &non_options_count, non_options, &unrecognized); + &p_value, &q_value, + &non_options_count, non_options, &unrecognized); ASSERT (strcmp (argv[0], "program") == 0); ASSERT (strcmp (argv[1], "donald") == 0); ASSERT (strcmp (argv[2], "-p") == 0); @@ -667,6 +1520,7 @@ test_getopt_long (void) ASSERT (strcmp (argv[4], "duck") == 0); ASSERT (strcmp (argv[5], "-a") == 0); ASSERT (strcmp (argv[6], "bar") == 0); + ASSERT (argv[7] == NULL); ASSERT (a_seen == 1); ASSERT (b_seen == 0); ASSERT (p_value != NULL && strcmp (p_value, "billy") == 0); @@ -680,7 +1534,7 @@ test_getopt_long (void) } /* Check that '--' ends the argument processing. */ - for (start = OPTIND_MIN; start <= 1; start++) + for (start = 0; start <= 1; start++) { const char *p_value = NULL; const char *q_value = NULL; @@ -704,10 +1558,11 @@ test_getopt_long (void) argv[argc++] = "-q"; argv[argc++] = "johnny"; argv[argc++] = "bar"; + argv[argc] = NULL; optind = start; getopt_long_loop (argc, argv, "-abp:q:", long_options_required, - &p_value, &q_value, - &non_options_count, non_options, &unrecognized); + &p_value, &q_value, + &non_options_count, non_options, &unrecognized); ASSERT (strcmp (argv[0], "program") == 0); ASSERT (strcmp (argv[1], "donald") == 0); ASSERT (strcmp (argv[2], "-p") == 0); @@ -720,37 +1575,38 @@ test_getopt_long (void) ASSERT (strcmp (argv[9], "-q") == 0); ASSERT (strcmp (argv[10], "johnny") == 0); ASSERT (strcmp (argv[11], "bar") == 0); + ASSERT (argv[12] == NULL); ASSERT (a_seen == 1); ASSERT (b_seen == 0); ASSERT (p_value != NULL && strcmp (p_value, "billy") == 0); ASSERT (q_value == NULL); if (non_options_count == 2) { - /* glibc behaviour. */ - ASSERT (non_options_count == 2); - ASSERT (strcmp (non_options[0], "donald") == 0); - ASSERT (strcmp (non_options[1], "duck") == 0); - ASSERT (unrecognized == 0); - ASSERT (optind == 7); + /* glibc behaviour. */ + ASSERT (non_options_count == 2); + ASSERT (strcmp (non_options[0], "donald") == 0); + ASSERT (strcmp (non_options[1], "duck") == 0); + ASSERT (unrecognized == 0); + ASSERT (optind == 7); } else { - /* Another valid behaviour. */ - ASSERT (non_options_count == 7); - ASSERT (strcmp (non_options[0], "donald") == 0); - ASSERT (strcmp (non_options[1], "duck") == 0); - ASSERT (strcmp (non_options[2], "-b") == 0); - ASSERT (strcmp (non_options[3], "foo") == 0); - ASSERT (strcmp (non_options[4], "-q") == 0); - ASSERT (strcmp (non_options[5], "johnny") == 0); - ASSERT (strcmp (non_options[6], "bar") == 0); - ASSERT (unrecognized == 0); - ASSERT (optind == 12); + /* Another valid behaviour. */ + ASSERT (non_options_count == 7); + ASSERT (strcmp (non_options[0], "donald") == 0); + ASSERT (strcmp (non_options[1], "duck") == 0); + ASSERT (strcmp (non_options[2], "-b") == 0); + ASSERT (strcmp (non_options[3], "foo") == 0); + ASSERT (strcmp (non_options[4], "-q") == 0); + ASSERT (strcmp (non_options[5], "johnny") == 0); + ASSERT (strcmp (non_options[6], "bar") == 0); + ASSERT (unrecognized == 0); + ASSERT (optind == 12); } } /* Check that the '-' flag has to come first. */ - for (start = OPTIND_MIN; start <= 1; start++) + for (start = 0; start <= 1; start++) { const char *p_value = NULL; const char *q_value = NULL; @@ -769,10 +1625,11 @@ test_getopt_long (void) argv[argc++] = "duck"; argv[argc++] = "-a"; argv[argc++] = "bar"; + argv[argc] = NULL; optind = start; getopt_long_loop (argc, argv, "abp:q:-", long_options_required, - &p_value, &q_value, - &non_options_count, non_options, &unrecognized); + &p_value, &q_value, + &non_options_count, non_options, &unrecognized); ASSERT (strcmp (argv[0], "program") == 0); ASSERT (strcmp (argv[1], "-p") == 0); ASSERT (strcmp (argv[2], "billy") == 0); @@ -780,6 +1637,7 @@ test_getopt_long (void) ASSERT (strcmp (argv[4], "donald") == 0); ASSERT (strcmp (argv[5], "duck") == 0); ASSERT (strcmp (argv[6], "bar") == 0); + ASSERT (argv[7] == NULL); ASSERT (a_seen == 1); ASSERT (b_seen == 0); ASSERT (p_value != NULL && strcmp (p_value, "billy") == 0); @@ -791,7 +1649,7 @@ test_getopt_long (void) /* Check that the '+' flag causes the first non-option to terminate the loop. */ - for (start = OPTIND_MIN; start <= 1; start++) + for (start = 0; start <= 1; start++) { const char *p_value = NULL; const char *q_value = NULL; @@ -810,10 +1668,11 @@ test_getopt_long (void) argv[argc++] = "duck"; argv[argc++] = "-a"; argv[argc++] = "bar"; + argv[argc] = NULL; optind = start; getopt_long_loop (argc, argv, "+abp:q:", long_options_required, - &p_value, &q_value, - &non_options_count, non_options, &unrecognized); + &p_value, &q_value, + &non_options_count, non_options, &unrecognized); ASSERT (strcmp (argv[0], "program") == 0); ASSERT (strcmp (argv[1], "donald") == 0); ASSERT (strcmp (argv[2], "-p") == 0); @@ -821,6 +1680,7 @@ test_getopt_long (void) ASSERT (strcmp (argv[4], "duck") == 0); ASSERT (strcmp (argv[5], "-a") == 0); ASSERT (strcmp (argv[6], "bar") == 0); + ASSERT (argv[7] == NULL); ASSERT (a_seen == 0); ASSERT (b_seen == 0); ASSERT (p_value == NULL); @@ -829,7 +1689,7 @@ test_getopt_long (void) ASSERT (unrecognized == 0); ASSERT (optind == 1); } - for (start = OPTIND_MIN; start <= 1; start++) + for (start = 0; start <= 1; start++) { const char *p_value = NULL; const char *q_value = NULL; @@ -843,10 +1703,11 @@ test_getopt_long (void) argv[argc++] = "program"; argv[argc++] = "-+"; + argv[argc] = NULL; optind = start; getopt_long_loop (argc, argv, "+abp:q:", long_options_required, - &p_value, &q_value, - &non_options_count, non_options, &unrecognized); + &p_value, &q_value, + &non_options_count, non_options, &unrecognized); ASSERT (a_seen == 0); ASSERT (b_seen == 0); ASSERT (p_value == NULL); @@ -857,7 +1718,7 @@ test_getopt_long (void) } /* Check that '--' ends the argument processing. */ - for (start = OPTIND_MIN; start <= 1; start++) + for (start = 0; start <= 1; start++) { const char *p_value = NULL; const char *q_value = NULL; @@ -881,10 +1742,11 @@ test_getopt_long (void) argv[argc++] = "-q"; argv[argc++] = "johnny"; argv[argc++] = "bar"; + argv[argc] = NULL; optind = start; getopt_long_loop (argc, argv, "+abp:q:", long_options_required, - &p_value, &q_value, - &non_options_count, non_options, &unrecognized); + &p_value, &q_value, + &non_options_count, non_options, &unrecognized); ASSERT (strcmp (argv[0], "program") == 0); ASSERT (strcmp (argv[1], "donald") == 0); ASSERT (strcmp (argv[2], "-p") == 0); @@ -897,17 +1759,18 @@ test_getopt_long (void) ASSERT (strcmp (argv[9], "-q") == 0); ASSERT (strcmp (argv[10], "johnny") == 0); ASSERT (strcmp (argv[11], "bar") == 0); + ASSERT (argv[12] == NULL); ASSERT (a_seen == 0); ASSERT (b_seen == 0); ASSERT (p_value == NULL); ASSERT (q_value == NULL); ASSERT (non_options_count == 0); ASSERT (unrecognized == 0); - ASSERT (optind = 1); + ASSERT (optind == 1); } /* Check that the '+' flag has to come first. */ - for (start = OPTIND_MIN; start <= 1; start++) + for (start = 0; start <= 1; start++) { const char *p_value = NULL; const char *q_value = NULL; @@ -926,10 +1789,11 @@ test_getopt_long (void) argv[argc++] = "duck"; argv[argc++] = "-a"; argv[argc++] = "bar"; + argv[argc] = NULL; optind = start; getopt_long_loop (argc, argv, "abp:q:+", long_options_required, - &p_value, &q_value, - &non_options_count, non_options, &unrecognized); + &p_value, &q_value, + &non_options_count, non_options, &unrecognized); ASSERT (strcmp (argv[0], "program") == 0); ASSERT (strcmp (argv[1], "-p") == 0); ASSERT (strcmp (argv[2], "billy") == 0); @@ -937,6 +1801,7 @@ test_getopt_long (void) ASSERT (strcmp (argv[4], "donald") == 0); ASSERT (strcmp (argv[5], "duck") == 0); ASSERT (strcmp (argv[6], "bar") == 0); + ASSERT (argv[7] == NULL); ASSERT (a_seen == 1); ASSERT (b_seen == 0); ASSERT (p_value != NULL && strcmp (p_value, "billy") == 0); @@ -954,16 +1819,326 @@ test_getopt_long (void) static void test_getopt_long_posix (void) { - int c = 3; - const char *v[4] = {"test", "-r", "foo", NULL}; - struct option l[] = {{NULL, 0, NULL, 0}}; int start; - int result; - for (start = OPTIND_MIN; start <= 1; start++) + + /* Check that POSIXLY_CORRECT stops parsing the same as leading '+'. */ + for (start = 0; start <= 1; start++) + { + const char *p_value = NULL; + const char *q_value = NULL; + int non_options_count = 0; + const char *non_options[10]; + int unrecognized = 0; + int argc = 0; + const char *argv[10]; + a_seen = 0; + b_seen = 0; + + argv[argc++] = "program"; + argv[argc++] = "donald"; + argv[argc++] = "-p"; + argv[argc++] = "billy"; + argv[argc++] = "duck"; + argv[argc++] = "-a"; + argv[argc++] = "bar"; + argv[argc] = NULL; + optind = start; + getopt_long_loop (argc, argv, "abp:q:", long_options_required, + &p_value, &q_value, + &non_options_count, non_options, &unrecognized); + ASSERT (strcmp (argv[0], "program") == 0); + ASSERT (strcmp (argv[1], "donald") == 0); + ASSERT (strcmp (argv[2], "-p") == 0); + ASSERT (strcmp (argv[3], "billy") == 0); + ASSERT (strcmp (argv[4], "duck") == 0); + ASSERT (strcmp (argv[5], "-a") == 0); + ASSERT (strcmp (argv[6], "bar") == 0); + ASSERT (argv[7] == NULL); + ASSERT (a_seen == 0); + ASSERT (b_seen == 0); + ASSERT (p_value == NULL); + ASSERT (q_value == NULL); + ASSERT (non_options_count == 0); + ASSERT (unrecognized == 0); + ASSERT (optind == 1); + } + + /* Check that POSIXLY_CORRECT doesn't change optional arguments. */ + for (start = 0; start <= 1; start++) + { + const char *p_value = NULL; + const char *q_value = NULL; + int non_options_count = 0; + const char *non_options[10]; + int unrecognized = 0; + int argc = 0; + const char *argv[10]; + a_seen = 0; + b_seen = 0; + + argv[argc++] = "program"; + argv[argc++] = "-p"; + argv[argc++] = "billy"; + argv[argc] = NULL; + optind = start; + getopt_long_loop (argc, argv, "p::", long_options_required, + &p_value, &q_value, + &non_options_count, non_options, &unrecognized); + ASSERT (a_seen == 0); + ASSERT (b_seen == 0); + ASSERT (p_value == NULL); + ASSERT (q_value == NULL); + ASSERT (non_options_count == 0); + ASSERT (unrecognized == 0); + ASSERT (optind == 2); + } + + /* Check that leading - still sees options after non-options. */ + for (start = 0; start <= 1; start++) { + const char *p_value = NULL; + const char *q_value = NULL; + int non_options_count = 0; + const char *non_options[10]; + int unrecognized = 0; + int argc = 0; + const char *argv[10]; + a_seen = 0; + b_seen = 0; + + argv[argc++] = "program"; + argv[argc++] = "-a"; + argv[argc++] = "billy"; + argv[argc++] = "-b"; + argv[argc] = NULL; optind = start; - result = do_getopt_long (c, v, "r::", l, NULL); + getopt_long_loop (argc, argv, "-ab", long_options_required, + &p_value, &q_value, + &non_options_count, non_options, &unrecognized); + ASSERT (a_seen == 1); + ASSERT (b_seen == 1); + ASSERT (p_value == NULL); + ASSERT (q_value == NULL); + ASSERT (non_options_count == 1); + ASSERT (strcmp (non_options[0], "billy") == 0); + ASSERT (unrecognized == 0); + ASSERT (optind == 4); } - ASSERT (result == 'r'); - ASSERT (optarg == NULL); +} + +/* Reduce casting, so we can use string literals elsewhere. + getopt_long_only takes an array of char*, but luckily does not + modify those elements, so we can pass const char*. */ +static int +do_getopt_long_only (int argc, const char **argv, const char *shortopts, + const struct option *longopts, int *longind) +{ + return getopt_long_only (argc, (char **) argv, shortopts, longopts, longind); +} + +static void +test_getopt_long_only (void) +{ + /* Test disambiguation of options. */ + { + int argc = 0; + const char *argv[10]; + int option_index; + int c; + + argv[argc++] = "program"; + argv[argc++] = "-x"; + argv[argc] = NULL; + optind = 1; + opterr = 0; + c = do_getopt_long_only (argc, argv, "ab", long_options_required, + &option_index); + ASSERT (c == '?'); + ASSERT (optopt == 0); + } + { + int argc = 0; + const char *argv[10]; + int option_index; + int c; + + argv[argc++] = "program"; + argv[argc++] = "-x"; + argv[argc] = NULL; + optind = 1; + opterr = 0; + c = do_getopt_long_only (argc, argv, "abx", long_options_required, + &option_index); + ASSERT (c == 'x'); + ASSERT (optopt == 0); + } + { + int argc = 0; + const char *argv[10]; + int option_index; + int c; + + argv[argc++] = "program"; + argv[argc++] = "--x"; + argv[argc] = NULL; + optind = 1; + opterr = 0; + c = do_getopt_long_only (argc, argv, "abx", long_options_required, + &option_index); + ASSERT (c == '?'); + ASSERT (optopt == 0); + } + { + int argc = 0; + const char *argv[10]; + int option_index; + int c; + + argv[argc++] = "program"; + argv[argc++] = "-b"; + argv[argc] = NULL; + optind = 1; + opterr = 0; + b_seen = 0; + c = do_getopt_long_only (argc, argv, "abx", long_options_required, + &option_index); + ASSERT (c == 'b'); + ASSERT (b_seen == 0); + } + { + int argc = 0; + const char *argv[10]; + int option_index; + int c; + + argv[argc++] = "program"; + argv[argc++] = "--b"; + argv[argc] = NULL; + optind = 1; + opterr = 0; + b_seen = 0; + c = do_getopt_long_only (argc, argv, "abx", long_options_required, + &option_index); + ASSERT (c == 0); + ASSERT (b_seen == 1); + } + { + int argc = 0; + const char *argv[10]; + int option_index; + int c; + + argv[argc++] = "program"; + argv[argc++] = "-xt"; + argv[argc] = NULL; + optind = 1; + opterr = 0; + c = do_getopt_long_only (argc, argv, "ab", long_options_required, + &option_index); + ASSERT (c == '?'); + ASSERT (optopt == 0); + } + { + int argc = 0; + const char *argv[10]; + int option_index; + int c; + + argv[argc++] = "program"; + argv[argc++] = "-xt"; + argv[argc] = NULL; + optind = 1; + opterr = 0; + c = do_getopt_long_only (argc, argv, "abx", long_options_required, + &option_index); + ASSERT (c == '?'); + ASSERT (optopt == 0); + } + { + int argc = 0; + const char *argv[10]; + int option_index; + int c; + + argv[argc++] = "program"; + argv[argc++] = "-xtra"; + argv[argc] = NULL; + optind = 1; + opterr = 0; + c = do_getopt_long_only (argc, argv, "ab", long_options_required, + &option_index); + ASSERT (c == 1001); + } + { + int argc = 0; + const char *argv[10]; + int option_index; + int c; + + argv[argc++] = "program"; + argv[argc++] = "-xtreme"; + argv[argc] = NULL; + optind = 1; + opterr = 0; + c = do_getopt_long_only (argc, argv, "abx:", long_options_required, + &option_index); + ASSERT (c == 1002); + } + { + int argc = 0; + const char *argv[10]; + int option_index; + int c; + + argv[argc++] = "program"; + argv[argc++] = "-xtremel"; + argv[argc] = NULL; + optind = 1; + opterr = 0; + c = do_getopt_long_only (argc, argv, "ab", long_options_required, + &option_index); + /* glibc getopt_long_only is intentionally different from + getopt_long when handling a prefix that is common to two + spellings, when both spellings have the same option directives. + BSD getopt_long_only treats both cases the same. */ + ASSERT (c == 1003 || c == '?'); + ASSERT (optind == 2); + } + { + int argc = 0; + const char *argv[10]; + int option_index; + int c; + + argv[argc++] = "program"; + argv[argc++] = "-xtremel"; + argv[argc] = NULL; + optind = 1; + opterr = 0; + c = do_getopt_long_only (argc, argv, "abx::", long_options_required, + &option_index); + /* glibc getopt_long_only is intentionally different from + getopt_long when handling a prefix that is common to two + spellings, when both spellings have the same option directives. + BSD getopt_long_only treats both cases the same. */ + ASSERT (c == 1003 || c == '?'); + ASSERT (optind == 2); + ASSERT (optarg == NULL); + } + { + int argc = 0; + const char *argv[10]; + int option_index; + int c; + + argv[argc++] = "program"; + argv[argc++] = "-xtras"; + argv[argc] = NULL; + optind = 1; + opterr = 0; + c = do_getopt_long_only (argc, argv, "abx::", long_options_required, + &option_index); + ASSERT (c == 'x'); + ASSERT (strcmp (optarg, "tras") == 0); + } }