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