tools lib traceevent: Handle %z in bprint format
[cascardo/linux.git] / tools / lib / traceevent / event-parse.c
index afe20ed..bdb1dd6 100644 (file)
@@ -304,7 +304,10 @@ int pevent_register_comm(struct pevent *pevent, const char *comm, int pid)
        if (!item)
                return -1;
 
-       item->comm = strdup(comm);
+       if (comm)
+               item->comm = strdup(comm);
+       else
+               item->comm = strdup("<...>");
        if (!item->comm) {
                free(item);
                return -1;
@@ -318,9 +321,14 @@ int pevent_register_comm(struct pevent *pevent, const char *comm, int pid)
        return 0;
 }
 
-void pevent_register_trace_clock(struct pevent *pevent, char *trace_clock)
+int pevent_register_trace_clock(struct pevent *pevent, const char *trace_clock)
 {
-       pevent->trace_clock = trace_clock;
+       pevent->trace_clock = strdup(trace_clock);
+       if (!pevent->trace_clock) {
+               errno = ENOMEM;
+               return -1;
+       }
+       return 0;
 }
 
 struct func_map {
@@ -2014,6 +2022,38 @@ process_entry(struct event_format *event __maybe_unused, struct print_arg *arg,
        return EVENT_ERROR;
 }
 
+static int alloc_and_process_delim(struct event_format *event, char *next_token,
+                                  struct print_arg **print_arg)
+{
+       struct print_arg *field;
+       enum event_type type;
+       char *token;
+       int ret = 0;
+
+       field = alloc_arg();
+       if (!field) {
+               do_warning_event(event, "%s: not enough memory!", __func__);
+               errno = ENOMEM;
+               return -1;
+       }
+
+       type = process_arg(event, field, &token);
+
+       if (test_type_token(type, token, EVENT_DELIM, next_token)) {
+               errno = EINVAL;
+               ret = -1;
+               free_arg(field);
+               goto out_free_token;
+       }
+
+       *print_arg = field;
+
+out_free_token:
+       free_token(token);
+
+       return ret;
+}
+
 static char *arg_eval (struct print_arg *arg);
 
 static unsigned long long
@@ -2486,49 +2526,20 @@ out_free:
 static enum event_type
 process_hex(struct event_format *event, struct print_arg *arg, char **tok)
 {
-       struct print_arg *field;
-       enum event_type type;
-       char *token = NULL;
-
        memset(arg, 0, sizeof(*arg));
        arg->type = PRINT_HEX;
 
-       field = alloc_arg();
-       if (!field) {
-               do_warning_event(event, "%s: not enough memory!", __func__);
-               goto out_free;
-       }
-
-       type = process_arg(event, field, &token);
-
-       if (test_type_token(type, token, EVENT_DELIM, ","))
-               goto out_free;
-
-       arg->hex.field = field;
-
-       free_token(token);
-
-       field = alloc_arg();
-       if (!field) {
-               do_warning_event(event, "%s: not enough memory!", __func__);
-               *tok = NULL;
-               return EVENT_ERROR;
-       }
-
-       type = process_arg(event, field, &token);
-
-       if (test_type_token(type, token, EVENT_DELIM, ")"))
-               goto out_free;
+       if (alloc_and_process_delim(event, ",", &arg->hex.field))
+               goto out;
 
-       arg->hex.size = field;
+       if (alloc_and_process_delim(event, ")", &arg->hex.size))
+               goto free_field;
 
-       free_token(token);
-       type = read_token_item(tok);
-       return type;
+       return read_token_item(tok);
 
- out_free:
-       free_arg(field);
-       free_token(token);
+free_field:
+       free_arg(arg->hex.field);
+out:
        *tok = NULL;
        return EVENT_ERROR;
 }
@@ -3997,6 +4008,10 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc
                                goto process_again;
                        case '.':
                                goto process_again;
+                       case 'z':
+                       case 'Z':
+                               ls = 1;
+                               goto process_again;
                        case 'p':
                                ls = 1;
                                /* fall through */
@@ -6228,15 +6243,20 @@ void pevent_ref(struct pevent *pevent)
        pevent->ref_count++;
 }
 
+void pevent_free_format_field(struct format_field *field)
+{
+       free(field->type);
+       free(field->name);
+       free(field);
+}
+
 static void free_format_fields(struct format_field *field)
 {
        struct format_field *next;
 
        while (field) {
                next = field->next;
-               free(field->type);
-               free(field->name);
-               free(field);
+               pevent_free_format_field(field);
                field = next;
        }
 }
@@ -6341,6 +6361,7 @@ void pevent_free(struct pevent *pevent)
                free_handler(handle);
        }
 
+       free(pevent->trace_clock);
        free(pevent->events);
        free(pevent->sort_events);