getopt-gnu: add another test
[gnulib.git] / tests / test-getopt_long.h
1 /* Test of command line argument processing.
2    Copyright (C) 2009 Free Software Foundation, Inc.
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
16
17 /* Written by Bruno Haible <bruno@clisp.org>, 2009.  */
18
19 static int a_seen;
20 static int b_seen;
21
22 static const struct option long_options_required[] =
23   {
24     { "alpha",    no_argument,       NULL, 'a' },
25     { "beta",     no_argument,       &b_seen, 1 },
26     { "prune",    required_argument, NULL, 'p' },
27     { "quetsche", required_argument, NULL, 'q' },
28     { "xtra",     no_argument,       NULL, 1001 },
29     { "xtreme",   no_argument,       NULL, 1002 },
30     { "xtremely", no_argument,       NULL, 1003 },
31     { NULL,       0,                 NULL, 0 }
32   };
33
34 static const struct option long_options_optional[] =
35   {
36     { "alpha",    no_argument,       NULL, 'a' },
37     { "beta",     no_argument,       &b_seen, 1 },
38     { "prune",    optional_argument, NULL, 'p' },
39     { "quetsche", optional_argument, NULL, 'q' },
40     { NULL,       0,                 NULL, 0 }
41   };
42
43 static void
44 getopt_long_loop (int argc, char **argv,
45                   const char *options, const struct option *long_options,
46                   const char **p_value, const char **q_value,
47                   int *non_options_count, const char **non_options,
48                   int *unrecognized)
49 {
50   int option_index;
51   int c;
52
53   opterr = 0;
54   while ((c = getopt_long (argc, argv, options, long_options, &option_index))
55          != -1)
56     {
57       switch (c)
58         {
59         case 0:
60           /* An option with a non-NULL flag pointer was processed.  */
61           break;
62         case 'a':
63           a_seen++;
64           break;
65         case 'b':
66           b_seen = 1;
67           break;
68         case 'p':
69           *p_value = optarg;
70           break;
71         case 'q':
72           *q_value = optarg;
73           break;
74         case '\1':
75           /* Must only happen with option '-' at the beginning.  */
76           ASSERT (options[0] == '-');
77           non_options[(*non_options_count)++] = optarg;
78           break;
79         case '?':
80           *unrecognized = optopt;
81           break;
82         default:
83           *unrecognized = c;
84           break;
85         }
86     }
87 }
88
89 static void
90 test_getopt_long (void)
91 {
92   int start;
93
94   /* Test disambiguation of options.  */
95   {
96     int argc = 0;
97     char *argv[10];
98     int option_index;
99     int c;
100
101     argv[argc++] = "program";
102     argv[argc++] = "--x";
103     optind = 1;
104     opterr = 0;
105     c = getopt_long (argc, argv, "ab", long_options_required, &option_index);
106     ASSERT (c == '?');
107     ASSERT (optopt == 0);
108   }
109   {
110     int argc = 0;
111     char *argv[10];
112     int option_index;
113     int c;
114
115     argv[argc++] = "program";
116     argv[argc++] = "--xt";
117     optind = 1;
118     opterr = 0;
119     c = getopt_long (argc, argv, "ab", long_options_required, &option_index);
120     ASSERT (c == '?');
121     ASSERT (optopt == 0);
122   }
123   {
124     int argc = 0;
125     char *argv[10];
126     int option_index;
127     int c;
128
129     argv[argc++] = "program";
130     argv[argc++] = "--xtr";
131     optind = 1;
132     opterr = 0;
133     c = getopt_long (argc, argv, "ab", long_options_required, &option_index);
134     ASSERT (c == '?');
135     ASSERT (optopt == 0);
136   }
137   {
138     int argc = 0;
139     char *argv[10];
140     int option_index;
141     int c;
142
143     argv[argc++] = "program";
144     argv[argc++] = "--xtra";
145     optind = 1;
146     opterr = 0;
147     c = getopt_long (argc, argv, "ab", long_options_required, &option_index);
148     ASSERT (c == 1001);
149   }
150   {
151     int argc = 0;
152     char *argv[10];
153     int option_index;
154     int c;
155
156     argv[argc++] = "program";
157     argv[argc++] = "--xtre";
158     optind = 1;
159     opterr = 0;
160     c = getopt_long (argc, argv, "ab", long_options_required, &option_index);
161     ASSERT (c == '?');
162     ASSERT (optopt == 0);
163   }
164   {
165     int argc = 0;
166     char *argv[10];
167     int option_index;
168     int c;
169
170     argv[argc++] = "program";
171     argv[argc++] = "--xtrem";
172     optind = 1;
173     opterr = 0;
174     c = getopt_long (argc, argv, "ab", long_options_required, &option_index);
175     ASSERT (c == '?');
176     ASSERT (optopt == 0);
177   }
178   {
179     int argc = 0;
180     char *argv[10];
181     int option_index;
182     int c;
183
184     argv[argc++] = "program";
185     argv[argc++] = "--xtreme";
186     optind = 1;
187     opterr = 0;
188     c = getopt_long (argc, argv, "ab", long_options_required, &option_index);
189     ASSERT (c == 1002);
190   }
191   {
192     int argc = 0;
193     char *argv[10];
194     int option_index;
195     int c;
196
197     argv[argc++] = "program";
198     argv[argc++] = "--xtremel";
199     optind = 1;
200     opterr = 0;
201     c = getopt_long (argc, argv, "ab", long_options_required, &option_index);
202     ASSERT (c == 1003);
203   }
204   {
205     int argc = 0;
206     char *argv[10];
207     int option_index;
208     int c;
209
210     argv[argc++] = "program";
211     argv[argc++] = "--xtremely";
212     optind = 1;
213     opterr = 0;
214     c = getopt_long (argc, argv, "ab", long_options_required, &option_index);
215     ASSERT (c == 1003);
216   }
217
218   /* Test processing of boolean options.  */
219   for (start = OPTIND_MIN; start <= 1; start++)
220     {
221       const char *p_value = NULL;
222       const char *q_value = NULL;
223       int non_options_count = 0;
224       const char *non_options[10];
225       int unrecognized = 0;
226       int argc = 0;
227       char *argv[10];
228       a_seen = 0;
229       b_seen = 0;
230
231       argv[argc++] = "program";
232       argv[argc++] = "-a";
233       argv[argc++] = "foo";
234       argv[argc++] = "bar";
235       optind = start;
236       getopt_long_loop (argc, argv, "ab", long_options_required,
237                         &p_value, &q_value,
238                         &non_options_count, non_options, &unrecognized);
239       ASSERT (a_seen == 1);
240       ASSERT (b_seen == 0);
241       ASSERT (p_value == NULL);
242       ASSERT (q_value == NULL);
243       ASSERT (non_options_count == 0);
244       ASSERT (unrecognized == 0);
245       ASSERT (optind == 2);
246     }
247   for (start = OPTIND_MIN; start <= 1; start++)
248     {
249       const char *p_value = NULL;
250       const char *q_value = NULL;
251       int non_options_count = 0;
252       const char *non_options[10];
253       int unrecognized = 0;
254       int argc = 0;
255       char *argv[10];
256       a_seen = 0;
257       b_seen = 0;
258
259       argv[argc++] = "program";
260       argv[argc++] = "-b";
261       argv[argc++] = "-a";
262       argv[argc++] = "foo";
263       argv[argc++] = "bar";
264       optind = start;
265       getopt_long_loop (argc, argv, "ab", long_options_required,
266                         &p_value, &q_value,
267                         &non_options_count, non_options, &unrecognized);
268       ASSERT (a_seen == 1);
269       ASSERT (b_seen == 1);
270       ASSERT (p_value == NULL);
271       ASSERT (q_value == NULL);
272       ASSERT (non_options_count == 0);
273       ASSERT (unrecognized == 0);
274       ASSERT (optind == 3);
275     }
276   for (start = OPTIND_MIN; start <= 1; start++)
277     {
278       const char *p_value = NULL;
279       const char *q_value = NULL;
280       int non_options_count = 0;
281       const char *non_options[10];
282       int unrecognized = 0;
283       int argc = 0;
284       char *argv[10];
285       a_seen = 0;
286       b_seen = 0;
287
288       argv[argc++] = "program";
289       argv[argc++] = "-ba";
290       argv[argc++] = "foo";
291       argv[argc++] = "bar";
292       optind = start;
293       getopt_long_loop (argc, argv, "ab", long_options_required,
294                         &p_value, &q_value,
295                         &non_options_count, non_options, &unrecognized);
296       ASSERT (a_seen == 1);
297       ASSERT (b_seen == 1);
298       ASSERT (p_value == NULL);
299       ASSERT (q_value == NULL);
300       ASSERT (non_options_count == 0);
301       ASSERT (unrecognized == 0);
302       ASSERT (optind == 2);
303     }
304   for (start = OPTIND_MIN; start <= 1; start++)
305     {
306       const char *p_value = NULL;
307       const char *q_value = NULL;
308       int non_options_count = 0;
309       const char *non_options[10];
310       int unrecognized = 0;
311       int argc = 0;
312       char *argv[10];
313       a_seen = 0;
314       b_seen = 0;
315
316       argv[argc++] = "program";
317       argv[argc++] = "-ab";
318       argv[argc++] = "-a";
319       argv[argc++] = "foo";
320       argv[argc++] = "bar";
321       optind = start;
322       getopt_long_loop (argc, argv, "ab", long_options_required,
323                         &p_value, &q_value,
324                         &non_options_count, non_options, &unrecognized);
325       ASSERT (a_seen == 2);
326       ASSERT (b_seen == 1);
327       ASSERT (p_value == NULL);
328       ASSERT (q_value == NULL);
329       ASSERT (non_options_count == 0);
330       ASSERT (unrecognized == 0);
331       ASSERT (optind == 3);
332     }
333
334   /* Test processing of options with arguments.  */
335   for (start = OPTIND_MIN; start <= 1; start++)
336     {
337       const char *p_value = NULL;
338       const char *q_value = NULL;
339       int non_options_count = 0;
340       const char *non_options[10];
341       int unrecognized = 0;
342       int argc = 0;
343       char *argv[10];
344       a_seen = 0;
345       b_seen = 0;
346
347       argv[argc++] = "program";
348       argv[argc++] = "-pfoo";
349       argv[argc++] = "bar";
350       optind = start;
351       getopt_long_loop (argc, argv, "p:q:", long_options_required,
352                         &p_value, &q_value,
353                         &non_options_count, non_options, &unrecognized);
354       ASSERT (a_seen == 0);
355       ASSERT (b_seen == 0);
356       ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0);
357       ASSERT (q_value == NULL);
358       ASSERT (non_options_count == 0);
359       ASSERT (unrecognized == 0);
360       ASSERT (optind == 2);
361     }
362   for (start = OPTIND_MIN; start <= 1; start++)
363     {
364       const char *p_value = NULL;
365       const char *q_value = NULL;
366       int non_options_count = 0;
367       const char *non_options[10];
368       int unrecognized = 0;
369       int argc = 0;
370       char *argv[10];
371       a_seen = 0;
372       b_seen = 0;
373
374       argv[argc++] = "program";
375       argv[argc++] = "-p";
376       argv[argc++] = "foo";
377       argv[argc++] = "bar";
378       optind = start;
379       getopt_long_loop (argc, argv, "p:q:", long_options_required,
380                         &p_value, &q_value,
381                         &non_options_count, non_options, &unrecognized);
382       ASSERT (a_seen == 0);
383       ASSERT (b_seen == 0);
384       ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0);
385       ASSERT (q_value == NULL);
386       ASSERT (non_options_count == 0);
387       ASSERT (unrecognized == 0);
388       ASSERT (optind == 3);
389     }
390   for (start = OPTIND_MIN; start <= 1; start++)
391     {
392       const char *p_value = NULL;
393       const char *q_value = NULL;
394       int non_options_count = 0;
395       const char *non_options[10];
396       int unrecognized = 0;
397       int argc = 0;
398       char *argv[10];
399       a_seen = 0;
400       b_seen = 0;
401
402       argv[argc++] = "program";
403       argv[argc++] = "-ab";
404       argv[argc++] = "-q";
405       argv[argc++] = "baz";
406       argv[argc++] = "-pfoo";
407       argv[argc++] = "bar";
408       optind = start;
409       getopt_long_loop (argc, argv, "abp:q:", long_options_required,
410                         &p_value, &q_value,
411                         &non_options_count, non_options, &unrecognized);
412       ASSERT (a_seen == 1);
413       ASSERT (b_seen == 1);
414       ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0);
415       ASSERT (q_value != NULL && strcmp (q_value, "baz") == 0);
416       ASSERT (non_options_count == 0);
417       ASSERT (unrecognized == 0);
418       ASSERT (optind == 5);
419     }
420
421   /* Test processing of options with optional arguments.  */
422   for (start = OPTIND_MIN; start <= 1; start++)
423     {
424       const char *p_value = NULL;
425       const char *q_value = NULL;
426       int non_options_count = 0;
427       const char *non_options[10];
428       int unrecognized = 0;
429       int argc = 0;
430       char *argv[10];
431       a_seen = 0;
432       b_seen = 0;
433
434       argv[argc++] = "program";
435       argv[argc++] = "-pfoo";
436       argv[argc++] = "bar";
437       optind = start;
438       getopt_long_loop (argc, argv, "p::q::", long_options_optional,
439                         &p_value, &q_value,
440                         &non_options_count, non_options, &unrecognized);
441       ASSERT (a_seen == 0);
442       ASSERT (b_seen == 0);
443       ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0);
444       ASSERT (q_value == NULL);
445       ASSERT (non_options_count == 0);
446       ASSERT (unrecognized == 0);
447       ASSERT (optind == 2);
448     }
449   for (start = OPTIND_MIN; start <= 1; start++)
450     {
451       const char *p_value = NULL;
452       const char *q_value = NULL;
453       int non_options_count = 0;
454       const char *non_options[10];
455       int unrecognized = 0;
456       int argc = 0;
457       char *argv[10];
458       a_seen = 0;
459       b_seen = 0;
460
461       argv[argc++] = "program";
462       argv[argc++] = "-p";
463       argv[argc++] = "foo";
464       argv[argc++] = "bar";
465       optind = start;
466       getopt_long_loop (argc, argv, "p::q::", long_options_optional,
467                         &p_value, &q_value,
468                         &non_options_count, non_options, &unrecognized);
469       ASSERT (a_seen == 0);
470       ASSERT (b_seen == 0);
471       ASSERT (p_value == NULL);
472       ASSERT (q_value == NULL);
473       ASSERT (non_options_count == 0);
474       ASSERT (unrecognized == 0);
475       ASSERT (optind == 2);
476     }
477   for (start = OPTIND_MIN; start <= 1; start++)
478     {
479       const char *p_value = NULL;
480       const char *q_value = NULL;
481       int non_options_count = 0;
482       const char *non_options[10];
483       int unrecognized = 0;
484       int argc = 0;
485       char *argv[10];
486       a_seen = 0;
487       b_seen = 0;
488
489       argv[argc++] = "program";
490       argv[argc++] = "-p";
491       argv[argc++] = "-a";
492       argv[argc++] = "bar";
493       optind = start;
494       getopt_long_loop (argc, argv, "abp::q::", long_options_optional,
495                         &p_value, &q_value,
496                         &non_options_count, non_options, &unrecognized);
497       ASSERT (a_seen == 1);
498       ASSERT (b_seen == 0);
499       ASSERT (p_value == NULL);
500       ASSERT (q_value == NULL);
501       ASSERT (non_options_count == 0);
502       ASSERT (unrecognized == 0);
503       ASSERT (optind == 3);
504     }
505
506   /* Check that invalid options are recognized.  */
507   for (start = OPTIND_MIN; start <= 1; start++)
508     {
509       const char *p_value = NULL;
510       const char *q_value = NULL;
511       int non_options_count = 0;
512       const char *non_options[10];
513       int unrecognized = 0;
514       int argc = 0;
515       char *argv[10];
516       a_seen = 0;
517       b_seen = 0;
518
519       argv[argc++] = "program";
520       argv[argc++] = "-p";
521       argv[argc++] = "foo";
522       argv[argc++] = "-x";
523       argv[argc++] = "-a";
524       argv[argc++] = "bar";
525       optind = start;
526       getopt_long_loop (argc, argv, "abp:q:", long_options_required,
527                         &p_value, &q_value,
528                         &non_options_count, non_options, &unrecognized);
529       ASSERT (a_seen == 1);
530       ASSERT (b_seen == 0);
531       ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0);
532       ASSERT (q_value == NULL);
533       ASSERT (non_options_count == 0);
534       ASSERT (unrecognized == 'x');
535       ASSERT (optind == 5);
536     }
537
538   /* Check that by default, non-options arguments are moved to the end.  */
539   for (start = OPTIND_MIN; start <= 1; start++)
540     {
541       const char *p_value = NULL;
542       const char *q_value = NULL;
543       int non_options_count = 0;
544       const char *non_options[10];
545       int unrecognized = 0;
546       int argc = 0;
547       char *argv[10];
548       a_seen = 0;
549       b_seen = 0;
550
551       argv[argc++] = "program";
552       argv[argc++] = "donald";
553       argv[argc++] = "-p";
554       argv[argc++] = "billy";
555       argv[argc++] = "duck";
556       argv[argc++] = "-a";
557       argv[argc++] = "bar";
558       optind = start;
559       getopt_long_loop (argc, argv, "abp:q:", long_options_required,
560                         &p_value, &q_value,
561                         &non_options_count, non_options, &unrecognized);
562       ASSERT (strcmp (argv[0], "program") == 0);
563       ASSERT (strcmp (argv[1], "-p") == 0);
564       ASSERT (strcmp (argv[2], "billy") == 0);
565       ASSERT (strcmp (argv[3], "-a") == 0);
566       ASSERT (strcmp (argv[4], "donald") == 0);
567       ASSERT (strcmp (argv[5], "duck") == 0);
568       ASSERT (strcmp (argv[6], "bar") == 0);
569       ASSERT (a_seen == 1);
570       ASSERT (b_seen == 0);
571       ASSERT (p_value != NULL && strcmp (p_value, "billy") == 0);
572       ASSERT (q_value == NULL);
573       ASSERT (non_options_count == 0);
574       ASSERT (unrecognized == 0);
575       ASSERT (optind == 4);
576     }
577
578   /* Check that '--' ends the argument processing.  */
579   for (start = OPTIND_MIN; start <= 1; start++)
580     {
581       const char *p_value = NULL;
582       const char *q_value = NULL;
583       int non_options_count = 0;
584       const char *non_options[10];
585       int unrecognized = 0;
586       int argc = 0;
587       char *argv[20];
588       a_seen = 0;
589       b_seen = 0;
590
591       argv[argc++] = "program";
592       argv[argc++] = "donald";
593       argv[argc++] = "-p";
594       argv[argc++] = "billy";
595       argv[argc++] = "duck";
596       argv[argc++] = "-a";
597       argv[argc++] = "--";
598       argv[argc++] = "-b";
599       argv[argc++] = "foo";
600       argv[argc++] = "-q";
601       argv[argc++] = "johnny";
602       argv[argc++] = "bar";
603       optind = start;
604       getopt_long_loop (argc, argv, "abp:q:", long_options_required,
605                         &p_value, &q_value,
606                         &non_options_count, non_options, &unrecognized);
607       ASSERT (strcmp (argv[0], "program") == 0);
608       ASSERT (strcmp (argv[1], "-p") == 0);
609       ASSERT (strcmp (argv[2], "billy") == 0);
610       ASSERT (strcmp (argv[3], "-a") == 0);
611       ASSERT (strcmp (argv[4], "--") == 0);
612       ASSERT (strcmp (argv[5], "donald") == 0);
613       ASSERT (strcmp (argv[6], "duck") == 0);
614       ASSERT (strcmp (argv[7], "-b") == 0);
615       ASSERT (strcmp (argv[8], "foo") == 0);
616       ASSERT (strcmp (argv[9], "-q") == 0);
617       ASSERT (strcmp (argv[10], "johnny") == 0);
618       ASSERT (strcmp (argv[11], "bar") == 0);
619       ASSERT (a_seen == 1);
620       ASSERT (b_seen == 0);
621       ASSERT (p_value != NULL && strcmp (p_value, "billy") == 0);
622       ASSERT (q_value == NULL);
623       ASSERT (non_options_count == 0);
624       ASSERT (unrecognized == 0);
625       ASSERT (optind == 5);
626     }
627
628   /* Check that the '-' flag causes non-options to be returned in order.  */
629   for (start = OPTIND_MIN; start <= 1; start++)
630     {
631       const char *p_value = NULL;
632       const char *q_value = NULL;
633       int non_options_count = 0;
634       const char *non_options[10];
635       int unrecognized = 0;
636       int argc = 0;
637       char *argv[10];
638       a_seen = 0;
639       b_seen = 0;
640
641       argv[argc++] = "program";
642       argv[argc++] = "donald";
643       argv[argc++] = "-p";
644       argv[argc++] = "billy";
645       argv[argc++] = "duck";
646       argv[argc++] = "-a";
647       argv[argc++] = "bar";
648       optind = start;
649       getopt_long_loop (argc, argv, "-abp:q:", long_options_required,
650                         &p_value, &q_value,
651                         &non_options_count, non_options, &unrecognized);
652       ASSERT (strcmp (argv[0], "program") == 0);
653       ASSERT (strcmp (argv[1], "donald") == 0);
654       ASSERT (strcmp (argv[2], "-p") == 0);
655       ASSERT (strcmp (argv[3], "billy") == 0);
656       ASSERT (strcmp (argv[4], "duck") == 0);
657       ASSERT (strcmp (argv[5], "-a") == 0);
658       ASSERT (strcmp (argv[6], "bar") == 0);
659       ASSERT (a_seen == 1);
660       ASSERT (b_seen == 0);
661       ASSERT (p_value != NULL && strcmp (p_value, "billy") == 0);
662       ASSERT (q_value == NULL);
663       ASSERT (non_options_count == 3);
664       ASSERT (strcmp (non_options[0], "donald") == 0);
665       ASSERT (strcmp (non_options[1], "duck") == 0);
666       ASSERT (strcmp (non_options[2], "bar") == 0);
667       ASSERT (unrecognized == 0);
668       ASSERT (optind == 7);
669     }
670
671   /* Check that '--' ends the argument processing.  */
672   for (start = OPTIND_MIN; start <= 1; start++)
673     {
674       const char *p_value = NULL;
675       const char *q_value = NULL;
676       int non_options_count = 0;
677       const char *non_options[10];
678       int unrecognized = 0;
679       int argc = 0;
680       char *argv[20];
681       a_seen = 0;
682       b_seen = 0;
683
684       argv[argc++] = "program";
685       argv[argc++] = "donald";
686       argv[argc++] = "-p";
687       argv[argc++] = "billy";
688       argv[argc++] = "duck";
689       argv[argc++] = "-a";
690       argv[argc++] = "--";
691       argv[argc++] = "-b";
692       argv[argc++] = "foo";
693       argv[argc++] = "-q";
694       argv[argc++] = "johnny";
695       argv[argc++] = "bar";
696       optind = start;
697       getopt_long_loop (argc, argv, "-abp:q:", long_options_required,
698                         &p_value, &q_value,
699                         &non_options_count, non_options, &unrecognized);
700       ASSERT (strcmp (argv[0], "program") == 0);
701       ASSERT (strcmp (argv[1], "donald") == 0);
702       ASSERT (strcmp (argv[2], "-p") == 0);
703       ASSERT (strcmp (argv[3], "billy") == 0);
704       ASSERT (strcmp (argv[4], "duck") == 0);
705       ASSERT (strcmp (argv[5], "-a") == 0);
706       ASSERT (strcmp (argv[6], "--") == 0);
707       ASSERT (strcmp (argv[7], "-b") == 0);
708       ASSERT (strcmp (argv[8], "foo") == 0);
709       ASSERT (strcmp (argv[9], "-q") == 0);
710       ASSERT (strcmp (argv[10], "johnny") == 0);
711       ASSERT (strcmp (argv[11], "bar") == 0);
712       ASSERT (a_seen == 1);
713       ASSERT (b_seen == 0);
714       ASSERT (p_value != NULL && strcmp (p_value, "billy") == 0);
715       ASSERT (q_value == NULL);
716       if (non_options_count == 2)
717       {
718         /* glibc behaviour.  */
719         ASSERT (non_options_count == 2);
720         ASSERT (strcmp (non_options[0], "donald") == 0);
721         ASSERT (strcmp (non_options[1], "duck") == 0);
722         ASSERT (unrecognized == 0);
723         ASSERT (optind == 7);
724       }
725       else
726       {
727         /* Another valid behaviour.  */
728         ASSERT (non_options_count == 7);
729         ASSERT (strcmp (non_options[0], "donald") == 0);
730         ASSERT (strcmp (non_options[1], "duck") == 0);
731         ASSERT (strcmp (non_options[2], "-b") == 0);
732         ASSERT (strcmp (non_options[3], "foo") == 0);
733         ASSERT (strcmp (non_options[4], "-q") == 0);
734         ASSERT (strcmp (non_options[5], "johnny") == 0);
735         ASSERT (strcmp (non_options[6], "bar") == 0);
736         ASSERT (unrecognized == 0);
737         ASSERT (optind == 12);
738       }
739     }
740
741   /* Check that the '-' flag has to come first.  */
742   for (start = OPTIND_MIN; start <= 1; start++)
743     {
744       const char *p_value = NULL;
745       const char *q_value = NULL;
746       int non_options_count = 0;
747       const char *non_options[10];
748       int unrecognized = 0;
749       int argc = 0;
750       char *argv[10];
751       a_seen = 0;
752       b_seen = 0;
753
754       argv[argc++] = "program";
755       argv[argc++] = "donald";
756       argv[argc++] = "-p";
757       argv[argc++] = "billy";
758       argv[argc++] = "duck";
759       argv[argc++] = "-a";
760       argv[argc++] = "bar";
761       optind = start;
762       getopt_long_loop (argc, argv, "abp:q:-", long_options_required,
763                         &p_value, &q_value,
764                         &non_options_count, non_options, &unrecognized);
765       ASSERT (strcmp (argv[0], "program") == 0);
766       ASSERT (strcmp (argv[1], "-p") == 0);
767       ASSERT (strcmp (argv[2], "billy") == 0);
768       ASSERT (strcmp (argv[3], "-a") == 0);
769       ASSERT (strcmp (argv[4], "donald") == 0);
770       ASSERT (strcmp (argv[5], "duck") == 0);
771       ASSERT (strcmp (argv[6], "bar") == 0);
772       ASSERT (a_seen == 1);
773       ASSERT (b_seen == 0);
774       ASSERT (p_value != NULL && strcmp (p_value, "billy") == 0);
775       ASSERT (q_value == NULL);
776       ASSERT (non_options_count == 0);
777       ASSERT (unrecognized == 0);
778       ASSERT (optind == 4);
779     }
780
781   /* Check that the '+' flag causes the first non-option to terminate the
782      loop.  */
783   for (start = OPTIND_MIN; start <= 1; start++)
784     {
785       const char *p_value = NULL;
786       const char *q_value = NULL;
787       int non_options_count = 0;
788       const char *non_options[10];
789       int unrecognized = 0;
790       int argc = 0;
791       char *argv[10];
792       a_seen = 0;
793       b_seen = 0;
794
795       argv[argc++] = "program";
796       argv[argc++] = "donald";
797       argv[argc++] = "-p";
798       argv[argc++] = "billy";
799       argv[argc++] = "duck";
800       argv[argc++] = "-a";
801       argv[argc++] = "bar";
802       optind = start;
803       getopt_long_loop (argc, argv, "+abp:q:", long_options_required,
804                         &p_value, &q_value,
805                         &non_options_count, non_options, &unrecognized);
806       ASSERT (strcmp (argv[0], "program") == 0);
807       ASSERT (strcmp (argv[1], "donald") == 0);
808       ASSERT (strcmp (argv[2], "-p") == 0);
809       ASSERT (strcmp (argv[3], "billy") == 0);
810       ASSERT (strcmp (argv[4], "duck") == 0);
811       ASSERT (strcmp (argv[5], "-a") == 0);
812       ASSERT (strcmp (argv[6], "bar") == 0);
813       ASSERT (a_seen == 0);
814       ASSERT (b_seen == 0);
815       ASSERT (p_value == NULL);
816       ASSERT (q_value == NULL);
817       ASSERT (non_options_count == 0);
818       ASSERT (unrecognized == 0);
819       ASSERT (optind == 1);
820     }
821   for (start = OPTIND_MIN; start <= 1; start++)
822     {
823       const char *p_value = NULL;
824       const char *q_value = NULL;
825       int non_options_count = 0;
826       const char *non_options[10];
827       int unrecognized = 0;
828       int argc = 0;
829       char *argv[10];
830       a_seen = 0;
831       b_seen = 0;
832
833       argv[argc++] = "program";
834       argv[argc++] = "-+";
835       optind = start;
836       getopt_long_loop (argc, argv, "+abp:q:", long_options_required,
837                         &p_value, &q_value,
838                         &non_options_count, non_options, &unrecognized);
839       ASSERT (a_seen == 0);
840       ASSERT (b_seen == 0);
841       ASSERT (p_value == NULL);
842       ASSERT (q_value == NULL);
843       ASSERT (non_options_count == 0);
844       ASSERT (unrecognized == '+');
845       ASSERT (optind == 2);
846     }
847
848   /* Check that '--' ends the argument processing.  */
849   for (start = OPTIND_MIN; start <= 1; start++)
850     {
851       const char *p_value = NULL;
852       const char *q_value = NULL;
853       int non_options_count = 0;
854       const char *non_options[10];
855       int unrecognized = 0;
856       int argc = 0;
857       char *argv[20];
858       a_seen = 0;
859       b_seen = 0;
860
861       argv[argc++] = "program";
862       argv[argc++] = "donald";
863       argv[argc++] = "-p";
864       argv[argc++] = "billy";
865       argv[argc++] = "duck";
866       argv[argc++] = "-a";
867       argv[argc++] = "--";
868       argv[argc++] = "-b";
869       argv[argc++] = "foo";
870       argv[argc++] = "-q";
871       argv[argc++] = "johnny";
872       argv[argc++] = "bar";
873       optind = start;
874       getopt_long_loop (argc, argv, "+abp:q:", long_options_required,
875                         &p_value, &q_value,
876                         &non_options_count, non_options, &unrecognized);
877       ASSERT (strcmp (argv[0], "program") == 0);
878       ASSERT (strcmp (argv[1], "donald") == 0);
879       ASSERT (strcmp (argv[2], "-p") == 0);
880       ASSERT (strcmp (argv[3], "billy") == 0);
881       ASSERT (strcmp (argv[4], "duck") == 0);
882       ASSERT (strcmp (argv[5], "-a") == 0);
883       ASSERT (strcmp (argv[6], "--") == 0);
884       ASSERT (strcmp (argv[7], "-b") == 0);
885       ASSERT (strcmp (argv[8], "foo") == 0);
886       ASSERT (strcmp (argv[9], "-q") == 0);
887       ASSERT (strcmp (argv[10], "johnny") == 0);
888       ASSERT (strcmp (argv[11], "bar") == 0);
889       ASSERT (a_seen == 0);
890       ASSERT (b_seen == 0);
891       ASSERT (p_value == NULL);
892       ASSERT (q_value == NULL);
893       ASSERT (non_options_count == 0);
894       ASSERT (unrecognized == 0);
895       ASSERT (optind = 1);
896     }
897
898   /* Check that the '+' flag has to come first.  */
899   for (start = OPTIND_MIN; start <= 1; start++)
900     {
901       const char *p_value = NULL;
902       const char *q_value = NULL;
903       int non_options_count = 0;
904       const char *non_options[10];
905       int unrecognized = 0;
906       int argc = 0;
907       char *argv[10];
908       a_seen = 0;
909       b_seen = 0;
910
911       argv[argc++] = "program";
912       argv[argc++] = "donald";
913       argv[argc++] = "-p";
914       argv[argc++] = "billy";
915       argv[argc++] = "duck";
916       argv[argc++] = "-a";
917       argv[argc++] = "bar";
918       optind = start;
919       getopt_long_loop (argc, argv, "abp:q:+", long_options_required,
920                         &p_value, &q_value,
921                         &non_options_count, non_options, &unrecognized);
922       ASSERT (strcmp (argv[0], "program") == 0);
923       ASSERT (strcmp (argv[1], "-p") == 0);
924       ASSERT (strcmp (argv[2], "billy") == 0);
925       ASSERT (strcmp (argv[3], "-a") == 0);
926       ASSERT (strcmp (argv[4], "donald") == 0);
927       ASSERT (strcmp (argv[5], "duck") == 0);
928       ASSERT (strcmp (argv[6], "bar") == 0);
929       ASSERT (a_seen == 1);
930       ASSERT (b_seen == 0);
931       ASSERT (p_value != NULL && strcmp (p_value, "billy") == 0);
932       ASSERT (q_value == NULL);
933       ASSERT (non_options_count == 0);
934       ASSERT (unrecognized == 0);
935       ASSERT (optind == 4);
936     }
937 }
938
939 /* Test behavior of getopt_long when POSIXLY_CORRECT is set in the
940    environment.  Options with optional arguments should not change
941    behavior just because of an environment variable.
942    http://lists.gnu.org/archive/html/bug-m4/2006-09/msg00028.html  */
943 static void
944 test_getopt_long_posix (void)
945 {
946   int c = 3;
947   char *v[4] = {"test", "-r", "foo", NULL};
948   struct option l[] = {{NULL}};
949   int start;
950   int result;
951   for (start = OPTIND_MIN; start <= 1; start++)
952     {
953       optind = start;
954       result = getopt_long (c, v, "r::", l, NULL);
955     }
956   ASSERT (result == 'r');
957   ASSERT (optarg == NULL);
958 }