Merge branch 'upstream' into stable
[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, const 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, (char **) argv, options, long_options,
55                            &option_index))
56          != -1)
57     {
58       switch (c)
59         {
60         case 0:
61           /* An option with a non-NULL flag pointer was processed.  */
62           break;
63         case 'a':
64           a_seen++;
65           break;
66         case 'b':
67           b_seen = 1;
68           break;
69         case 'p':
70           *p_value = optarg;
71           break;
72         case 'q':
73           *q_value = optarg;
74           break;
75         case '\1':
76           /* Must only happen with option '-' at the beginning.  */
77           ASSERT (options[0] == '-');
78           non_options[(*non_options_count)++] = optarg;
79           break;
80         case '?':
81           *unrecognized = optopt;
82           break;
83         default:
84           *unrecognized = c;
85           break;
86         }
87     }
88 }
89
90 /* Reduce casting, so we can use string literals elsewhere.
91    getopt_long takes an array of char*, but luckily does not modify
92    those elements, so we can pass const char*.  */
93 static int
94 do_getopt_long (int argc, const char **argv, const char *shortopts,
95                 const struct option *longopts, int *longind)
96 {
97   return getopt_long (argc, (char **) argv, shortopts, longopts, longind);
98 }
99
100 static void
101 test_getopt_long (void)
102 {
103   int start;
104
105   /* Test disambiguation of options.  */
106   {
107     int argc = 0;
108     const char *argv[10];
109     int option_index;
110     int c;
111
112     argv[argc++] = "program";
113     argv[argc++] = "--x";
114     argv[argc] = NULL;
115     optind = 1;
116     opterr = 0;
117     c = do_getopt_long (argc, argv, "ab", long_options_required, &option_index);
118     ASSERT (c == '?');
119     ASSERT (optopt == 0);
120   }
121   {
122     int argc = 0;
123     const char *argv[10];
124     int option_index;
125     int c;
126
127     argv[argc++] = "program";
128     argv[argc++] = "--xt";
129     argv[argc] = NULL;
130     optind = 1;
131     opterr = 0;
132     c = do_getopt_long (argc, argv, "ab", long_options_required, &option_index);
133     ASSERT (c == '?');
134     ASSERT (optopt == 0);
135   }
136   {
137     int argc = 0;
138     const char *argv[10];
139     int option_index;
140     int c;
141
142     argv[argc++] = "program";
143     argv[argc++] = "--xtr";
144     argv[argc] = NULL;
145     optind = 1;
146     opterr = 0;
147     c = do_getopt_long (argc, argv, "ab", long_options_required, &option_index);
148     ASSERT (c == '?');
149     ASSERT (optopt == 0);
150   }
151   {
152     int argc = 0;
153     const char *argv[10];
154     int option_index;
155     int c;
156
157     argv[argc++] = "program";
158     argv[argc++] = "--xtra";
159     argv[argc] = NULL;
160     optind = 1;
161     opterr = 0;
162     c = do_getopt_long (argc, argv, "ab", long_options_required, &option_index);
163     ASSERT (c == 1001);
164   }
165   {
166     int argc = 0;
167     const char *argv[10];
168     int option_index;
169     int c;
170
171     argv[argc++] = "program";
172     argv[argc++] = "--xtre";
173     argv[argc] = NULL;
174     optind = 1;
175     opterr = 0;
176     c = do_getopt_long (argc, argv, "ab", long_options_required, &option_index);
177     ASSERT (c == '?');
178     ASSERT (optopt == 0);
179   }
180   {
181     int argc = 0;
182     const char *argv[10];
183     int option_index;
184     int c;
185
186     argv[argc++] = "program";
187     argv[argc++] = "--xtrem";
188     argv[argc] = NULL;
189     optind = 1;
190     opterr = 0;
191     c = do_getopt_long (argc, argv, "ab", long_options_required, &option_index);
192     ASSERT (c == '?');
193     ASSERT (optopt == 0);
194   }
195   {
196     int argc = 0;
197     const char *argv[10];
198     int option_index;
199     int c;
200
201     argv[argc++] = "program";
202     argv[argc++] = "--xtreme";
203     argv[argc] = NULL;
204     optind = 1;
205     opterr = 0;
206     c = do_getopt_long (argc, argv, "ab", long_options_required, &option_index);
207     ASSERT (c == 1002);
208   }
209   {
210     int argc = 0;
211     const char *argv[10];
212     int option_index;
213     int c;
214
215     argv[argc++] = "program";
216     argv[argc++] = "--xtremel";
217     argv[argc] = NULL;
218     optind = 1;
219     opterr = 0;
220     c = do_getopt_long (argc, argv, "ab", long_options_required, &option_index);
221     ASSERT (c == 1003);
222   }
223   {
224     int argc = 0;
225     const char *argv[10];
226     int option_index;
227     int c;
228
229     argv[argc++] = "program";
230     argv[argc++] = "--xtremely";
231     argv[argc] = NULL;
232     optind = 1;
233     opterr = 0;
234     c = do_getopt_long (argc, argv, "ab", long_options_required, &option_index);
235     ASSERT (c == 1003);
236   }
237
238   /* Test processing of boolean options.  */
239   for (start = OPTIND_MIN; start <= 1; start++)
240     {
241       const char *p_value = NULL;
242       const char *q_value = NULL;
243       int non_options_count = 0;
244       const char *non_options[10];
245       int unrecognized = 0;
246       int argc = 0;
247       const char *argv[10];
248       a_seen = 0;
249       b_seen = 0;
250
251       argv[argc++] = "program";
252       argv[argc++] = "-a";
253       argv[argc++] = "foo";
254       argv[argc++] = "bar";
255       argv[argc] = NULL;
256       optind = start;
257       getopt_long_loop (argc, argv, "ab", long_options_required,
258                         &p_value, &q_value,
259                         &non_options_count, non_options, &unrecognized);
260       ASSERT (a_seen == 1);
261       ASSERT (b_seen == 0);
262       ASSERT (p_value == NULL);
263       ASSERT (q_value == NULL);
264       ASSERT (non_options_count == 0);
265       ASSERT (unrecognized == 0);
266       ASSERT (optind == 2);
267     }
268   for (start = OPTIND_MIN; start <= 1; start++)
269     {
270       const char *p_value = NULL;
271       const char *q_value = NULL;
272       int non_options_count = 0;
273       const char *non_options[10];
274       int unrecognized = 0;
275       int argc = 0;
276       const char *argv[10];
277       a_seen = 0;
278       b_seen = 0;
279
280       argv[argc++] = "program";
281       argv[argc++] = "-b";
282       argv[argc++] = "-a";
283       argv[argc++] = "foo";
284       argv[argc++] = "bar";
285       argv[argc] = NULL;
286       optind = start;
287       getopt_long_loop (argc, argv, "ab", long_options_required,
288                         &p_value, &q_value,
289                         &non_options_count, non_options, &unrecognized);
290       ASSERT (a_seen == 1);
291       ASSERT (b_seen == 1);
292       ASSERT (p_value == NULL);
293       ASSERT (q_value == NULL);
294       ASSERT (non_options_count == 0);
295       ASSERT (unrecognized == 0);
296       ASSERT (optind == 3);
297     }
298   for (start = OPTIND_MIN; start <= 1; start++)
299     {
300       const char *p_value = NULL;
301       const char *q_value = NULL;
302       int non_options_count = 0;
303       const char *non_options[10];
304       int unrecognized = 0;
305       int argc = 0;
306       const char *argv[10];
307       a_seen = 0;
308       b_seen = 0;
309
310       argv[argc++] = "program";
311       argv[argc++] = "-ba";
312       argv[argc++] = "foo";
313       argv[argc++] = "bar";
314       argv[argc] = NULL;
315       optind = start;
316       getopt_long_loop (argc, argv, "ab", long_options_required,
317                         &p_value, &q_value,
318                         &non_options_count, non_options, &unrecognized);
319       ASSERT (a_seen == 1);
320       ASSERT (b_seen == 1);
321       ASSERT (p_value == NULL);
322       ASSERT (q_value == NULL);
323       ASSERT (non_options_count == 0);
324       ASSERT (unrecognized == 0);
325       ASSERT (optind == 2);
326     }
327   for (start = OPTIND_MIN; start <= 1; start++)
328     {
329       const char *p_value = NULL;
330       const char *q_value = NULL;
331       int non_options_count = 0;
332       const char *non_options[10];
333       int unrecognized = 0;
334       int argc = 0;
335       const char *argv[10];
336       a_seen = 0;
337       b_seen = 0;
338
339       argv[argc++] = "program";
340       argv[argc++] = "-ab";
341       argv[argc++] = "-a";
342       argv[argc++] = "foo";
343       argv[argc++] = "bar";
344       argv[argc] = NULL;
345       optind = start;
346       getopt_long_loop (argc, argv, "ab", long_options_required,
347                         &p_value, &q_value,
348                         &non_options_count, non_options, &unrecognized);
349       ASSERT (a_seen == 2);
350       ASSERT (b_seen == 1);
351       ASSERT (p_value == NULL);
352       ASSERT (q_value == NULL);
353       ASSERT (non_options_count == 0);
354       ASSERT (unrecognized == 0);
355       ASSERT (optind == 3);
356     }
357
358   /* Test processing of options with arguments.  */
359   for (start = OPTIND_MIN; start <= 1; start++)
360     {
361       const char *p_value = NULL;
362       const char *q_value = NULL;
363       int non_options_count = 0;
364       const char *non_options[10];
365       int unrecognized = 0;
366       int argc = 0;
367       const char *argv[10];
368       a_seen = 0;
369       b_seen = 0;
370
371       argv[argc++] = "program";
372       argv[argc++] = "-pfoo";
373       argv[argc++] = "bar";
374       argv[argc] = NULL;
375       optind = start;
376       getopt_long_loop (argc, argv, "p:q:", long_options_required,
377                         &p_value, &q_value,
378                         &non_options_count, non_options, &unrecognized);
379       ASSERT (a_seen == 0);
380       ASSERT (b_seen == 0);
381       ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0);
382       ASSERT (q_value == NULL);
383       ASSERT (non_options_count == 0);
384       ASSERT (unrecognized == 0);
385       ASSERT (optind == 2);
386     }
387   for (start = OPTIND_MIN; start <= 1; start++)
388     {
389       const char *p_value = NULL;
390       const char *q_value = NULL;
391       int non_options_count = 0;
392       const char *non_options[10];
393       int unrecognized = 0;
394       int argc = 0;
395       const char *argv[10];
396       a_seen = 0;
397       b_seen = 0;
398
399       argv[argc++] = "program";
400       argv[argc++] = "-p";
401       argv[argc++] = "foo";
402       argv[argc++] = "bar";
403       argv[argc] = NULL;
404       optind = start;
405       getopt_long_loop (argc, argv, "p:q:", long_options_required,
406                         &p_value, &q_value,
407                         &non_options_count, non_options, &unrecognized);
408       ASSERT (a_seen == 0);
409       ASSERT (b_seen == 0);
410       ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0);
411       ASSERT (q_value == NULL);
412       ASSERT (non_options_count == 0);
413       ASSERT (unrecognized == 0);
414       ASSERT (optind == 3);
415     }
416   for (start = OPTIND_MIN; start <= 1; start++)
417     {
418       const char *p_value = NULL;
419       const char *q_value = NULL;
420       int non_options_count = 0;
421       const char *non_options[10];
422       int unrecognized = 0;
423       int argc = 0;
424       const char *argv[10];
425       a_seen = 0;
426       b_seen = 0;
427
428       argv[argc++] = "program";
429       argv[argc++] = "-ab";
430       argv[argc++] = "-q";
431       argv[argc++] = "baz";
432       argv[argc++] = "-pfoo";
433       argv[argc++] = "bar";
434       argv[argc] = NULL;
435       optind = start;
436       getopt_long_loop (argc, argv, "abp:q:", long_options_required,
437                         &p_value, &q_value,
438                         &non_options_count, non_options, &unrecognized);
439       ASSERT (a_seen == 1);
440       ASSERT (b_seen == 1);
441       ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0);
442       ASSERT (q_value != NULL && strcmp (q_value, "baz") == 0);
443       ASSERT (non_options_count == 0);
444       ASSERT (unrecognized == 0);
445       ASSERT (optind == 5);
446     }
447
448   /* Test processing of options with optional arguments.  */
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       const char *argv[10];
458       a_seen = 0;
459       b_seen = 0;
460
461       argv[argc++] = "program";
462       argv[argc++] = "-pfoo";
463       argv[argc++] = "bar";
464       argv[argc] = NULL;
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 && strcmp (p_value, "foo") == 0);
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       const char *argv[10];
486       a_seen = 0;
487       b_seen = 0;
488
489       argv[argc++] = "program";
490       argv[argc++] = "-p";
491       argv[argc++] = "foo";
492       argv[argc++] = "bar";
493       argv[argc] = NULL;
494       optind = start;
495       getopt_long_loop (argc, argv, "p::q::", long_options_optional,
496                         &p_value, &q_value,
497                         &non_options_count, non_options, &unrecognized);
498       ASSERT (a_seen == 0);
499       ASSERT (b_seen == 0);
500       ASSERT (p_value == NULL);
501       ASSERT (q_value == NULL);
502       ASSERT (non_options_count == 0);
503       ASSERT (unrecognized == 0);
504       ASSERT (optind == 2);
505     }
506   for (start = OPTIND_MIN; start <= 1; start++)
507     {
508       const char *p_value = NULL;
509       const char *q_value = NULL;
510       int non_options_count = 0;
511       const char *non_options[10];
512       int unrecognized = 0;
513       int argc = 0;
514       const char *argv[10];
515       a_seen = 0;
516       b_seen = 0;
517
518       argv[argc++] = "program";
519       argv[argc++] = "-p";
520       argv[argc++] = "-a";
521       argv[argc++] = "bar";
522       argv[argc] = NULL;
523       optind = start;
524       getopt_long_loop (argc, argv, "abp::q::", long_options_optional,
525                         &p_value, &q_value,
526                         &non_options_count, non_options, &unrecognized);
527       ASSERT (a_seen == 1);
528       ASSERT (b_seen == 0);
529       ASSERT (p_value == NULL);
530       ASSERT (q_value == NULL);
531       ASSERT (non_options_count == 0);
532       ASSERT (unrecognized == 0);
533       ASSERT (optind == 3);
534     }
535
536   /* Check that invalid options are recognized.  */
537   for (start = OPTIND_MIN; start <= 1; start++)
538     {
539       const char *p_value = NULL;
540       const char *q_value = NULL;
541       int non_options_count = 0;
542       const char *non_options[10];
543       int unrecognized = 0;
544       int argc = 0;
545       const char *argv[10];
546       a_seen = 0;
547       b_seen = 0;
548
549       argv[argc++] = "program";
550       argv[argc++] = "-p";
551       argv[argc++] = "foo";
552       argv[argc++] = "-x";
553       argv[argc++] = "-a";
554       argv[argc++] = "bar";
555       argv[argc] = NULL;
556       optind = start;
557       getopt_long_loop (argc, argv, "abp:q:", long_options_required,
558                         &p_value, &q_value,
559                         &non_options_count, non_options, &unrecognized);
560       ASSERT (a_seen == 1);
561       ASSERT (b_seen == 0);
562       ASSERT (p_value != NULL && strcmp (p_value, "foo") == 0);
563       ASSERT (q_value == NULL);
564       ASSERT (non_options_count == 0);
565       ASSERT (unrecognized == 'x');
566       ASSERT (optind == 5);
567     }
568
569   /* Check that by default, non-options arguments are moved to the end.  */
570   for (start = OPTIND_MIN; start <= 1; start++)
571     {
572       const char *p_value = NULL;
573       const char *q_value = NULL;
574       int non_options_count = 0;
575       const char *non_options[10];
576       int unrecognized = 0;
577       int argc = 0;
578       const char *argv[10];
579       a_seen = 0;
580       b_seen = 0;
581
582       argv[argc++] = "program";
583       argv[argc++] = "donald";
584       argv[argc++] = "-p";
585       argv[argc++] = "billy";
586       argv[argc++] = "duck";
587       argv[argc++] = "-a";
588       argv[argc++] = "bar";
589       argv[argc] = NULL;
590       optind = start;
591       getopt_long_loop (argc, argv, "abp:q:", long_options_required,
592                         &p_value, &q_value,
593                         &non_options_count, non_options, &unrecognized);
594       ASSERT (strcmp (argv[0], "program") == 0);
595       ASSERT (strcmp (argv[1], "-p") == 0);
596       ASSERT (strcmp (argv[2], "billy") == 0);
597       ASSERT (strcmp (argv[3], "-a") == 0);
598       ASSERT (strcmp (argv[4], "donald") == 0);
599       ASSERT (strcmp (argv[5], "duck") == 0);
600       ASSERT (strcmp (argv[6], "bar") == 0);
601       ASSERT (argv[7] == NULL);
602       ASSERT (a_seen == 1);
603       ASSERT (b_seen == 0);
604       ASSERT (p_value != NULL && strcmp (p_value, "billy") == 0);
605       ASSERT (q_value == NULL);
606       ASSERT (non_options_count == 0);
607       ASSERT (unrecognized == 0);
608       ASSERT (optind == 4);
609     }
610
611   /* Check that '--' ends the argument processing.  */
612   for (start = OPTIND_MIN; start <= 1; start++)
613     {
614       const char *p_value = NULL;
615       const char *q_value = NULL;
616       int non_options_count = 0;
617       const char *non_options[10];
618       int unrecognized = 0;
619       int argc = 0;
620       const char *argv[20];
621       a_seen = 0;
622       b_seen = 0;
623
624       argv[argc++] = "program";
625       argv[argc++] = "donald";
626       argv[argc++] = "-p";
627       argv[argc++] = "billy";
628       argv[argc++] = "duck";
629       argv[argc++] = "-a";
630       argv[argc++] = "--";
631       argv[argc++] = "-b";
632       argv[argc++] = "foo";
633       argv[argc++] = "-q";
634       argv[argc++] = "johnny";
635       argv[argc++] = "bar";
636       argv[argc] = NULL;
637       optind = start;
638       getopt_long_loop (argc, argv, "abp:q:", long_options_required,
639                         &p_value, &q_value,
640                         &non_options_count, non_options, &unrecognized);
641       ASSERT (strcmp (argv[0], "program") == 0);
642       ASSERT (strcmp (argv[1], "-p") == 0);
643       ASSERT (strcmp (argv[2], "billy") == 0);
644       ASSERT (strcmp (argv[3], "-a") == 0);
645       ASSERT (strcmp (argv[4], "--") == 0);
646       ASSERT (strcmp (argv[5], "donald") == 0);
647       ASSERT (strcmp (argv[6], "duck") == 0);
648       ASSERT (strcmp (argv[7], "-b") == 0);
649       ASSERT (strcmp (argv[8], "foo") == 0);
650       ASSERT (strcmp (argv[9], "-q") == 0);
651       ASSERT (strcmp (argv[10], "johnny") == 0);
652       ASSERT (strcmp (argv[11], "bar") == 0);
653       ASSERT (argv[12] == NULL);
654       ASSERT (a_seen == 1);
655       ASSERT (b_seen == 0);
656       ASSERT (p_value != NULL && strcmp (p_value, "billy") == 0);
657       ASSERT (q_value == NULL);
658       ASSERT (non_options_count == 0);
659       ASSERT (unrecognized == 0);
660       ASSERT (optind == 5);
661     }
662
663   /* Check that the '-' flag causes non-options to be returned in order.  */
664   for (start = OPTIND_MIN; start <= 1; start++)
665     {
666       const char *p_value = NULL;
667       const char *q_value = NULL;
668       int non_options_count = 0;
669       const char *non_options[10];
670       int unrecognized = 0;
671       int argc = 0;
672       const char *argv[10];
673       a_seen = 0;
674       b_seen = 0;
675
676       argv[argc++] = "program";
677       argv[argc++] = "donald";
678       argv[argc++] = "-p";
679       argv[argc++] = "billy";
680       argv[argc++] = "duck";
681       argv[argc++] = "-a";
682       argv[argc++] = "bar";
683       argv[argc] = NULL;
684       optind = start;
685       getopt_long_loop (argc, argv, "-abp:q:", long_options_required,
686                         &p_value, &q_value,
687                         &non_options_count, non_options, &unrecognized);
688       ASSERT (strcmp (argv[0], "program") == 0);
689       ASSERT (strcmp (argv[1], "donald") == 0);
690       ASSERT (strcmp (argv[2], "-p") == 0);
691       ASSERT (strcmp (argv[3], "billy") == 0);
692       ASSERT (strcmp (argv[4], "duck") == 0);
693       ASSERT (strcmp (argv[5], "-a") == 0);
694       ASSERT (strcmp (argv[6], "bar") == 0);
695       ASSERT (argv[7] == NULL);
696       ASSERT (a_seen == 1);
697       ASSERT (b_seen == 0);
698       ASSERT (p_value != NULL && strcmp (p_value, "billy") == 0);
699       ASSERT (q_value == NULL);
700       ASSERT (non_options_count == 3);
701       ASSERT (strcmp (non_options[0], "donald") == 0);
702       ASSERT (strcmp (non_options[1], "duck") == 0);
703       ASSERT (strcmp (non_options[2], "bar") == 0);
704       ASSERT (unrecognized == 0);
705       ASSERT (optind == 7);
706     }
707
708   /* Check that '--' ends the argument processing.  */
709   for (start = OPTIND_MIN; start <= 1; start++)
710     {
711       const char *p_value = NULL;
712       const char *q_value = NULL;
713       int non_options_count = 0;
714       const char *non_options[10];
715       int unrecognized = 0;
716       int argc = 0;
717       const char *argv[20];
718       a_seen = 0;
719       b_seen = 0;
720
721       argv[argc++] = "program";
722       argv[argc++] = "donald";
723       argv[argc++] = "-p";
724       argv[argc++] = "billy";
725       argv[argc++] = "duck";
726       argv[argc++] = "-a";
727       argv[argc++] = "--";
728       argv[argc++] = "-b";
729       argv[argc++] = "foo";
730       argv[argc++] = "-q";
731       argv[argc++] = "johnny";
732       argv[argc++] = "bar";
733       argv[argc] = NULL;
734       optind = start;
735       getopt_long_loop (argc, argv, "-abp:q:", long_options_required,
736                         &p_value, &q_value,
737                         &non_options_count, non_options, &unrecognized);
738       ASSERT (strcmp (argv[0], "program") == 0);
739       ASSERT (strcmp (argv[1], "donald") == 0);
740       ASSERT (strcmp (argv[2], "-p") == 0);
741       ASSERT (strcmp (argv[3], "billy") == 0);
742       ASSERT (strcmp (argv[4], "duck") == 0);
743       ASSERT (strcmp (argv[5], "-a") == 0);
744       ASSERT (strcmp (argv[6], "--") == 0);
745       ASSERT (strcmp (argv[7], "-b") == 0);
746       ASSERT (strcmp (argv[8], "foo") == 0);
747       ASSERT (strcmp (argv[9], "-q") == 0);
748       ASSERT (strcmp (argv[10], "johnny") == 0);
749       ASSERT (strcmp (argv[11], "bar") == 0);
750       ASSERT (argv[12] == NULL);
751       ASSERT (a_seen == 1);
752       ASSERT (b_seen == 0);
753       ASSERT (p_value != NULL && strcmp (p_value, "billy") == 0);
754       ASSERT (q_value == NULL);
755       if (non_options_count == 2)
756       {
757         /* glibc behaviour.  */
758         ASSERT (non_options_count == 2);
759         ASSERT (strcmp (non_options[0], "donald") == 0);
760         ASSERT (strcmp (non_options[1], "duck") == 0);
761         ASSERT (unrecognized == 0);
762         ASSERT (optind == 7);
763       }
764       else
765       {
766         /* Another valid behaviour.  */
767         ASSERT (non_options_count == 7);
768         ASSERT (strcmp (non_options[0], "donald") == 0);
769         ASSERT (strcmp (non_options[1], "duck") == 0);
770         ASSERT (strcmp (non_options[2], "-b") == 0);
771         ASSERT (strcmp (non_options[3], "foo") == 0);
772         ASSERT (strcmp (non_options[4], "-q") == 0);
773         ASSERT (strcmp (non_options[5], "johnny") == 0);
774         ASSERT (strcmp (non_options[6], "bar") == 0);
775         ASSERT (unrecognized == 0);
776         ASSERT (optind == 12);
777       }
778     }
779
780   /* Check that the '-' flag has to come first.  */
781   for (start = OPTIND_MIN; start <= 1; start++)
782     {
783       const char *p_value = NULL;
784       const char *q_value = NULL;
785       int non_options_count = 0;
786       const char *non_options[10];
787       int unrecognized = 0;
788       int argc = 0;
789       const char *argv[10];
790       a_seen = 0;
791       b_seen = 0;
792
793       argv[argc++] = "program";
794       argv[argc++] = "donald";
795       argv[argc++] = "-p";
796       argv[argc++] = "billy";
797       argv[argc++] = "duck";
798       argv[argc++] = "-a";
799       argv[argc++] = "bar";
800       argv[argc] = NULL;
801       optind = start;
802       getopt_long_loop (argc, argv, "abp:q:-", long_options_required,
803                         &p_value, &q_value,
804                         &non_options_count, non_options, &unrecognized);
805       ASSERT (strcmp (argv[0], "program") == 0);
806       ASSERT (strcmp (argv[1], "-p") == 0);
807       ASSERT (strcmp (argv[2], "billy") == 0);
808       ASSERT (strcmp (argv[3], "-a") == 0);
809       ASSERT (strcmp (argv[4], "donald") == 0);
810       ASSERT (strcmp (argv[5], "duck") == 0);
811       ASSERT (strcmp (argv[6], "bar") == 0);
812       ASSERT (argv[7] == NULL);
813       ASSERT (a_seen == 1);
814       ASSERT (b_seen == 0);
815       ASSERT (p_value != NULL && strcmp (p_value, "billy") == 0);
816       ASSERT (q_value == NULL);
817       ASSERT (non_options_count == 0);
818       ASSERT (unrecognized == 0);
819       ASSERT (optind == 4);
820     }
821
822   /* Check that the '+' flag causes the first non-option to terminate the
823      loop.  */
824   for (start = OPTIND_MIN; start <= 1; start++)
825     {
826       const char *p_value = NULL;
827       const char *q_value = NULL;
828       int non_options_count = 0;
829       const char *non_options[10];
830       int unrecognized = 0;
831       int argc = 0;
832       const char *argv[10];
833       a_seen = 0;
834       b_seen = 0;
835
836       argv[argc++] = "program";
837       argv[argc++] = "donald";
838       argv[argc++] = "-p";
839       argv[argc++] = "billy";
840       argv[argc++] = "duck";
841       argv[argc++] = "-a";
842       argv[argc++] = "bar";
843       argv[argc] = NULL;
844       optind = start;
845       getopt_long_loop (argc, argv, "+abp:q:", long_options_required,
846                         &p_value, &q_value,
847                         &non_options_count, non_options, &unrecognized);
848       ASSERT (strcmp (argv[0], "program") == 0);
849       ASSERT (strcmp (argv[1], "donald") == 0);
850       ASSERT (strcmp (argv[2], "-p") == 0);
851       ASSERT (strcmp (argv[3], "billy") == 0);
852       ASSERT (strcmp (argv[4], "duck") == 0);
853       ASSERT (strcmp (argv[5], "-a") == 0);
854       ASSERT (strcmp (argv[6], "bar") == 0);
855       ASSERT (argv[7] == NULL);
856       ASSERT (a_seen == 0);
857       ASSERT (b_seen == 0);
858       ASSERT (p_value == NULL);
859       ASSERT (q_value == NULL);
860       ASSERT (non_options_count == 0);
861       ASSERT (unrecognized == 0);
862       ASSERT (optind == 1);
863     }
864   for (start = OPTIND_MIN; start <= 1; start++)
865     {
866       const char *p_value = NULL;
867       const char *q_value = NULL;
868       int non_options_count = 0;
869       const char *non_options[10];
870       int unrecognized = 0;
871       int argc = 0;
872       const char *argv[10];
873       a_seen = 0;
874       b_seen = 0;
875
876       argv[argc++] = "program";
877       argv[argc++] = "-+";
878       argv[argc] = NULL;
879       optind = start;
880       getopt_long_loop (argc, argv, "+abp:q:", long_options_required,
881                         &p_value, &q_value,
882                         &non_options_count, non_options, &unrecognized);
883       ASSERT (a_seen == 0);
884       ASSERT (b_seen == 0);
885       ASSERT (p_value == NULL);
886       ASSERT (q_value == NULL);
887       ASSERT (non_options_count == 0);
888       ASSERT (unrecognized == '+');
889       ASSERT (optind == 2);
890     }
891
892   /* Check that '--' ends the argument processing.  */
893   for (start = OPTIND_MIN; start <= 1; start++)
894     {
895       const char *p_value = NULL;
896       const char *q_value = NULL;
897       int non_options_count = 0;
898       const char *non_options[10];
899       int unrecognized = 0;
900       int argc = 0;
901       const char *argv[20];
902       a_seen = 0;
903       b_seen = 0;
904
905       argv[argc++] = "program";
906       argv[argc++] = "donald";
907       argv[argc++] = "-p";
908       argv[argc++] = "billy";
909       argv[argc++] = "duck";
910       argv[argc++] = "-a";
911       argv[argc++] = "--";
912       argv[argc++] = "-b";
913       argv[argc++] = "foo";
914       argv[argc++] = "-q";
915       argv[argc++] = "johnny";
916       argv[argc++] = "bar";
917       argv[argc] = NULL;
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], "donald") == 0);
924       ASSERT (strcmp (argv[2], "-p") == 0);
925       ASSERT (strcmp (argv[3], "billy") == 0);
926       ASSERT (strcmp (argv[4], "duck") == 0);
927       ASSERT (strcmp (argv[5], "-a") == 0);
928       ASSERT (strcmp (argv[6], "--") == 0);
929       ASSERT (strcmp (argv[7], "-b") == 0);
930       ASSERT (strcmp (argv[8], "foo") == 0);
931       ASSERT (strcmp (argv[9], "-q") == 0);
932       ASSERT (strcmp (argv[10], "johnny") == 0);
933       ASSERT (strcmp (argv[11], "bar") == 0);
934       ASSERT (argv[12] == NULL);
935       ASSERT (a_seen == 0);
936       ASSERT (b_seen == 0);
937       ASSERT (p_value == NULL);
938       ASSERT (q_value == NULL);
939       ASSERT (non_options_count == 0);
940       ASSERT (unrecognized == 0);
941       ASSERT (optind = 1);
942     }
943
944   /* Check that the '+' flag has to come first.  */
945   for (start = OPTIND_MIN; start <= 1; start++)
946     {
947       const char *p_value = NULL;
948       const char *q_value = NULL;
949       int non_options_count = 0;
950       const char *non_options[10];
951       int unrecognized = 0;
952       int argc = 0;
953       const char *argv[10];
954       a_seen = 0;
955       b_seen = 0;
956
957       argv[argc++] = "program";
958       argv[argc++] = "donald";
959       argv[argc++] = "-p";
960       argv[argc++] = "billy";
961       argv[argc++] = "duck";
962       argv[argc++] = "-a";
963       argv[argc++] = "bar";
964       argv[argc] = NULL;
965       optind = start;
966       getopt_long_loop (argc, argv, "abp:q:+", long_options_required,
967                         &p_value, &q_value,
968                         &non_options_count, non_options, &unrecognized);
969       ASSERT (strcmp (argv[0], "program") == 0);
970       ASSERT (strcmp (argv[1], "-p") == 0);
971       ASSERT (strcmp (argv[2], "billy") == 0);
972       ASSERT (strcmp (argv[3], "-a") == 0);
973       ASSERT (strcmp (argv[4], "donald") == 0);
974       ASSERT (strcmp (argv[5], "duck") == 0);
975       ASSERT (strcmp (argv[6], "bar") == 0);
976       ASSERT (argv[7] == NULL);
977       ASSERT (a_seen == 1);
978       ASSERT (b_seen == 0);
979       ASSERT (p_value != NULL && strcmp (p_value, "billy") == 0);
980       ASSERT (q_value == NULL);
981       ASSERT (non_options_count == 0);
982       ASSERT (unrecognized == 0);
983       ASSERT (optind == 4);
984     }
985 }
986
987 /* Test behavior of getopt_long when POSIXLY_CORRECT is set in the
988    environment.  Options with optional arguments should not change
989    behavior just because of an environment variable.
990    http://lists.gnu.org/archive/html/bug-m4/2006-09/msg00028.html  */
991 static void
992 test_getopt_long_posix (void)
993 {
994   int start;
995
996   /* Check that POSIXLY_CORRECT doesn't change optional arguments.  */
997   for (start = OPTIND_MIN; start <= 1; start++)
998     {
999       const char *p_value = NULL;
1000       const char *q_value = NULL;
1001       int non_options_count = 0;
1002       const char *non_options[10];
1003       int unrecognized = 0;
1004       int argc = 0;
1005       const char *argv[10];
1006       a_seen = 0;
1007       b_seen = 0;
1008
1009       argv[argc++] = "program";
1010       argv[argc++] = "-p";
1011       argv[argc++] = "billy";
1012       argv[argc] = NULL;
1013       optind = start;
1014       getopt_long_loop (argc, argv, "p::", long_options_required,
1015                         &p_value, &q_value,
1016                         &non_options_count, non_options, &unrecognized);
1017       ASSERT (a_seen == 0);
1018       ASSERT (b_seen == 0);
1019       ASSERT (p_value == NULL);
1020       ASSERT (q_value == NULL);
1021       ASSERT (non_options_count == 0);
1022       ASSERT (unrecognized == 0);
1023       ASSERT (optind == 2);
1024     }
1025
1026   /* Check that leading - still sees options after non-options.  */
1027   for (start = OPTIND_MIN; start <= 1; start++)
1028     {
1029       const char *p_value = NULL;
1030       const char *q_value = NULL;
1031       int non_options_count = 0;
1032       const char *non_options[10];
1033       int unrecognized = 0;
1034       int argc = 0;
1035       const char *argv[10];
1036       a_seen = 0;
1037       b_seen = 0;
1038
1039       argv[argc++] = "program";
1040       argv[argc++] = "-a";
1041       argv[argc++] = "billy";
1042       argv[argc++] = "-b";
1043       argv[argc] = NULL;
1044       optind = start;
1045       getopt_long_loop (argc, argv, "-ab", long_options_required,
1046                         &p_value, &q_value,
1047                         &non_options_count, non_options, &unrecognized);
1048       ASSERT (a_seen == 1);
1049       ASSERT (b_seen == 1);
1050       ASSERT (p_value == NULL);
1051       ASSERT (q_value == NULL);
1052       ASSERT (non_options_count == 1);
1053       ASSERT (strcmp (non_options[0], "billy") == 0);
1054       ASSERT (unrecognized == 0);
1055       ASSERT (optind == 4);
1056     }
1057 }