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