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