From: Eugene Syromyatnikov <evgsyr@gmail.com> Date: Mon, 2 Apr 2018 18:01:56 +0000 (+0200) Subject: Add support for value-indexed xlats X-Git-Tag: v4.23~263 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=25d6ed1600eed45a485879113d1c6846b06b8bdc;p=strace Add support for value-indexed xlats There are quite a few xlats that start from 0 and not too sparse, we can push the search time for them down to O(1). * defs.h (printxval_indexn_ex): New declaration. (printxval_indexn, printxval_index, printxval_index_ex): New macros. * xlat.c (printxval_sized): Rename from printxval_searchn_ex, add fn argument, call it instead of xlat_search. (printxval_searchn_ex): Implement as a thin wrapper around printxval_sized using xlat_search as a search function. (xlat_idx): New function. (printxval_indexn_ex): New function, a thin wrapper around printxval_sized using xlat_idx as a search function. * xlat/gen.sh: Add support for "#value_indexed" directive. --- diff --git a/defs.h b/defs.h index b2d683db..72789e26 100644 --- a/defs.h +++ b/defs.h @@ -645,6 +645,16 @@ extern int printxval_searchn_ex(const struct xlat *xlat, size_t xlat_size, #define printxval_search_ex(xlat__, val__, dflt__) \ printxval_searchn_ex((xlat__), ARRAY_SIZE(xlat__) - 1, (val__), \ (dflt__), XLAT_STYLE_DEFAULT) +extern int printxval_indexn_ex(const struct xlat *xlat, size_t xlat_size, + uint64_t val, const char *dflt, enum xlat_style style); +#define printxval_indexn(xlat_, xlat_size_, val_, dflt_) \ + printxval_indexn_ex((xlat_), (xlat_size_), (val_), (dflt_), \ + XLAT_STYLE_DEFAULT) +#define printxval_index(xlat__, val__, dflt__) \ + printxval_indexn(xlat__, ARRAY_SIZE(xlat__) - 1, val__, dflt__) +#define printxval_index_ex(xlat__, val__, dflt__) \ + printxval_indexn_ex((xlat__), ARRAY_SIZE(xlat__) - 1, (val__), \ + (dflt__), XLAT_STYLE_DEFAULT) extern int sprintxval_ex(char *buf, size_t size, const struct xlat *xlat, unsigned int val, const char *dflt, enum xlat_style style); diff --git a/xlat.c b/xlat.c index d52d1b10..476a89cd 100644 --- a/xlat.c +++ b/xlat.c @@ -184,12 +184,14 @@ sprintxval_ex(char *const buf, const size_t size, const struct xlat *const x, * @param dflt String (abbreviated in comment syntax) which should be * emitted if no appropriate xlat value has been found. * @param style Style in which xlat value should be printed. + * @param fn Search function. * @return 1 if appropriate xlat value has been found, 0 * otherwise. */ -int -printxval_searchn_ex(const struct xlat *xlat, size_t xlat_size, uint64_t val, - const char *dflt, enum xlat_style style) +static int +printxval_sized(const struct xlat *xlat, size_t xlat_size, uint64_t val, + const char *dflt, enum xlat_style style, + const char *(* fn)(const struct xlat *, size_t, uint64_t)) { style = get_xlat_style(style); @@ -198,7 +200,7 @@ printxval_searchn_ex(const struct xlat *xlat, size_t xlat_size, uint64_t val, return 0; } - const char *s = xlat_search(xlat, xlat_size, val); + const char *s = fn(xlat, xlat_size, val); if (s) { if (xlat_verbose(style) == XLAT_STYLE_VERBOSE) { @@ -216,6 +218,37 @@ printxval_searchn_ex(const struct xlat *xlat, size_t xlat_size, uint64_t val, return 0; } +int +printxval_searchn_ex(const struct xlat *xlat, size_t xlat_size, uint64_t val, + const char *dflt, enum xlat_style style) +{ + return printxval_sized(xlat, xlat_size, val, dflt, style, + xlat_search); +} + +static const char * +xlat_idx(const struct xlat *xlat, size_t nmemb, uint64_t val) +{ + if (val >= nmemb) + return NULL; + + if (val != xlat[val].val) { + error_func_msg("Unexpected xlat value %" PRIu64 + " at index %" PRIu64, + xlat[val].val, val); + return NULL; + } + + return xlat[val].str; +} + +int +printxval_indexn_ex(const struct xlat *xlat, size_t xlat_size, uint64_t val, + const char *dflt, enum xlat_style style) +{ + return printxval_sized(xlat, xlat_size, val, dflt, style, xlat_idx); +} + /* * Interpret `xlat' as an array of flags. * Print to static string the entries whose bits are on in `flags' diff --git a/xlat/gen.sh b/xlat/gen.sh index 170163cb..aff79922 100755 --- a/xlat/gen.sh +++ b/xlat/gen.sh @@ -65,6 +65,7 @@ print_xlat() local val val="$1"; shift + [ 1 = "$value_indexed" ] && printf " [%s] =" "${val}" if [ -z "${val_type-}" ]; then echo " XLAT(${val})," else @@ -78,6 +79,7 @@ print_xlat_pair() val="$1"; shift str="$1"; shift + [ 1 = "$value_indexed" ] && printf " [%s] =" "${val}" if [ -z "${val_type-}" ]; then echo " XLAT_PAIR(${val}, \"${str}\")," else @@ -123,6 +125,8 @@ gen_header() local decl="extern const struct xlat ${name}[];" local in_defs= in_mpers= + value_indexed=0 + if grep -F -x "$decl" "$defs" > /dev/null; then in_defs=1 elif grep -F -x "$decl" "$mpers" > /dev/null; then @@ -151,6 +155,9 @@ gen_header() '#val_type '*) # to be processed during 2nd pass ;; + '#value_indexed') + value_indexed=1 + ;; '#'*) echo "${line}" ;; @@ -206,6 +213,8 @@ gen_header() '#unconditional') unconditional=1 ;; + '#value_indexed') + ;; '#val_type '*) val_type="${line#\#val_type }" ;;