^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* SPDX-License-Identifier: GPL-2.0-or-later */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #ifndef UTIL_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #define UTIL_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <stdarg.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <stdbool.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <getopt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Copyright 2011 The Chromium Authors, All Rights Reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #ifdef __GNUC__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #ifdef __clang__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #define PRINTF(i, j) __attribute__((format (printf, i, j)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define PRINTF(i, j) __attribute__((format (gnu_printf, i, j)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define NORETURN __attribute__((noreturn))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define PRINTF(i, j)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define NORETURN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define stringify(s) stringify_(s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define stringify_(s) #s
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) static inline void NORETURN PRINTF(1, 2) die(const char *str, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) va_list ap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) va_start(ap, str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) fprintf(stderr, "FATAL ERROR: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) vfprintf(stderr, str, ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) va_end(ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) exit(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) static inline void *xmalloc(size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) void *new = malloc(len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) if (!new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) die("malloc() failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) return new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) static inline void *xrealloc(void *p, size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) void *new = realloc(p, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) if (!new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) die("realloc() failed (len=%zd)\n", len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) return new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) extern char *xstrdup(const char *s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) extern int PRINTF(2, 3) xasprintf(char **strp, const char *fmt, ...);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) extern int PRINTF(2, 3) xasprintf_append(char **strp, const char *fmt, ...);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) extern int xavsprintf_append(char **strp, const char *fmt, va_list ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) extern char *join_path(const char *path, const char *name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * Check a property of a given length to see if it is all printable and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * has a valid terminator. The property can contain either a single string,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * or multiple strings each of non-zero length.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * @param data The string to check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) * @param len The string length including terminator
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) * @return 1 if a valid printable string, 0 if not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) bool util_is_printable_string(const void *data, int len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) * Parse an escaped character starting at index i in string s. The resulting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * character will be returned and the index i will be updated to point at the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) * character directly after the end of the encoding, this may be the '\0'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * terminator of the string.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) char get_escape_char(const char *s, int *i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) * Read a device tree file into a buffer. This will report any errors on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) * stderr.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) * @param filename The filename to read, or - for stdin
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * @param len If non-NULL, the amount of data we managed to read
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * @return Pointer to allocated buffer containing fdt, or NULL on error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) char *utilfdt_read(const char *filename, size_t *len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * Read a device tree file into a buffer. Does not report errors, but only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * returns them. The value returned can be passed to strerror() to obtain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) * an error message for the user.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) * @param filename The filename to read, or - for stdin
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) * @param buffp Returns pointer to buffer containing fdt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * @param len If non-NULL, the amount of data we managed to read
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) * @return 0 if ok, else an errno value representing the error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) int utilfdt_read_err(const char *filename, char **buffp, size_t *len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * Write a device tree buffer to a file. This will report any errors on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) * stderr.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) * @param filename The filename to write, or - for stdout
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * @param blob Pointer to buffer containing fdt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * @return 0 if ok, -1 on error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) int utilfdt_write(const char *filename, const void *blob);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) * Write a device tree buffer to a file. Does not report errors, but only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * returns them. The value returned can be passed to strerror() to obtain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * an error message for the user.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * @param filename The filename to write, or - for stdout
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) * @param blob Pointer to buffer containing fdt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) * @return 0 if ok, else an errno value representing the error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) int utilfdt_write_err(const char *filename, const void *blob);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) * Decode a data type string. The purpose of this string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) * The string consists of an optional character followed by the type:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) * Modifier characters:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) * hh or b 1 byte
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) * h 2 byte
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) * l 4 byte, default
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) * Type character:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * s string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * i signed integer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * u unsigned integer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) * x hex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) * TODO: Implement ll modifier (8 bytes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) * TODO: Implement o type (octal)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) * @param fmt Format string to process
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) * @param type Returns type found(s/d/u/x), or 0 if none
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) * @param size Returns size found(1,2,4,8) or 4 if none
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) * @return 0 if ok, -1 on error (no type given, or other invalid format)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) int utilfdt_decode_type(const char *fmt, int *type, int *size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) * This is a usage message fragment for the -t option. It is the format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) * supported by utilfdt_decode_type.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) #define USAGE_TYPE_MSG \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) "<type>\ts=string, i=int, u=unsigned, x=hex\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) "\tOptional modifier prefix:\n" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) "\t\thh or b=byte, h=2 byte, l=4 byte (default)";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) * Print property data in a readable format to stdout
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * Properties that look like strings will be printed as strings. Otherwise
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) * the data will be displayed either as cells (if len is a multiple of 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) * bytes) or bytes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * If len is 0 then this function does nothing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) * @param data Pointers to property data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) * @param len Length of property data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) void utilfdt_print_data(const char *data, int len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) * Show source version and exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) void NORETURN util_version(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) * Show usage and exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) * This helps standardize the output of various utils. You most likely want
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) * to use the usage() helper below rather than call this.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) * @param errmsg If non-NULL, an error message to display
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) * @param synopsis The initial example usage text (and possible examples)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) * @param short_opts The string of short options
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) * @param long_opts The structure of long options
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * @param opts_help An array of help strings (should align with long_opts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) void NORETURN util_usage(const char *errmsg, const char *synopsis,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) const char *short_opts,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) struct option const long_opts[],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) const char * const opts_help[]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) * Show usage and exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) * If you name all your usage variables with usage_xxx, then you can call this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) * help macro rather than expanding all arguments yourself.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) * @param errmsg If non-NULL, an error message to display
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) #define usage(errmsg) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) util_usage(errmsg, usage_synopsis, usage_short_opts, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) usage_long_opts, usage_opts_help)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) * Call getopt_long() with standard options
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) * Since all util code runs getopt in the same way, provide a helper.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) #define util_getopt_long() getopt_long(argc, argv, usage_short_opts, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) usage_long_opts, NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) /* Helper for aligning long_opts array */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) #define a_argument required_argument
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) /* Helper for usage_short_opts string constant */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) #define USAGE_COMMON_SHORT_OPTS "hV"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) /* Helper for usage_long_opts option array */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) #define USAGE_COMMON_LONG_OPTS \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) {"help", no_argument, NULL, 'h'}, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) {"version", no_argument, NULL, 'V'}, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) {NULL, no_argument, NULL, 0x0}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) /* Helper for usage_opts_help array */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) #define USAGE_COMMON_OPTS_HELP \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) "Print this help and exit", \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) "Print version and exit", \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) /* Helper for getopt case statements */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) #define case_USAGE_COMMON_FLAGS \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) case 'h': usage(NULL); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) case 'V': util_version(); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) case '?': usage("unknown option");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) #endif /* UTIL_H */