Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
0.cmdopts.cpp
Go to the documentation of this file.
1
30#include <rw_cmdopt.h>
31
32#include <stdio.h>
33#include <string.h>
34
35// global buffer containing the names of all callbacks (along with
36// their arguments) called in response to each invocation to rw_runopts()
37static char argstr [4096];
38
39// the maximum number of callbacks to be invoked by a single call
40// to rw_runopts()
41#define MAXCALLBACKS 32
42
43// the values to be returned by each callback
44static int retvals [MAXCALLBACKS];
45
46// the cumulative number of callback invocations
47static size_t ncalls;
48
49// the exit status of the whole test
50static int exit_status;
51
52// the current line number
53static int current_line;
54
55
57// prints its arguments in a human-readable form to buf
58static int
59pargs (char *buf, const char *funcname, int argc, char *argv [])
60{
61 _RWSTD_ASSERT (0 != buf);
62
63 char* next = buf + strlen (buf);
64
65 if ('\0' != *buf) {
66 next [0] = ';';
67 next [1] = '\0';
68 ++next;
69 }
70
71 if (funcname)
72 next += sprintf (next, "%s(%d,{", funcname, argc);
73 else
74 next += sprintf (next, "%d,{", argc);
75
76 for (int i = 0; i < argc; ++i) {
77
78 if (argv [i])
79 next += sprintf (next, "\"%s\"", argv [i]);
80 else {
81 strcpy (next, "(null)");
82 next += strlen (next);
83 }
84
85 if (i + 1 < argc) {
86 next [0] = ',';
87 next [1] = '\0';
88 ++next;
89 }
90 }
91
92 next [0] = '}';
93 next [1] = ')';
94 next [2] = '\0';
95
96 // verify that the number of calls hasn't exceeded the size
97 // of the array of return values
98 _RWSTD_ASSERT (ncalls < MAXCALLBACKS);
99
100 return retvals [ncalls];
101}
102
103
105static int
106callback_imp (const char *cbname, int argc, char *argv[])
107{
108 const int status = pargs (argstr, cbname, argc, argv);
109
110 ++ncalls;
111
112 return status;
113}
114
115
116static int
117foo (int argc, char *argv[])
118{
119 return callback_imp ("foo", argc, argv);
120}
121
122
123static int
124bar (int argc, char *argv[])
125{
126 return callback_imp ("bar", argc, argv);
127}
128
129static int
130err (int argc, char *argv[])
131{
132 return callback_imp ("ERR", argc, argv);
133}
134
135
137typedef int (cbfun_t)(int, char*[]);
138
139static int opt_counts [4];
140
141// hackery to allow passing int* and cbfun_t* in the same argument
142static const union {
143 int *pint;
145 int ival;
146} cntptrs [] = {
147 { opt_counts + 0 },
148 { opt_counts + 1 },
149 { opt_counts + 2 },
150 { opt_counts + 3 }
151};
152
153
155static void
156test_opts (const char *expect,
157 int get_exp,
158 char *argv [],
159 int set_exp,
160 const char *argspec,
161 cbfun_t *f0,
162 cbfun_t *f1 = 0,
163 cbfun_t *f2 = 0,
164 cbfun_t *f3 = 0)
165{
166 argstr [0] = '\0';
167
168 // reset all previously set options
169 rw_setopts (0, 0);
170
171 // set new options
172 const int set_res = rw_setopts (argspec, f0, f1, f2, f3);
173
174 if (set_res != set_exp) {
175
176 // convert function pointers to void pointers
177 // to avoid compiler error and warnings
178 union {
179 cbfun_t *pfun;
180 void *pvoid;
181 } uptr[] = {
182 { f0 }, { f1 }, { f2 }, { f3 }
183 };
184
185 fprintf (stderr,
186 "line %d: rw_setopts (\"%s\", %p, %p, %p, %p) == %d, got %d\n",
187 current_line, argspec,
188 uptr [0].pvoid, uptr [1].pvoid, uptr [2].pvoid, uptr [3].pvoid,
189 set_exp, set_res);
190
191 exit_status = 1;
192 }
193
194 argstr [0] = '\0';
195
196 // compute the value of argc from argv
197 int argc = 0;
198 for (; argv [argc]; ++argc);
199
200 // reset the number of callback invocations
201 ncalls = 0;
202
203 // reset the option counters
204 memset (opt_counts, 0, sizeof opt_counts);
205
206 const int get_res = rw_runopts (argc, argv);
207
208 if (get_res != get_exp) {
209
210 static char tmp [4096];
211
212 tmp [0] = '\0';
213 pargs (tmp, 0, argc, argv);
214
215 fprintf (stderr,
216 "line %d: rw_runopts (%s) == %d, got %d\n",
217 current_line, tmp, get_exp, get_res);
218
219 exit_status = 1;
220 }
221
222 if (strchr (expect, '#')) {
223 // when the expected result string contains the pound sign,
224 // treat the arguments as pointers to integers as opposed
225 // to pointers to callback functions and format the actual
226 // result as a sequence of integers at the given addresses
227
228 if (f0 == cntptrs [0].pfun) {
229 sprintf (argstr + strlen (argstr),
230 "%s%d", *argstr ? "; #" : "#", opt_counts [0]);
231
232 if (f1 == cntptrs [1].pfun) {
233 sprintf (argstr + strlen (argstr),
234 ",%d", opt_counts [1]);
235
236 if (f2 == cntptrs [2].pfun) {
237 sprintf (argstr + strlen (argstr),
238 ",%d", opt_counts [2]);
239
240 if (f3 == cntptrs [3].pfun) {
241 sprintf (argstr + strlen (argstr),
242 ",%d", opt_counts [3]);
243 }
244 }
245 }
246 }
247 }
248
249 if (strcmp (argstr, expect)) {
250 fprintf (stderr,
251 "line %d: \"%s\" != \"%s\"\n",
252 current_line, argstr, expect);
253
254 exit_status = 1;
255 }
256}
257
258
260static char**
261mkargv (const char *s0,
262 const char *s1 = 0,
263 const char *s2 = 0,
264 const char *s3 = 0,
265 const char *s4 = 0,
266 const char *s5 = 0,
267 const char *s6 = 0,
268 const char *s7 = 0,
269 const char *s8 = 0,
270 const char *s9 = 0)
271{
272 static char argbuf [10][1024];
273 static char* argv [10];
274
275 argv [0] = s0 ? strcpy (argbuf [0], s0) : 0;
276 argv [1] = s1 ? strcpy (argbuf [1], s1) : 0;
277 argv [2] = s2 ? strcpy (argbuf [2], s2) : 0;
278 argv [3] = s3 ? strcpy (argbuf [3], s3) : 0;
279 argv [4] = s4 ? strcpy (argbuf [4], s4) : 0;
280 argv [5] = s5 ? strcpy (argbuf [5], s5) : 0;
281 argv [6] = s6 ? strcpy (argbuf [6], s6) : 0;
282 argv [7] = s7 ? strcpy (argbuf [7], s7) : 0;
283 argv [8] = s8 ? strcpy (argbuf [8], s8) : 0;
284 argv [9] = s9 ? strcpy (argbuf [9], s9) : 0;
285
286 return argv;
287}
288
289
291// convenience macros for brevity
292
293#define A mkargv
294#define B bar
295#define F foo
296#define E err
297#define C0 cntptrs [0].pfun
298#define C1 cntptrs [1].pfun
299#define C2 cntptrs [2].pfun
300#define C3 cntptrs [3].pfun
301#define N(n) make_arg (n)
302#define T (current_line = __LINE__), test_opts
303
304
306static void
307test_unknown_options ()
308{
309 // +--------- expected result string (formatted by callbacks)
310 // | +----- expected value returned from rw_runopts()
311 // | | +-- second argument to rw_runopts() (argv)
312 // | | |
313 // | | | +---------- expected rw_setopts() result
314 // | | | | +------- rw_setopts() first argument
315 // | | | | | +-- rw_setopts() callbacks...
316 // | | | | | |
317 // V V V V V V
318 T ("", 0, A (""), 0, "", 0);
319
320 // exercise setting up the "unknown option" handler
321 T ("", 0, A (""), 1, "-", 0);
322 T ("", 0, A (""), 1, "-", E);
323
324 // exercise invoking the "unknown option" handler
325 T ("ERR(1,{\"-x\"})", 0, A ("-x"), 2, "- f", E, F);
326 T ("ERR(2,{\"-x\",\"-y\"});"
327 "foo(1,{\"-y\"})", 0, A ("-x","-y"), 2, "- y", E, F);
328
329 retvals [0] = 1;
330 T ("ERR(2,{\"-x\",\"-y\"})", 1, A ("-x","-y"), 2, "- y", E, F);
331
332 retvals [0] = 0;
333 retvals [1] = 2;
334 T ("foo(2,{\"-x\",\"-y\"});"
335 "ERR(1,{\"-y\"})", 2, A ("-x","-y"), 2, "- x", E, F);
336 T ("foo(3,{\"-x\",\"-y\",\"-x\"});"
337 "ERR(2,{\"-y\",\"-x\"})", 2, A ("-x","-y", "-x"), 2, "- x", E, F);
338 retvals [1] = 0;
339}
340
341
343static void
344test_counted_options ()
345{
346 // exercise options with a counter instead of a callback
347 T ("#1", 0, A ("-b"), 1, "b#", C0);
348 T ("#1", 0, A ("--cc"), 1, "|-cc#", C0);
349 T ("#2", 0, A ("-d", "-d"), 1, "d#", C0);
350 T ("#2", 0, A ("-e", "--ee"), 1, "e|-ee#", C0);
351 T ("#3", 0, A ("-e", "-e", "-e"), 1, "e#", C0);
352 T ("#1,2", 0, A ("-f", "-g", "-g"), 2, "f# g#", C0, C1);
353
354 // exercise counted options with a numerical argument
355 T ("#0", 0, A ("--n=0"), 1, "|-n#", C0);
356 T ("#1", 0, A ("--n=1"), 1, "|-n#", C0);
357 T ("#1", 0, A ("--n=+1"), 1, "|-n#", C0);
358 T ("#-1", 0, A ("--n=-1"), 1, "|-n#", C0);
359 T ("#2", 0, A ("--n=+2"), 1, "|-n#", C0);
360 T ("#-2", 0, A ("--n=-2"), 1, "|-n#", C0);
361 T ("#12345", 0, A ("--n=+12345"), 1, "|-n#", C0);
362 T ("#-12346", 0, A ("--n=-12346"), 1, "|-n#", C0);
363
364 // exercise counted options with a restricted numerical argument
365 T ("#0", 0, A ("--n=0"), 1, "|-n#0", C0);
366 T ("#1", 0, A ("--n=1"), 1, "|-n#0", C0);
367 T ("#1", 0, A ("--n=1"), 1, "|-n#1", C0);
368 T ("#2", 0, A ("--n=2"), 1, "|-n#1", C0);
369 T ("#1", 0, A ("--n=+1"), 1, "|-n#+1", C0);
370 T ("#-1", 0, A ("--n=-1"), 1, "|-n#-1", C0);
371 T ("#0", 0, A ("--n=0"), 1, "|-n#-1", C0);
372 T ("#1", 0, A ("--n=1"), 1, "|-n#-1", C0);
373 T ("#123", 0, A ("--n=+123"), 1, "|-n#+123", C0);
374 T ("#124", 0, A ("--n=+124"), 1, "|-n#+123", C0);
375 T ("#-125", 0, A ("--n=-125"), 1, "|-n#-125", C0);
376 T ("#-126", 0, A ("--n=-126"), 1, "|-n#-127", C0);
377
378 T ("#0", 0, A ("--n=0"), 1, "|-n#0-1", C0);
379 T ("#1", 0, A ("--n=1"), 1, "|-n#0-1", C0);
380
381 T ("#0", 0, A ("--n=0"), 1, "|-n#-1-0", C0);
382
383 // same as above but with an out of range argument
384 T ("", 1, A ("--n=1"), 1, "|-n#-1-0", C0);
385 T ("", 1, A ("--n=-1"), 1, "|-n#0", C0);
386 T ("", 1, A ("--n=0"), 1, "|-n#1", C0);
387 T ("", 1, A ("--n=1"), 1, "|-n#2", C0);
388 T ("", 1, A ("--n=+2"), 1, "|-n#+3", C0);
389
390 T ("", 1, A ("--n=-1"), 1, "|-n#0-1", C0);
391 T ("", 1, A ("--n=+2"), 1, "|-n#0-1", C0);
392 T ("", 1, A ("--n=-11"), 1, "|-n#-10--5", C0);
393 T ("", 1, A ("--n=-4"), 1, "|-n#-10--5", C0);
394 T ("", 1, A ("--n=-11"), 1, "|-n#-1-1", C0);
395 T ("", 1, A ("--n=-1"), 1, "|-n#0-32", C0);
396 T ("", 1, A ("--n=33"), 1, "|-n#0-32", C0);
397}
398
399
401static void
402test_tristate ()
403{
404 // +-- expected result string
405 // | +-- expected return value from rw_getopts()
406 // | | +-- command line arguments
407 // | | | +-- number of directives
408 // | | | | +-- cmdopt specification
409 // | | | | | +-- counter
410 // | | | | | |
411 // V V V V V V
412 T ("#1", 0, A ("--enable-foo"), 1, "|-foo~", C0);
413 T ("#1", 0, A ("--use-foo"), 1, "|-foo~", C0);
414 T ("#1", 0, A ("--with-foo"), 1, "|-foo~", C0);
415 T ("#-1", 0, A ("--disable-foo"), 1, "|-foo~", C0);
416 T ("#-1", 0, A ("--no-foo"), 1, "|-foo~", C0);
417 T ("#-1", 0, A ("--without-foo"), 1, "|-foo~", C0);
418
419 // the same tristate can be repeated any number of times
420 T ("#1", 0, A ("--enable-foo", "--use-foo"), 1, "|-foo~", C0);
421 T ("#-1", 0, A ("--no-foo", "--without-foo"), 1, "|-foo~", C0);
422
423 // the last tristate wins
424 T ("#-1", 0, A ("--use-foo", "--no-foo"), 1, "|-foo~", C0);
425 T ("#1", 0, A ("--no-foo", "--use-foo"), 1, "|-foo~", C0);
426
428
429 // set bits using a bitmap
430 T ("#1", 0, A ("--enable-foo"), 1, "|-foo~:0", C0);
431 T ("#1", 0, A ("--enable-foo"), 1, "|-foo~:1", C0);
432 T ("#2", 0, A ("--enable-foo"), 1, "|-foo~:2", C0);
433 T ("#3", 0, A ("--enable-foo"), 1, "|-foo~:3", C0);
434 T ("#4", 0, A ("--enable-foo"), 1, "|-foo~:4", C0);
435
436 // unset bits using a bitmap
437 T ("#-2", 0, A ("--disable-foo"), 1, "|-foo~:1", C0);
438 T ("#-3", 0, A ("--disable-foo"), 1, "|-foo~:2", C0);
439 T ("#-4", 0, A ("--disable-foo"), 1, "|-foo~:3", C0);
440 T ("#-5", 0, A ("--disable-foo"), 1, "|-foo~:4", C0);
441
442 // set bits in word 2
443 T ("#0,1", 0, A ("--enable-bar"), 1, "|-bar~32:0", C0, C1);
444 T ("#0,1", 0, A ("--enable-bar"), 1, "|-bar~32:1", C0, C1);
445 T ("#0,2", 0, A ("--enable-bar"), 1, "|-bar~32:2", C0, C1);
446 T ("#0,3", 0, A ("--enable-bar"), 1, "|-bar~32:3", C0, C1);
447 T ("#0,4", 0, A ("--enable-bar"), 1, "|-bar~32:4", C0, C1);
448
449 // enable bits 0 through 4 in C0 one at a time
450 T ("#1", 0, A ("--with-0"), 4, "|-0~0 |-1~1 |-2~2 |-3~3", C0, C0, C0, C0);
451 T ("#2", 0, A ("--with-1"), 4, "|-0~0 |-1~1 |-2~2 |-3~3", C0, C0, C0, C0);
452 T ("#4", 0, A ("--with-2"), 4, "|-0~0 |-1~1 |-2~2 |-3~3", C0, C0, C0, C0);
453 T ("#8", 0, A ("--with-3"), 4, "|-0~0 |-1~1 |-2~2 |-3~3", C0, C0, C0, C0);
454
455 // enable multiple bits 0 through 4 in C0 simultaneously
456 T ("#3", 0, A ("--with-0", "--with-1"),
457 4, "|-0~0 |-1~1 |-2~2 |-3~3", C0, C0, C0, C0);
458
459 T ("#7", 0, A ("--with-0", "--with-1", "--with-2"),
460 4, "|-0~0 |-1~1 |-2~2 |-3~3", C0, C0, C0, C0);
461
462 T ("#15", 0, A ("--with-0", "--with-1", "--with-2", "--with-3"),
463 4, "|-0~0 |-1~1 |-2~2 |-3~3", C0, C0, C0, C0);
464
465 // specify bit value
466 T ("#1", 0, A ("--with-0"),
467 4, "|-0~0:1 |-1~1:1 |-2~2:1 |-3~3:1", C0, C0, C0, C0);
468
469 T ("#2", 0, A ("--with-1"),
470 4, "|-0~0:1 |-1~1:1 |-2~2:1 |-3~3:1", C0, C0, C0, C0);
471
472 T ("#4", 0, A ("--with-2"),
473 4, "|-0~0:1 |-1~1:1 |-2~2:1 |-3~3:1", C0, C0, C0, C0);
474
475 T ("#8", 0, A ("--with-3"),
476 4, "|-0~0:1 |-1~1:1 |-2~2:1 |-3~3:1", C0, C0, C0, C0);
477
478 T ("#3", 0, A ("--with-0", "--with-1"),
479 4, "|-0~0:1 |-1~1:1 |-2~2:1 |-3~3:1", C0, C0, C0, C0);
480
481 T ("#7", 0, A ("--with-0", "--with-1", "--with-2"),
482 4, "|-0~0:1 |-1~1:1 |-2~2:1 |-3~3:1", C0, C0, C0, C0);
483
484 T ("#15", 0, A ("--with-0", "--with-1", "--with-2", "--with-3"),
485 4, "|-0~0:1 |-1~1:1 |-2~2:1 |-3~3:1", C0, C0, C0, C0);
486
487 T ("#-1073741824",
488 0, A ("--enable-f30"),
489 3, "|-f30~30:3 |-f28~28:2 |-f26~26:2", C0, C0, C0);
490
491 T ("#-2147483648",
492 0, A ("--enable-f30"),
493 3, "|-f30~30:2 |-f28~28:2 |-f26~26:2", C0, C0, C0);
494
495 T ("#-1610612736",
496 0, A ("--enable-f30","--enable-f28"),
497 3, "|-f30~30:2 |-f28~28:2 |-f26~26:2", C0, C0, C0);
498
499 T ("#-1476395008",
500 0, A ("--enable-f30","--enable-f28","--enable-f26"),
501 3, "|-f30~30:2 |-f28~28:2 |-f26~26:2", C0, C0, C0);
502}
503
504
506static void
507test_optional_argument ()
508{
509 // exercise an option with an optional argument
510 T ("foo(1,{\"-a\"})", 0, A ("-a"), 1, "a:", F);
511 T ("foo(1,{\"-a\"})", 0, A ("-a"), 1, "a:", F);
512 T ("foo(2,{\"-a\",\"x\"})", 0, A ("-a", "x"), 1, "a:", F);
513 T ("foo(1,{\"-ay\"})", 0, A ("-ay"), 1, "a:", F);
514 T ("foo(1,{\"-axyz\"})", 0, A ("-axyz"), 1, "a:", F);
515 T ("foo(1,{\"--a\"})", 0, A ("--a"), 1, "|-a:", F);
516 T ("ERR(1,{\"--ab\"})", 0, A ("--ab"), 2, "- |-a:", E, F);
517
518 // exercise the processing of two optional command line options
519 T ("foo(2,{\"-a\",\"-b\"});"
520 "bar(1,{\"-b\"})",
521 0, A ("-a", "-b"), 2, "a: b", F, B);
522
523 T ("foo(3,{\"-a\",\"x\",\"-b\"});"
524 "bar(1,{\"-b\"})",
525 0, A ("-a", "x", "-b"), 2, "a: b", F, B);
526
527 // exercise optional restricted numeric argument
528 T ("foo(2,{\"-n\",\"0\"})", 0, A ("-n", "0"), 1, "n:0", F);
529 T ("foo(2,{\"-n\",\"+1\"})", 0, A ("-n", "+1"), 1, "n:1", F);
530 T ("foo(2,{\"-n\",\"+2\"})", 0, A ("-n", "+2"), 1, "n:+2", F);
531 T ("foo(2,{\"-n\",\"\\-2\"})", 0, A ("-n", "\\-2"), 1, "n:-3", F);
532 T ("foo(2,{\"-n\",\"\\-0\"})", 0, A ("-n", "\\-0"), 1, "n:-3-0", F);
533}
534
535
537static void
538test_required_argument ()
539{
540 // exercise the processing of an option with a required argument
541
542 // the equals sign missing
543 T ("ERR(1,{\"--a\"})", 0, A ("--a"), 2, "- |-a=", E, F);
544
545 // required argument empty
546 T ("foo(1,{\"--a=\"})", 0, A ("--a="), 1, "|-a=", F);
547
548 // required argument contains funky characters
549 T ("foo(1,{\"--a=1\"})", 0, A ("--a=1"), 1, "|-a=", F);
550 T ("foo(1,{\"--b=1-\"})", 0, A ("--b=1-"), 1, "|-b=", F);
551 T ("foo(1,{\"--c=-2\"})", 0, A ("--c=-2"), 1, "|-c=", F);
552 T ("foo(1,{\"--d=1-2\"})", 0, A ("--d=1-2"), 1, "|-d=", F);
553 T ("foo(1,{\"--e=-1=2\"})", 0, A ("--e=-1=2"), 1, "|-e=", F);
554 T ("foo(1,{\"--f=-1=-2\"})", 0, A ("--f=-1=-2"), 1, "|-f=", F);
555 T ("foo(1,{\"--g=2,3\"})", 0, A ("--g=2,3"), 1, "|-g=", F);
556 T ("foo(1,{\"--h=3:4\"})", 0, A ("--h=3:4"), 1, "|-h=", F);
557 T ("foo(1,{\"--i=\"j\"\"})", 0, A ("--i=\"j\""), 1, "|-i=", F);
558
559 // exercise restricted numeric argument
560 T ("foo(1,{\"--a=1\"})", 0, A ("--a=1"), 1, "|-a=0", F);
561 T ("foo(1,{\"--a=1\"})", 0, A ("--a=1"), 1, "|-a=1", F);
562 T ("foo(1,{\"--a=2\"})", 0, A ("--a=2"), 1, "|-a=2", F);
563 T ("foo(1,{\"--a=3\"})", 0, A ("--a=3"), 1, "|-a=3-4", F);
564 T ("foo(1,{\"--a=5\"})", 0, A ("--a=5"), 1, "|-a=4-5", F);
565
566 T ("", 1, A ("--a=1"), 1, "|-a=2", F);
567 T ("", 1, A ("--a=2"), 1, "|-a=0-1", F);
568 T ("", 1, A ("--a=-1"), 1, "|-a=1-2", F);
569 T ("", 1, A ("--a=+123"), 1, "|-a=+2-3", F);
570
571}
572
573
575static void
576test_repeated_options ()
577{
578 // exercise repeated options
579 // only the first occurrence of each command line option
580 // causes an invocation of the callback, all subsequent
581 // ones will be ignored by default
582 T ("foo(2,{\"-a\",\"-a\"})", 0, A ("-a", "-a"), 1, "a", F);
583
584 // unlimited number of invocations
585 T ("foo(2,{\"-a\",\"-a\"});"
586 "foo(1,{\"-a\"})",
587 0, A ("-a", "-a"), 1, "a@*", F);
588
589 // no invocation (option is disabled)
590 T ("", 0, A ("-a"), 1, "a@0", F);
591 T ("", 0, A ("-a", "-a"), 1, "a@0", F);
592
593 T ("bar(1,{\"-b\"})", 0, A ("-a", "-a", "-b"), 2, "a@0 b", F, B);
594 T ("bar(2,{\"-b\",\"-a\"})", 0, A ("-a", "-b", "-a"), 2, "a@0 b", F, B);
595
596 T ("bar(3,{\"-b\",\"-a\",\"-b\"})",
597 0, A ("-b", "-a", "-b"), 2, "b a@0", B, F);
598
599 T ("bar(4,{\"-b\",\"-a\",\"-b\",\"-a\"})",
600 0, A ("-b", "-a", "-b", "-a"), 2, "b a@0", B, F);
601
602 // at most one invocation (default)
603 T ("foo(2,{\"-a\",\"-a\"})", 0, A ("-a", "-a"), 1, "a@1", F);
604 T ("foo(2,{\"-a\",\"-a\"})", 0, A ("-a", "-a"), 1, "a@1", F);
605
606 // at most two invocations
607 T ("foo(2,{\"-a\",\"-a\"});"
608 "foo(1,{\"-a\"})",
609 0, A ("-a", "-a"), 1, "a@2", F);
610
611 T ("foo(3,{\"-a\",\"-a\",\"-a\"});"
612 "foo(2,{\"-a\",\"-a\"})",
613 0, A ("-a", "-a", "-a"), 1, "a@2", F);
614
615 // inverted option (callback invoked iff option is not specified)
616 T ("", 0, A ("-i"), 1, "i!", F);
617 T ("foo(0,{})", 0, A (""), 1, "i!", F);
618 T ("", 0, A ("--j"), 1, "i|-j!", F);
619
620 T ("foo(1,{\"-k\"});"
621 "foo(0,{})", 0, A ("-k"), 2, "k l!", F, F);
622}
623
624
626int main ()
627{
628 // +--------- expected result string (formatted by callbacks)
629 // | +----- expected value returned from rw_runopts()
630 // | | +-- second argument to rw_runopts() (argv)
631 // | | |
632 // | | | +---------- expected rw_setopts() result
633 // | | | | +------- rw_setopts() first argument
634 // | | | | | +-- rw_setopts() callbacks...
635 // | | | | | |
636 // V V V V V V
637 T ("", 0, A (""), 0, "", 0);
638 T ("", 0, A ("a"), 0, "", 0);
639 T ("", 0, A ("a", "b"), 0, "", 0);
640 T ("", 0, A ("a", "b"), 0, "", 0);
641
642 T ("", 0, A (""), 1, "f", F);
643 T ("", 0, A ("a"), 1, "f", F);
644 T ("", 0, A ("a", "b"), 1, "f", F);
645 T ("", 0, A ("a", "b"), 1, "f", F);
646 T ("", 0, A ("a", "f"), 1, "f", F);
647 T ("", 0, A ("f", "f"), 1, "f", F);
648
649 // exercise short and/or long options
650 T ("foo(1,{\"-a\"})", 0, A ("-a"), 1, "a", F);
651 T ("foo(1,{\"--a\"})", 0, A ("--a"), 1, "|-a", F);
652 T ("foo(1,{\"-a\"})", 0, A ("-a"), 1, "a|-a", F);
653 T ("foo(1,{\"--a\"})", 0, A ("--a"), 1, "a|-a", F);
654
655 // exercise the handling of unknown options
656 test_unknown_options ();
657
658 // exercise the handling of options with a counter
659 // instead of a callback handler
660 test_counted_options ();
661
662 // exercise the handling of options with an optional argument
663 test_optional_argument ();
664
665 // exercise the handling of tristate options
666 test_tristate ();
667
668 // exercise the handling of options with a required argument
669 test_required_argument ();
670
671 // exercise the handling of repeated occurrences of the same option
672 test_repeated_options ();
673
674 // exercise callback errors
675 retvals [0] = 1;
676 T ("foo(2,{\"-a\",\"-b\"})",
677 retvals [0], A ("-a", "-b"), 2, "a b", F, B);
678
679 retvals [0] = 0;
680 retvals [1] = 2;
681
682 T ("foo(3,{\"-a\",\"-b\",\"-c\"});"
683 "bar(2,{\"-b\",\"-c\"})",
684 retvals [1], A ("-a", "-b", "-c"), 3, "a b c", F, B, E);
685
686 retvals [1] = 0;
687
688 return exit_status;
689}
#define T
int ival
int * pint
#define C1
int() cbfun_t(int, char *[])
cbfun_t * pfun
#define C0
int main()
#define MAXCALLBACKS
Definition 0.cmdopts.cpp:41
#define i
Definition 17.names.cpp:126
#define s1
Definition 17.names.cpp:242
#define s2
Definition 17.names.cpp:268
#define f1
Definition 17.names.cpp:230
#define buf
Definition 17.names.cpp:452
#define tmp
Definition 17.names.cpp:553
#define f2
Definition 17.names.cpp:256
const char * s3
@ s0
Definition HONOR_STD.cpp:38
#define foo(buf, s,...)
#define stderr
#define _RWSTD_ASSERT(ignore)
Definition _defs.h:1108
_TEST_EXPORT int rw_setopts(const char *optspec,...)
Definition cmdopt.cpp:652
_TEST_EXPORT int rw_runopts(int argc, char *argv[])
Definition cmdopt.cpp:875