]>
Commit | Line | Data |
---|---|---|
732a6311 KZ |
1 | #ifndef UTIL_LINUX_OPTUTILS_H |
2 | #define UTIL_LINUX_OPTUTILS_H | |
3 | ||
fdf8e1f5 SK |
4 | #include <assert.h> |
5 | ||
8f77d454 SK |
6 | #include "c.h" |
7 | #include "nls.h" | |
9bf13750 | 8 | #include "cctype.h" |
8f77d454 | 9 | |
732a6311 KZ |
10 | static inline const char *option_to_longopt(int c, const struct option *opts) |
11 | { | |
12 | const struct option *o; | |
13 | ||
fdf8e1f5 | 14 | assert(!(opts == NULL)); |
732a6311 KZ |
15 | for (o = opts; o->name; o++) |
16 | if (o->val == c) | |
17 | return o->name; | |
18 | return NULL; | |
19 | } | |
20 | ||
8f77d454 SK |
21 | #ifndef OPTUTILS_EXIT_CODE |
22 | # define OPTUTILS_EXIT_CODE EXIT_FAILURE | |
23 | #endif | |
217d20a7 | 24 | |
217d20a7 KZ |
25 | /* |
26 | * Check collisions between options. | |
27 | * | |
28 | * The conflicts between options are described in ul_excl_t array. The | |
29 | * array contains groups of mutually exclusive options. For example | |
30 | * | |
31 | * static const ul_excl_t excl[] = { | |
32 | * { 'Z','b','c' }, // first group | |
33 | * { 'b','x' }, // second group | |
34 | * { 0 } | |
35 | * }; | |
36 | * | |
37 | * int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT; | |
38 | * | |
39 | * while ((c = getopt_long(argc, argv, "Zbcx", longopts, NULL)) != -1) { | |
40 | * | |
41 | * err_exclusive_options(c, longopts, excl, excl_st); | |
42 | * | |
43 | * switch (c) { | |
44 | * case 'Z': | |
45 | * .... | |
46 | * } | |
47 | * } | |
48 | * | |
49 | * The array excl[] defines two groups of the mutually exclusive options. The | |
50 | * option '-b' is in the both groups. | |
51 | * | |
52 | * Note that the options in the group have to be in ASCII order (ABC..abc..) and | |
53 | * groups have to be also in ASCII order. | |
54 | * | |
2c7bcdf8 KZ |
55 | * The maximal number of the options in the group is 15 (size of the array is |
56 | * 16, last is zero). | |
57 | * | |
217d20a7 KZ |
58 | * The current status of options is stored in excl_st array. The size of the array |
59 | * must be the same as number of the groups in the ul_excl_t array. | |
60 | * | |
61 | * If you're unsure then see sys-utils/mount.c or misc-utils/findmnt.c. | |
62 | */ | |
63 | #define UL_EXCL_STATUS_INIT { 0 } | |
64 | typedef int ul_excl_t[16]; | |
65 | ||
66 | static inline void err_exclusive_options( | |
67 | int c, | |
68 | const struct option *opts, | |
69 | const ul_excl_t *excl, | |
70 | int *status) | |
71 | { | |
72 | int e; | |
73 | ||
74 | for (e = 0; excl[e][0] && excl[e][0] <= c; e++) { | |
75 | const int *op = excl[e]; | |
76 | ||
77 | for (; *op && *op <= c; op++) { | |
78 | if (*op != c) | |
79 | continue; | |
80 | if (status[e] == 0) | |
81 | status[e] = c; | |
82 | else if (status[e] != c) { | |
2c7bcdf8 KZ |
83 | size_t ct = 0; |
84 | ||
9bf13750 WP |
85 | fprintf(stderr, _("%s: mutually exclusive " |
86 | "arguments:"), | |
217d20a7 | 87 | program_invocation_short_name); |
2c7bcdf8 KZ |
88 | |
89 | for (op = excl[e]; | |
90 | ct + 1 < ARRAY_SIZE(excl[0]) && *op; | |
91 | op++, ct++) { | |
92 | const char *n = option_to_longopt(*op, opts); | |
93 | if (n) | |
1d231190 | 94 | fprintf(stderr, " --%s", n); |
9bf13750 | 95 | else if (c_isgraph(*op)) |
1d231190 | 96 | fprintf(stderr, " -%c", *op); |
217d20a7 | 97 | } |
217d20a7 KZ |
98 | fputc('\n', stderr); |
99 | exit(OPTUTILS_EXIT_CODE); | |
100 | } | |
101 | break; | |
102 | } | |
103 | } | |
104 | } | |
105 | ||
732a6311 KZ |
106 | #endif |
107 |