1 /* 2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk (at) cs.few.eur.nl> 3 * Copyright (c) 1993 Branko Lankester <branko (at) hacktic.nl> 4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs (at) world.std.com> 5 * Copyright (c) 1996-1999 Wichert Akkerman <wichert (at) cistron.nl> 6 * Copyright (c) 1999-2018 The strace developers. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. The name of the author may not be used to endorse or promote products 18 * derived from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include "defs.h" 33 #include "xstring.h" 34 #include <stdarg.h> 35 36 const char * 37 xlookup(const struct xlat *xlat, const uint64_t val) 38 { 39 for (; xlat->str != NULL; xlat++) 40 if (xlat->val == val) 41 return xlat->str; 42 return NULL; 43 } 44 45 static int 46 xlat_bsearch_compare(const void *a, const void *b) 47 { 48 const uint64_t val1 = *(const uint64_t *) a; 49 const uint64_t val2 = ((const struct xlat *) b)->val; 50 return (val1 > val2) ? 1 : (val1 < val2) ? -1 : 0; 51 } 52 53 const char * 54 xlat_search(const struct xlat *xlat, const size_t nmemb, const uint64_t val) 55 { 56 const struct xlat *e = 57 bsearch((const void *) &val, 58 xlat, nmemb, sizeof(*xlat), xlat_bsearch_compare); 59 60 return e ? e->str : NULL; 61 } 62 63 /** 64 * Print entry in struct xlat table, if there. 65 * 66 * @param val Value to search a literal representation for. 67 * @param dflt String (abbreviated in comment syntax) which should be emitted 68 * if no appropriate xlat value has been found. 69 * @param xlat (And the following arguments) Pointers to arrays of xlat values. 70 * The last argument should be NULL. 71 * @return 1 if appropriate xlat value has been found, 0 otherwise. 72 */ 73 int 74 printxvals(const uint64_t val, const char *dflt, const struct xlat *xlat, ...) 75 { 76 va_list args; 77 78 va_start(args, xlat); 79 for (; xlat; xlat = va_arg(args, const struct xlat *)) { 80 const char *str = xlookup(xlat, val); 81 82 if (str) { 83 tprints(str); 84 va_end(args); 85 return 1; 86 } 87 } 88 /* No hits -- print raw # instead. */ 89 tprintf("%#" PRIx64, val); 90 tprints_comment(dflt); 91 92 va_end(args); 93 94 return 0; 95 } 96 97 int 98 sprintxval(char *const buf, const size_t size, const struct xlat *const x, 99 const unsigned int val, const char *const dflt) 100 { 101 const char *const str = xlookup(x, val); 102 103 if (str) 104 return xsnprintf(buf, size, "%s", str); 105 if (dflt) 106 return xsnprintf(buf, size, "%#x /* %s */", val, dflt); 107 108 return xsnprintf(buf, size, "%#x", val); 109 } 110 111 /** 112 * Print entry in sorted struct xlat table, if it is there. 113 * 114 * @param xlat Pointer to an array of xlat values (not terminated with 115 * XLAT_END). 116 * @param xlat_size Number of xlat elements present in array (usually ARRAY_SIZE 117 * if array is declared in the unit's scope and not 118 * terminated with XLAT_END). 119 * @param val Value to search literal representation for. 120 * @param dflt String (abbreviated in comment syntax) which should be 121 * emitted if no appropriate xlat value has been found. 122 * @return 1 if appropriate xlat value has been found, 0 123 * otherwise. 124 */ 125 int 126 printxval_searchn(const struct xlat *xlat, size_t xlat_size, uint64_t val, 127 const char *dflt) 128 { 129 const char *s = xlat_search(xlat, xlat_size, val); 130 131 if (s) { 132 tprints(s); 133 return 1; 134 } 135 136 tprintf("%#" PRIx64, val); 137 tprints_comment(dflt); 138 139 return 0; 140 } 141 142 /* 143 * Interpret `xlat' as an array of flags 144 * print the entries whose bits are on in `flags' 145 */ 146 void 147 addflags(const struct xlat *xlat, uint64_t flags) 148 { 149 for (; xlat->str; xlat++) { 150 if (xlat->val && (flags & xlat->val) == xlat->val) { 151 tprintf("|%s", xlat->str); 152 flags &= ~xlat->val; 153 } 154 } 155 if (flags) { 156 tprintf("|%#" PRIx64, flags); 157 } 158 } 159 160 /* 161 * Interpret `xlat' as an array of flags. 162 * Print to static string the entries whose bits are on in `flags' 163 * Return static string. If 0 is provided as flags, and there is no flag that 164 * has the value of 0 (it should be the first in xlat table), return NULL. 165 */ 166 const char * 167 sprintflags(const char *prefix, const struct xlat *xlat, uint64_t flags) 168 { 169 static char outstr[1024]; 170 char *outptr; 171 int found = 0; 172 173 outptr = stpcpy(outstr, prefix); 174 175 if (flags == 0 && xlat->val == 0 && xlat->str) { 176 strcpy(outptr, xlat->str); 177 return outstr; 178 } 179 180 for (; xlat->str; xlat++) { 181 if (xlat->val && (flags & xlat->val) == xlat->val) { 182 if (found) 183 *outptr++ = '|'; 184 outptr = stpcpy(outptr, xlat->str); 185 found = 1; 186 flags &= ~xlat->val; 187 if (!flags) 188 break; 189 } 190 } 191 192 if (flags) { 193 if (found) 194 *outptr++ = '|'; 195 outptr = xappendstr(outstr, outptr, "%#" PRIx64, flags); 196 } else { 197 if (!found) 198 return NULL; 199 } 200 201 return outstr; 202 } 203 204 int 205 printflags_ex(uint64_t flags, const char *dflt, const struct xlat *xlat, ...) 206 { 207 unsigned int n = 0; 208 va_list args; 209 210 va_start(args, xlat); 211 for (; xlat; xlat = va_arg(args, const struct xlat *)) { 212 for (; (flags || !n) && xlat->str; ++xlat) { 213 if ((flags == xlat->val) || 214 (xlat->val && (flags & xlat->val) == xlat->val)) { 215 tprintf("%s%s", (n++ ? "|" : ""), xlat->str); 216 flags &= ~xlat->val; 217 } 218 if (!flags) 219 break; 220 } 221 } 222 va_end(args); 223 224 if (n) { 225 if (flags) { 226 tprintf("|%#" PRIx64, flags); 227 n++; 228 } 229 } else { 230 if (flags) { 231 tprintf("%#" PRIx64, flags); 232 tprints_comment(dflt); 233 } else { 234 if (dflt) 235 tprints("0"); 236 } 237 } 238 239 return n; 240 } 241