Use side_ptr_t for side_type_null attr pointer
[libside.git] / src / tracer.c
index 864799ed98176e67c8229d43e843b779a4fafcd5..5e3157f8ab7d77afa0461ee193c7d8c88f7d6516 100644 (file)
@@ -9,6 +9,7 @@
 #include <stdio.h>
 #include <stdbool.h>
 #include <string.h>
+#include <iconv.h>
 
 #include <side/trace.h>
 
@@ -29,6 +30,8 @@ static struct side_tracer_handle *tracer_handle;
 static
 void tracer_print_struct(const struct side_type *type_desc, const struct side_arg_vec *side_arg_vec);
 static
+void tracer_print_variant(const struct side_type *type_desc, const struct side_arg_variant *side_arg_variant);
+static
 void tracer_print_array(const struct side_type *type_desc, const struct side_arg_vec *side_arg_vec);
 static
 void tracer_print_vla(const struct side_type *type_desc, const struct side_arg_vec *side_arg_vec);
@@ -46,6 +49,8 @@ uint32_t tracer_print_gather_integer_type(const struct side_type_gather *type_ga
 static
 uint32_t tracer_print_gather_float_type(const struct side_type_gather *type_gather, const void *_ptr);
 static
+uint32_t tracer_print_gather_string_type(const struct side_type_gather *type_gather, const void *_ptr);
+static
 uint32_t tracer_print_gather_enum_type(const struct side_type_gather *type_gather, const void *_ptr);
 static
 uint32_t tracer_print_gather_struct(const struct side_type_gather *type_gather, const void *_ptr);
@@ -57,6 +62,125 @@ uint32_t tracer_print_gather_vla(const struct side_type_gather *type_gather, con
 static
 void tracer_print_type(const struct side_type *type_desc, const struct side_arg *item);
 
+static
+void tracer_convert_string_to_utf8(const void *p, uint8_t unit_size, enum side_type_label_byte_order byte_order,
+               size_t *strlen_with_null,
+               char **output_str)
+{
+       size_t ret, inbytesleft = 0, outbytesleft, bufsize;
+       const char *str = p, *fromcode;
+       char *inbuf = (char *) p, *outbuf, *buf;
+       iconv_t cd;
+
+       switch (unit_size) {
+       case 1:
+               if (strlen_with_null)
+                       *strlen_with_null = strlen(str) + 1;
+               *output_str = (char *) str;
+               return;
+       case 2:
+       {
+               const uint16_t *p16 = p;
+
+               switch (byte_order) {
+               case SIDE_TYPE_BYTE_ORDER_LE:
+               {
+                       fromcode = "UTF-16LE";
+                       break;
+               }
+               case SIDE_TYPE_BYTE_ORDER_BE:
+               {
+                       fromcode = "UTF-16BE";
+                       break;
+               }
+               default:
+                       fprintf(stderr, "Unknown byte order\n");
+                       abort();
+               }
+               for (; *p16; p16++)
+                       inbytesleft += 2;
+               /*
+                * Worse case is U+FFFF UTF-16 (2 bytes) converting to
+                * { ef, bf, bf } UTF-8 (3 bytes).
+                */
+               bufsize = inbytesleft / 2 * 3 + 1;
+               break;
+       }
+       case 4:
+       {
+               const uint32_t *p32 = p;
+
+               switch (byte_order) {
+               case SIDE_TYPE_BYTE_ORDER_LE:
+               {
+                       fromcode = "UTF-32LE";
+                       break;
+               }
+               case SIDE_TYPE_BYTE_ORDER_BE:
+               {
+                       fromcode = "UTF-32BE";
+                       break;
+               }
+               default:
+                       fprintf(stderr, "Unknown byte order\n");
+                       abort();
+               }
+               for (; *p32; p32++)
+                       inbytesleft += 4;
+               /*
+                * Each 4-byte UTF-32 character converts to at most a
+                * 4-byte UTF-8 character.
+                */
+               bufsize = inbytesleft + 1;
+               break;
+       }
+       default:
+               fprintf(stderr, "Unknown string unit size %" PRIu8 "\n", unit_size);
+               abort();
+       }
+
+       cd = iconv_open("UTF8", fromcode);
+       if (cd == (iconv_t) -1) {
+               perror("iconv_open");
+               abort();
+       }
+       buf = malloc(bufsize);
+       if (!buf) {
+               abort();
+       }
+       outbuf = (char *) buf;
+       outbytesleft = bufsize;
+       ret = iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
+       if (ret == (size_t) -1) {
+               perror("iconv");
+               abort();
+       }
+       if (inbytesleft) {
+               fprintf(stderr, "Buffer too small to convert string input\n");
+               abort();
+       }
+       (*outbuf++) = '\0';
+       if (iconv_close(cd) == -1) {
+               perror("iconv_close");
+               abort();
+       }
+       if (strlen_with_null)
+               *strlen_with_null = outbuf - buf;
+       *output_str = buf;
+}
+
+static
+void tracer_print_string(const void *p, uint8_t unit_size, enum side_type_label_byte_order byte_order,
+               size_t *strlen_with_null)
+{
+       char *output_str = NULL;
+
+       tracer_convert_string_to_utf8(p, unit_size, byte_order, strlen_with_null, &output_str);
+       printf("\"%s\"", output_str);
+       if (output_str != p)
+               free(output_str);
+}
+
 static
 int64_t get_attr_integer_value(const struct side_attr *attr)
 {
@@ -102,8 +226,15 @@ enum tracer_display_base get_attr_display_base(const struct side_attr *_attr, ui
 
        for (i = 0; i < nr_attr; i++) {
                const struct side_attr *attr = &_attr[i];
-
-               if (!strcmp(attr->key, "std.integer.base")) {
+               char *utf8_str = NULL;
+               bool cmp;
+
+               tracer_convert_string_to_utf8(side_ptr_get(attr->key.p), attr->key.unit_size,
+                       attr->key.byte_order, NULL, &utf8_str);
+               cmp = strcmp(utf8_str, "std.integer.base");
+               if (utf8_str != side_ptr_get(attr->key.p))
+                       free(utf8_str);
+               if (!cmp) {
                        int64_t val = get_attr_integer_value(attr);
 
                        switch (val) {
@@ -127,7 +258,13 @@ enum tracer_display_base get_attr_display_base(const struct side_attr *_attr, ui
 static
 void tracer_print_attr_type(const char *separator, const struct side_attr *attr)
 {
-       printf("{ key%s \"%s\", value%s ", separator, attr->key, separator);
+       char *utf8_str = NULL;
+
+       tracer_convert_string_to_utf8(side_ptr_get(attr->key.p), attr->key.unit_size,
+               attr->key.byte_order, NULL, &utf8_str);
+       printf("{ key%s \"%s\", value%s ", separator, utf8_str, separator);
+       if (utf8_str != side_ptr_get(attr->key.p))
+               free(utf8_str);
        switch (attr->value.type) {
        case SIDE_ATTR_TYPE_BOOL:
                printf("%s", attr->value.u.bool_value ? "true" : "false");
@@ -189,7 +326,9 @@ void tracer_print_attr_type(const char *separator, const struct side_attr *attr)
                abort();
 #endif
        case SIDE_ATTR_TYPE_STRING:
-               printf("\"%s\"", (const char *)(uintptr_t) attr->value.u.string_value);
+               tracer_print_string(side_ptr_get(attr->value.u.string_value.p),
+                               attr->value.u.string_value.unit_size,
+                               attr->value.u.string_value.byte_order, NULL);
                break;
        default:
                fprintf(stderr, "ERROR: <UNKNOWN ATTRIBUTE TYPE>");
@@ -321,7 +460,7 @@ void print_enum_labels(const struct side_enum_mappings *mappings, union int64_va
                }
                if (v64.s >= mapping->range_begin && v64.s <= mapping->range_end) {
                        printf("%s", print_count++ ? ", " : "");
-                       printf("\"%s\"", mapping->label);
+                       tracer_print_string(side_ptr_get(mapping->label.p), mapping->label.unit_size, mapping->label.byte_order, NULL);
                }
        }
        if (!print_count)
@@ -450,7 +589,7 @@ void tracer_print_enum_bitmap(const struct side_type *type_desc,
 match:
                if (match) {
                        printf("%s", print_count++ ? ", " : "");
-                       printf("\"%s\"", mapping->label);
+                       tracer_print_string(side_ptr_get(mapping->label.p), mapping->label.unit_size, mapping->label.byte_order, NULL);
                }
        }
        if (!print_count)
@@ -765,7 +904,8 @@ void tracer_print_type(const struct side_type *type_desc, const struct side_arg
        switch (type) {
                /* Stack-copy basic types */
        case SIDE_TYPE_NULL:
-               tracer_print_type_header(":", type_desc->u.side_null.attr, type_desc->u.side_null.nr_attr);
+               tracer_print_type_header(":", side_ptr_get(type_desc->u.side_null.attr),
+                       type_desc->u.side_null.nr_attr);
                printf("<NULL TYPE>");
                break;
 
@@ -802,15 +942,21 @@ void tracer_print_type(const struct side_type *type_desc, const struct side_arg
                tracer_print_type_float(":", &type_desc->u.side_float, &item->u.side_static.float_value);
                break;
 
-       case SIDE_TYPE_STRING:
+       case SIDE_TYPE_STRING_UTF8:
+       case SIDE_TYPE_STRING_UTF16:
+       case SIDE_TYPE_STRING_UTF32:
                tracer_print_type_header(":", type_desc->u.side_string.attr, type_desc->u.side_string.nr_attr);
-               printf("\"%s\"", (const char *)(uintptr_t) item->u.side_static.string_value);
+               tracer_print_string((const void *)(uintptr_t) item->u.side_static.string_value,
+                               type_desc->u.side_string.unit_size, type_desc->u.side_string.byte_order, NULL);
                break;
 
                /* Stack-copy compound types */
        case SIDE_TYPE_STRUCT:
                tracer_print_struct(type_desc, item->u.side_static.side_struct);
                break;
+       case SIDE_TYPE_VARIANT:
+               tracer_print_variant(type_desc, item->u.side_static.side_variant);
+               break;
        case SIDE_TYPE_ARRAY:
                tracer_print_array(type_desc, item->u.side_static.side_array);
                break;
@@ -847,6 +993,9 @@ void tracer_print_type(const struct side_type *type_desc, const struct side_arg
        case SIDE_TYPE_GATHER_FLOAT:
                (void) tracer_print_gather_float_type(&type_desc->u.side_gather, item->u.side_static.side_float_gather_ptr);
                break;
+       case SIDE_TYPE_GATHER_STRING:
+               (void) tracer_print_gather_string_type(&type_desc->u.side_gather, item->u.side_static.side_string_gather_ptr);
+               break;
 
                /* Gather compound type */
        case SIDE_TYPE_GATHER_STRUCT:
@@ -915,6 +1064,46 @@ void tracer_print_struct(const struct side_type *type_desc, const struct side_ar
        printf(" }");
 }
 
+static
+void tracer_print_variant(const struct side_type *type_desc, const struct side_arg_variant *side_arg_variant)
+{
+       const struct side_type_variant *side_type_variant = type_desc->u.side_variant;
+       const struct side_type *selector_type = &side_type_variant->selector;
+       union int64_value v64;
+       uint32_t i;
+
+       if (selector_type->type != side_arg_variant->selector.type) {
+               fprintf(stderr, "ERROR: Unexpected variant selector type\n");
+               abort();
+       }
+       switch (selector_type->type) {
+       case SIDE_TYPE_U8:
+       case SIDE_TYPE_U16:
+       case SIDE_TYPE_U32:
+       case SIDE_TYPE_U64:
+       case SIDE_TYPE_S8:
+       case SIDE_TYPE_S16:
+       case SIDE_TYPE_S32:
+       case SIDE_TYPE_S64:
+               break;
+       default:
+               fprintf(stderr, "ERROR: Expecting integer variant selector type\n");
+               abort();
+       }
+       v64 = tracer_load_integer_value(&selector_type->u.side_integer,
+                       &side_arg_variant->selector.u.side_static.integer_value, 0, NULL);
+       for (i = 0; i < side_type_variant->nr_options; i++) {
+               const struct side_variant_option *option = &side_type_variant->options[i];
+
+               if (v64.s >= option->range_begin && v64.s <= option->range_end) {
+                       tracer_print_type(&option->side_type, &side_arg_variant->option);
+                       return;
+               }
+       }
+       fprintf(stderr, "ERROR: Variant selector value unknown %" PRId64 "\n", v64.s);
+       abort();
+}
+
 static
 void tracer_print_array(const struct side_type *type_desc, const struct side_arg_vec *side_arg_vec)
 {
@@ -961,7 +1150,7 @@ const char *tracer_gather_access(enum side_type_gather_access_mode access_mode,
                return ptr;
        case SIDE_TYPE_GATHER_ACCESS_POINTER:
                /* Dereference pointer */
-               memcpy(&ptr, ptr, sizeof(ptr));
+               memcpy(&ptr, ptr, sizeof(const char *));
                return ptr;
        default:
                abort();
@@ -1088,6 +1277,27 @@ uint32_t tracer_print_gather_float_type(const struct side_type_gather *type_gath
        return tracer_gather_size(access_mode, float_size_bytes);
 }
 
+static
+uint32_t tracer_print_gather_string_type(const struct side_type_gather *type_gather, const void *_ptr)
+{
+       enum side_type_gather_access_mode access_mode =
+               (enum side_type_gather_access_mode) type_gather->u.side_string.access_mode;
+       const char *ptr = (const char *) _ptr;
+       size_t string_len;
+
+       ptr = tracer_gather_access(access_mode, ptr + type_gather->u.side_string.offset);
+       tracer_print_type_header(":", type_gather->u.side_string.type.attr,
+                       type_gather->u.side_string.type.nr_attr);
+       if (ptr) {
+               tracer_print_string(ptr, type_gather->u.side_string.type.unit_size,
+                               type_gather->u.side_string.type.byte_order, &string_len);
+       } else {
+               printf("<NULL>");
+               string_len = type_gather->u.side_string.type.unit_size;
+       }
+       return tracer_gather_size(access_mode, string_len);
+}
+
 static
 uint32_t tracer_print_gather_type(const struct side_type *type_desc, const void *ptr)
 {
@@ -1113,6 +1323,9 @@ uint32_t tracer_print_gather_type(const struct side_type *type_desc, const void
        case SIDE_TYPE_GATHER_FLOAT:
                len = tracer_print_gather_float_type(&type_desc->u.side_gather, ptr);
                break;
+       case SIDE_TYPE_GATHER_STRING:
+               len = tracer_print_gather_string_type(&type_desc->u.side_gather, ptr);
+               break;
 
                /* Gather enum types */
        case SIDE_TYPE_GATHER_ENUM:
@@ -1445,7 +1658,8 @@ void tracer_print_dynamic(const struct side_arg *item)
        switch (item->type) {
                /* Dynamic basic types */
        case SIDE_TYPE_DYNAMIC_NULL:
-               tracer_print_type_header("::", item->u.side_dynamic.side_null.attr, item->u.side_dynamic.side_null.nr_attr);
+               tracer_print_type_header("::", side_ptr_get(item->u.side_dynamic.side_null.attr),
+                       item->u.side_dynamic.side_null.nr_attr);
                printf("<NULL TYPE>");
                break;
        case SIDE_TYPE_DYNAMIC_BOOL:
@@ -1469,7 +1683,9 @@ void tracer_print_dynamic(const struct side_arg *item)
                break;
        case SIDE_TYPE_DYNAMIC_STRING:
                tracer_print_type_header("::", item->u.side_dynamic.side_string.type.attr, item->u.side_dynamic.side_string.type.nr_attr);
-               printf("\"%s\"", (const char *)(uintptr_t) item->u.side_dynamic.side_string.value);
+               tracer_print_string((const char *)(uintptr_t) item->u.side_dynamic.side_string.value,
+                               item->u.side_dynamic.side_string.type.unit_size,
+                               item->u.side_dynamic.side_string.type.byte_order, NULL);
                break;
 
                /* Dynamic compound types */
@@ -1517,6 +1733,7 @@ void tracer_print_static_fields(const struct side_event_description *desc,
                printf(" ]");
 }
 
+static
 void tracer_call(const struct side_event_description *desc,
                const struct side_arg_vec *side_arg_vec,
                void *priv __attribute__((unused)))
@@ -1527,6 +1744,7 @@ void tracer_call(const struct side_event_description *desc,
        printf("\n");
 }
 
+static
 void tracer_call_variadic(const struct side_event_description *desc,
                const struct side_arg_vec *side_arg_vec,
                const struct side_arg_dynamic_struct *var_struct,
@@ -1552,8 +1770,10 @@ void tracer_call_variadic(const struct side_event_description *desc,
        printf("\n");
 }
 
+static
 void tracer_event_notification(enum side_tracer_notification notif,
-               struct side_event_description **events, uint32_t nr_events, void *priv)
+               struct side_event_description **events, uint32_t nr_events,
+               void *priv __attribute__((unused)))
 {
        uint32_t i;
        int ret;
@@ -1569,7 +1789,7 @@ void tracer_event_notification(enum side_tracer_notification notif,
                        continue;
                printf("provider: %s, event: %s\n",
                        event->provider_name, event->event_name);
-               if  (notif == SIDE_TRACER_NOTIFICATION_INSERT_EVENTS) {
+               if (notif == SIDE_TRACER_NOTIFICATION_INSERT_EVENTS) {
                        if (event->flags & SIDE_EVENT_FLAG_VARIADIC) {
                                ret = side_tracer_callback_variadic_register(event, tracer_call_variadic, NULL);
                                if (ret)
This page took 0.027613 seconds and 4 git commands to generate.