2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
5 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
6 * Copyright (c) 1999-2018 The strace developers.
9 * SPDX-License-Identifier: LGPL-2.1-or-later
16 static inline enum xlat_style
17 get_xlat_style(enum xlat_style style)
19 if (xlat_verbose(style) == XLAT_STYLE_DEFAULT)
20 return style | xlat_verbosity;
25 static inline const char *
26 sprint_xlat_val(uint64_t val, enum xlat_style style)
28 static char buf[sizeof(val) * 3];
30 switch (xlat_format(style)) {
31 case XLAT_STYLE_FMT_D:
32 xsprintf(buf, "%" PRId64, val);
35 case XLAT_STYLE_FMT_U:
36 xsprintf(buf, "%" PRIu64, val);
39 case XLAT_STYLE_FMT_X:
40 xsprintf(buf, "%#" PRIx64, val);
48 print_xlat_val(uint64_t val, enum xlat_style style)
50 tprints(sprint_xlat_val(val, style));
54 xlat_bsearch_compare(const void *a, const void *b)
56 const uint64_t val1 = *(const uint64_t *) a;
57 const uint64_t val2 = ((const struct xlat_data *) b)->val;
58 return (val1 > val2) ? 1 : (val1 < val2) ? -1 : 0;
62 xlookup(const struct xlat *xlat, const uint64_t val)
64 static const struct xlat *x;
66 const struct xlat_data *e;
78 for (; idx < x->size; idx++)
79 if (x->data[idx].val == val)
80 return x->data[idx].str;
84 e = bsearch((const void *) &val,
88 xlat_bsearch_compare);
97 if (val == x->data[val].val)
98 return x->data[val].str;
99 if (x->data[val].val == 0)
100 break; /* a hole in the index */
101 error_func_msg("Unexpected xlat value %" PRIu64
102 " at index %" PRIu64 " (str %s)",
103 x->data[val].val, val,
109 error_func_msg("Invalid xlat type: %#x", x->type);
116 xlat_search_eq_or_less(const struct xlat *xlat, uint64_t *val)
118 const struct xlat_data *base = xlat->data;
119 const struct xlat_data *cur = xlat->data;
120 size_t nmemb = xlat->size;
122 for (; nmemb > 0; nmemb >>= 1) {
123 cur = base + (nmemb >> 1);
125 if (*val == cur->val)
128 if (*val > cur->val) {
134 if (*val < cur->val) {
135 if (cur > xlat->data)
146 xlookup_le(const struct xlat *xlat, uint64_t *val)
148 if (!xlat || !xlat->data)
151 switch (xlat->type) {
153 return xlat_search_eq_or_less(xlat, val);
155 #if 0 /* enable when used */
157 uint64_t best_hit = 0;
158 const char *str = NULL;
160 for (size_t idx = 0; idx < xlat->size; idx++) {
161 if (xlat->data[idx].val == *val)
162 return xlat->data[idx].str;
164 if (xlat->data[idx].val < *val
165 && xlat->data[idx].val > best_hit) {
166 best_hit = xlat->data[idx].val;
167 str = xlat->data[idx].str;
178 if (idx >= xlat->size) {
182 idx = xlat->size - 1;
186 if (idx == xlat->data[idx].val && xlat->data[idx].str) {
188 return xlat->data[idx].str;
190 if (xlat->data[idx].val == 0)
191 continue; /* a hole in the index */
192 error_func_msg("Unexpected xlat value %" PRIu64
193 " at index %zu (str %s)",
194 xlat->data[idx].val, idx,
195 xlat->data[idx].str);
202 error_func_msg("Invalid xlat type: %#x", xlat->type);
209 * Print entry in struct xlat table, if there.
211 * @param val Value to search a literal representation for.
212 * @param dflt String (abbreviated in comment syntax) which should be emitted
213 * if no appropriate xlat value has been found.
214 * @param style Style in which xlat value should be printed.
215 * @param xlat (And the following arguments) Pointers to arrays of xlat values.
216 * The last argument should be NULL.
217 * @return 1 if appropriate xlat value has been found, 0 otherwise.
220 printxvals_ex(const uint64_t val, const char *dflt, enum xlat_style style,
221 const struct xlat *xlat, ...)
223 static const struct xlat *last;
225 style = get_xlat_style(style);
227 if (xlat_verbose(style) == XLAT_STYLE_RAW) {
228 print_xlat_val(val, style);
232 const char *str = NULL;
235 va_start(args, xlat);
240 for (; xlat; xlat = va_arg(args, const struct xlat *)) {
243 str = xlookup(xlat, val);
246 if (xlat_verbose(style) == XLAT_STYLE_VERBOSE) {
247 print_xlat_val(val, style);
248 tprints_comment(str);
253 goto printxvals_ex_end;
257 /* No hits -- print raw # instead. */
258 print_xlat_val(val, style);
259 tprints_comment(dflt);
268 sprintxval_ex(char *const buf, const size_t size, const struct xlat *const x,
269 const unsigned int val, const char *const dflt,
270 enum xlat_style style)
272 style = get_xlat_style(style);
274 if (xlat_verbose(style) == XLAT_STYLE_RAW)
275 return xsnprintf(buf, size, "%s", sprint_xlat_val(val, style));
277 const char *const str = xlookup(x, val);
280 if (xlat_verbose(style) == XLAT_STYLE_VERBOSE)
281 return xsnprintf(buf, size, "%s /* %s */",
282 sprint_xlat_val(val, style), str);
284 return xsnprintf(buf, size, "%s", str);
287 return xsnprintf(buf, size, "%s /* %s */",
288 sprint_xlat_val(val, style), dflt);
290 return xsnprintf(buf, size, "%s", sprint_xlat_val(val, style));
294 * Interpret `xlat' as an array of flags.
295 * Print to static string the entries whose bits are on in `flags'
296 * Return static string. If 0 is provided as flags, and there is no flag that
297 * has the value of 0 (it should be the first in xlat table), return NULL.
300 * +------------+------------+---------+------------+
301 * | flags != 0 | xlat found | style | output |
302 * +------------+------------+---------+------------+
303 * | false | (any) | raw | <none> |
304 * | true | (any) | raw | VAL |
305 * +------------+------------+---------+------------+
306 * | false | false | abbrev | <none> |
307 * | true | false | abbrev | VAL |
308 * | (any) | true | abbrev | XLAT |
309 * +------------+------------+---------+------------+
310 * | false | false | verbose | <none> |
311 * | true | false | verbose | VAL |
312 * | (any) | true | verbose | VAL (XLAT) |
313 * +------------+------------+---------+------------+
316 sprintflags_ex(const char *prefix, const struct xlat *xlat, uint64_t flags,
317 char sep, enum xlat_style style)
319 static char outstr[1024];
323 outptr = stpcpy(outstr, prefix);
324 style = get_xlat_style(style);
326 if (xlat_verbose(style) == XLAT_STYLE_RAW) {
332 outptr = xappendstr(outstr, outptr, "%s",
333 sprint_xlat_val(flags, style));
338 if (flags == 0 && xlat->data->val == 0 && xlat->data->str) {
341 if (xlat_verbose(style) == XLAT_STYLE_VERBOSE) {
342 outptr = xappendstr(outstr, outptr, "0 /* %s */",
345 strcpy(outptr, xlat->data->str);
351 if (xlat_verbose(style) == XLAT_STYLE_VERBOSE && flags) {
356 outptr = xappendstr(outstr, outptr, "%s",
357 sprint_xlat_val(flags, style));
360 for (size_t idx = 0; flags && idx < xlat->size; idx++) {
361 if (xlat->data[idx].val && xlat->data[idx].str
362 && (flags & xlat->data[idx].val) == xlat->data[idx].val) {
365 } else if (xlat_verbose(style) == XLAT_STYLE_VERBOSE) {
366 outptr = stpcpy(outptr, " /* ");
369 outptr = stpcpy(outptr, xlat->data[idx].str);
372 flags &= ~xlat->data[idx].val;
379 if (found || xlat_verbose(style) != XLAT_STYLE_VERBOSE)
380 outptr = xappendstr(outstr, outptr, "%s",
381 sprint_xlat_val(flags, style));
387 if (found && xlat_verbose(style) == XLAT_STYLE_VERBOSE)
388 outptr = stpcpy(outptr, " */");
394 * Print flags from multiple xlat tables.
397 * +------------+--------------+------------+---------+------------+
398 * | flags != 0 | dflt != NULL | xlat found | style | output |
399 * +------------+--------------+------------+---------+------------+
400 * | false | false | (any) | raw | <none> |
401 * | false | true | (any) | raw | VAL |
402 * | true | (any) | (any) | raw | VAL |
403 * +------------+--------------+------------+---------+------------+
404 * | false | false | false | abbrev | <none> |
405 * | false | true | false | abbrev | VAL |
406 * | true | false | false | abbrev | VAL |
407 * | true | true | false | abbrev | VAL (DFLT) |
408 * | (any) | (any) | true | abbrev | XLAT |
409 * +------------+--------------+------------+---------+------------+
410 * | false | false | false | verbose | <none> |
411 * | false | true | false | verbose | VAL |
412 * | true | false | false | verbose | VAL |
413 * | true | true | false | verbose | VAL (DFLT) |
414 * | (any) | (any) | true | verbose | VAL (XLAT) |
415 * +------------+--------------+------------+---------+------------+
418 printflags_ex(uint64_t flags, const char *dflt, enum xlat_style style,
419 const struct xlat *xlat, ...)
421 style = get_xlat_style(style);
423 if (xlat_verbose(style) == XLAT_STYLE_RAW) {
425 print_xlat_val(flags, style);
432 const char *init_sep = "";
436 if (xlat_verbose(style) == XLAT_STYLE_VERBOSE) {
439 print_xlat_val(flags, style);
442 va_start(args, xlat);
443 for (; xlat; xlat = va_arg(args, const struct xlat *)) {
444 for (size_t idx = 0; (flags || !n) && idx < xlat->size; ++idx) {
445 uint64_t v = xlat->data[idx].val;
446 if (xlat->data[idx].str
447 && ((flags == v) || (v && (flags & v) == v))) {
448 if (xlat_verbose(style) == XLAT_STYLE_VERBOSE
452 (n++ ? "|" : init_sep),
453 xlat->data[idx].str);
465 print_xlat_val(flags, style);
469 if (xlat_verbose(style) == XLAT_STYLE_VERBOSE)
473 if (xlat_verbose(style) != XLAT_STYLE_VERBOSE)
474 print_xlat_val(flags, style);
475 tprints_comment(dflt);
486 print_xlat_ex(const uint64_t val, const char *str, enum xlat_style style)
488 bool default_str = style & PXF_DEFAULT_STR;
489 style = get_xlat_style(style);
491 switch (xlat_verbose(style)) {
492 case XLAT_STYLE_ABBREV:
495 print_xlat_val(val, style);
496 tprints_comment(str);
502 ATTRIBUTE_FALLTHROUGH;
505 print_xlat_val(val, style);
509 error_func_msg("Unexpected style value of %#x", style);
510 ATTRIBUTE_FALLTHROUGH;
512 case XLAT_STYLE_VERBOSE:
513 print_xlat_val(val, style);
514 tprints_comment(str);