Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-or-later */
0002 #ifndef UTIL_H
0003 #define UTIL_H
0004 
0005 #include <stdlib.h>
0006 #include <stdarg.h>
0007 #include <stdbool.h>
0008 #include <getopt.h>
0009 
0010 /*
0011  * Copyright 2011 The Chromium Authors, All Rights Reserved.
0012  * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc.
0013  */
0014 
0015 #ifdef __GNUC__
0016 #if __GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)
0017 #define PRINTF(i, j)    __attribute__((format (gnu_printf, i, j)))
0018 #else
0019 #define PRINTF(i, j)    __attribute__((format (printf, i, j)))
0020 #endif
0021 #define NORETURN    __attribute__((noreturn))
0022 #else
0023 #define PRINTF(i, j)
0024 #define NORETURN
0025 #endif
0026 
0027 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
0028 
0029 #define stringify(s)    stringify_(s)
0030 #define stringify_(s)   #s
0031 
0032 static inline void NORETURN PRINTF(1, 2) die(const char *str, ...)
0033 {
0034     va_list ap;
0035 
0036     va_start(ap, str);
0037     fprintf(stderr, "FATAL ERROR: ");
0038     vfprintf(stderr, str, ap);
0039     va_end(ap);
0040     exit(1);
0041 }
0042 
0043 static inline void *xmalloc(size_t len)
0044 {
0045     void *new = malloc(len);
0046 
0047     if (!new)
0048         die("malloc() failed\n");
0049 
0050     return new;
0051 }
0052 
0053 static inline void *xrealloc(void *p, size_t len)
0054 {
0055     void *new = realloc(p, len);
0056 
0057     if (!new)
0058         die("realloc() failed (len=%zd)\n", len);
0059 
0060     return new;
0061 }
0062 
0063 extern char *xstrdup(const char *s);
0064 
0065 extern int PRINTF(2, 3) xasprintf(char **strp, const char *fmt, ...);
0066 extern int PRINTF(2, 3) xasprintf_append(char **strp, const char *fmt, ...);
0067 extern int xavsprintf_append(char **strp, const char *fmt, va_list ap);
0068 extern char *join_path(const char *path, const char *name);
0069 
0070 /**
0071  * Check a property of a given length to see if it is all printable and
0072  * has a valid terminator. The property can contain either a single string,
0073  * or multiple strings each of non-zero length.
0074  *
0075  * @param data  The string to check
0076  * @param len   The string length including terminator
0077  * @return 1 if a valid printable string, 0 if not
0078  */
0079 bool util_is_printable_string(const void *data, int len);
0080 
0081 /*
0082  * Parse an escaped character starting at index i in string s.  The resulting
0083  * character will be returned and the index i will be updated to point at the
0084  * character directly after the end of the encoding, this may be the '\0'
0085  * terminator of the string.
0086  */
0087 char get_escape_char(const char *s, int *i);
0088 
0089 /**
0090  * Read a device tree file into a buffer. This will report any errors on
0091  * stderr.
0092  *
0093  * @param filename  The filename to read, or - for stdin
0094  * @param len       If non-NULL, the amount of data we managed to read
0095  * @return Pointer to allocated buffer containing fdt, or NULL on error
0096  */
0097 char *utilfdt_read(const char *filename, size_t *len);
0098 
0099 /**
0100  * Read a device tree file into a buffer. Does not report errors, but only
0101  * returns them. The value returned can be passed to strerror() to obtain
0102  * an error message for the user.
0103  *
0104  * @param filename  The filename to read, or - for stdin
0105  * @param buffp     Returns pointer to buffer containing fdt
0106  * @param len       If non-NULL, the amount of data we managed to read
0107  * @return 0 if ok, else an errno value representing the error
0108  */
0109 int utilfdt_read_err(const char *filename, char **buffp, size_t *len);
0110 
0111 /**
0112  * Write a device tree buffer to a file. This will report any errors on
0113  * stderr.
0114  *
0115  * @param filename  The filename to write, or - for stdout
0116  * @param blob      Pointer to buffer containing fdt
0117  * @return 0 if ok, -1 on error
0118  */
0119 int utilfdt_write(const char *filename, const void *blob);
0120 
0121 /**
0122  * Write a device tree buffer to a file. Does not report errors, but only
0123  * returns them. The value returned can be passed to strerror() to obtain
0124  * an error message for the user.
0125  *
0126  * @param filename  The filename to write, or - for stdout
0127  * @param blob      Pointer to buffer containing fdt
0128  * @return 0 if ok, else an errno value representing the error
0129  */
0130 int utilfdt_write_err(const char *filename, const void *blob);
0131 
0132 /**
0133  * Decode a data type string. The purpose of this string
0134  *
0135  * The string consists of an optional character followed by the type:
0136  *  Modifier characters:
0137  *      hh or b 1 byte
0138  *      h   2 byte
0139  *      l   4 byte, default
0140  *
0141  *  Type character:
0142  *      s   string
0143  *      i   signed integer
0144  *      u   unsigned integer
0145  *      x   hex
0146  *
0147  * TODO: Implement ll modifier (8 bytes)
0148  * TODO: Implement o type (octal)
0149  *
0150  * @param fmt       Format string to process
0151  * @param type      Returns type found(s/d/u/x), or 0 if none
0152  * @param size      Returns size found(1,2,4,8) or 4 if none
0153  * @return 0 if ok, -1 on error (no type given, or other invalid format)
0154  */
0155 int utilfdt_decode_type(const char *fmt, int *type, int *size);
0156 
0157 /*
0158  * This is a usage message fragment for the -t option. It is the format
0159  * supported by utilfdt_decode_type.
0160  */
0161 
0162 #define USAGE_TYPE_MSG \
0163     "<type>\ts=string, i=int, u=unsigned, x=hex\n" \
0164     "\tOptional modifier prefix:\n" \
0165     "\t\thh or b=byte, h=2 byte, l=4 byte (default)";
0166 
0167 /**
0168  * Print property data in a readable format to stdout
0169  *
0170  * Properties that look like strings will be printed as strings. Otherwise
0171  * the data will be displayed either as cells (if len is a multiple of 4
0172  * bytes) or bytes.
0173  *
0174  * If len is 0 then this function does nothing.
0175  *
0176  * @param data  Pointers to property data
0177  * @param len   Length of property data
0178  */
0179 void utilfdt_print_data(const char *data, int len);
0180 
0181 /**
0182  * Show source version and exit
0183  */
0184 void NORETURN util_version(void);
0185 
0186 /**
0187  * Show usage and exit
0188  *
0189  * This helps standardize the output of various utils.  You most likely want
0190  * to use the usage() helper below rather than call this.
0191  *
0192  * @param errmsg    If non-NULL, an error message to display
0193  * @param synopsis  The initial example usage text (and possible examples)
0194  * @param short_opts    The string of short options
0195  * @param long_opts The structure of long options
0196  * @param opts_help An array of help strings (should align with long_opts)
0197  */
0198 void NORETURN util_usage(const char *errmsg, const char *synopsis,
0199              const char *short_opts,
0200              struct option const long_opts[],
0201              const char * const opts_help[]);
0202 
0203 /**
0204  * Show usage and exit
0205  *
0206  * If you name all your usage variables with usage_xxx, then you can call this
0207  * help macro rather than expanding all arguments yourself.
0208  *
0209  * @param errmsg    If non-NULL, an error message to display
0210  */
0211 #define usage(errmsg) \
0212     util_usage(errmsg, usage_synopsis, usage_short_opts, \
0213            usage_long_opts, usage_opts_help)
0214 
0215 /**
0216  * Call getopt_long() with standard options
0217  *
0218  * Since all util code runs getopt in the same way, provide a helper.
0219  */
0220 #define util_getopt_long() getopt_long(argc, argv, usage_short_opts, \
0221                        usage_long_opts, NULL)
0222 
0223 /* Helper for aligning long_opts array */
0224 #define a_argument required_argument
0225 
0226 /* Helper for usage_short_opts string constant */
0227 #define USAGE_COMMON_SHORT_OPTS "hV"
0228 
0229 /* Helper for usage_long_opts option array */
0230 #define USAGE_COMMON_LONG_OPTS \
0231     {"help",      no_argument, NULL, 'h'}, \
0232     {"version",   no_argument, NULL, 'V'}, \
0233     {NULL,        no_argument, NULL, 0x0}
0234 
0235 /* Helper for usage_opts_help array */
0236 #define USAGE_COMMON_OPTS_HELP \
0237     "Print this help and exit", \
0238     "Print version and exit", \
0239     NULL
0240 
0241 /* Helper for getopt case statements */
0242 #define case_USAGE_COMMON_FLAGS \
0243     case 'h': usage(NULL); \
0244     case 'V': util_version(); \
0245     case '?': usage("unknown option");
0246 
0247 #endif /* UTIL_H */