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