]> granicus.if.org Git - strace/commitdiff
Add support for value-indexed xlats
authorEugene Syromyatnikov <evgsyr@gmail.com>
Mon, 2 Apr 2018 18:01:56 +0000 (20:01 +0200)
committerDmitry V. Levin <ldv@altlinux.org>
Fri, 27 Apr 2018 00:56:25 +0000 (00:56 +0000)
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.

defs.h
xlat.c
xlat/gen.sh

diff --git a/defs.h b/defs.h
index b2d683db5d4d5a201d58d3ab4d9668b5a7c435ac..72789e26560b65642d751f86abb3c6bb2a7ca492 100644 (file)
--- 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 d52d1b10887b104ec0649710f81ca96d6f36bf76..476a89cd7ce1ea1cc4523835249b8bf594674514 100644 (file)
--- 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'
index 170163cb9aea5fa79ae1adff3ec1e3dd5e09ff1c..aff79922d8d207324e049a3b79de96c4d5a9fa6d 100755 (executable)
@@ -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 }"
                        ;;