]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - tools/perf/util/trace-event-parse.c
perf tools: Fix backslash processing on trace print formats
[net-next-2.6.git] / tools / perf / util / trace-event-parse.c
index 55b41b9e3834bff2b5abd17a6d53c9a5295af3a4..2b75ec2f57e8720c28494d0ca524a9955986f27e 100644 (file)
@@ -522,7 +522,10 @@ static enum event_type __read_token(char **tok)
                        last_ch = ch;
                        ch = __read_char();
                        buf[i++] = ch;
-               } while (ch != quote_ch && last_ch != '\\');
+                       /* the '\' '\' will cancel itself */
+                       if (ch == '\\' && last_ch == '\\')
+                               last_ch = 0;
+               } while (ch != quote_ch || last_ch == '\\');
                /* remove the last quote */
                i--;
                goto out;
@@ -618,7 +621,7 @@ static int test_type(enum event_type type, enum event_type expect)
 }
 
 static int test_type_token(enum event_type type, char *token,
-                   enum event_type expect, char *expect_tok)
+                   enum event_type expect, const char *expect_tok)
 {
        if (type != expect) {
                die("Error: expected type %d but read %d",
@@ -650,7 +653,7 @@ static int read_expect_type(enum event_type expect, char **tok)
        return __read_expect_type(expect, tok, 1);
 }
 
-static int __read_expected(enum event_type expect, char *str, int newline_ok)
+static int __read_expected(enum event_type expect, const char *str, int newline_ok)
 {
        enum event_type type;
        char *token;
@@ -668,12 +671,12 @@ static int __read_expected(enum event_type expect, char *str, int newline_ok)
        return 0;
 }
 
-static int read_expected(enum event_type expect, char *str)
+static int read_expected(enum event_type expect, const char *str)
 {
        return __read_expected(expect, str, 1);
 }
 
-static int read_expected_item(enum event_type expect, char *str)
+static int read_expected_item(enum event_type expect, const char *str)
 {
        return __read_expected(expect, str, 0);
 }
@@ -721,6 +724,24 @@ static int event_read_id(void)
        return -1;
 }
 
+static int field_is_string(struct format_field *field)
+{
+       if ((field->flags & FIELD_IS_ARRAY) &&
+           (!strstr(field->type, "char") || !strstr(field->type, "u8") ||
+            !strstr(field->type, "s8")))
+               return 1;
+
+       return 0;
+}
+
+static int field_is_dynamic(struct format_field *field)
+{
+       if (!strcmp(field->type, "__data_loc"))
+               return 1;
+
+       return 0;
+}
+
 static int event_read_fields(struct event *event, struct format_field **fields)
 {
        struct format_field *field = NULL;
@@ -865,6 +886,12 @@ static int event_read_fields(struct event *event, struct format_field **fields)
                        free(brackets);
                }
 
+               if (field_is_string(field)) {
+                       field->flags |= FIELD_IS_STRING;
+                       if (field_is_dynamic(field))
+                               field->flags |= FIELD_IS_DYNAMIC;
+               }
+
                if (test_type_token(type, token,  EVENT_OP, (char *)";"))
                        goto fail;
                free_token(token);
@@ -894,6 +921,21 @@ static int event_read_fields(struct event *event, struct format_field **fields)
                field->size = strtoul(token, NULL, 0);
                free_token(token);
 
+               if (read_expected(EVENT_OP, (char *)";") < 0)
+                       goto fail_expect;
+
+               if (read_expected(EVENT_ITEM, (char *)"signed") < 0)
+                       goto fail_expect;
+
+               if (read_expected(EVENT_OP, (char *)":") < 0)
+                       goto fail_expect;
+
+               if (read_expect_type(EVENT_ITEM, &token))
+                       goto fail;
+               if (strtoul(token, NULL, 0))
+                       field->flags |= FIELD_IS_SIGNED;
+               free_token(token);
+
                if (read_expected(EVENT_OP, (char *)";") < 0)
                        goto fail_expect;
 
@@ -1695,6 +1737,7 @@ static int event_read_print(struct event *event)
        if (read_expect_type(EVENT_DQUOTE, &token) < 0)
                goto fail;
 
+ concat:
        event->print_fmt.format = token;
        event->print_fmt.args = NULL;
 
@@ -1704,6 +1747,21 @@ static int event_read_print(struct event *event)
        if (type == EVENT_NONE)
                return 0;
 
+       /* Handle concatination of print lines */
+       if (type == EVENT_DQUOTE) {
+               char *cat;
+
+               cat = malloc_or_die(strlen(event->print_fmt.format) +
+                                   strlen(token) + 1);
+               strcpy(cat, event->print_fmt.format);
+               strcat(cat, token);
+               free_token(token);
+               free_token(event->print_fmt.format);
+               event->print_fmt.format = NULL;
+               token = cat;
+               goto concat;
+       }
+                            
        if (test_type_token(type, token, EVENT_DELIM, (char *)","))
                goto fail;
 
@@ -2270,7 +2328,27 @@ static void pretty_print(void *data, int size, struct event *event)
 
        for (; *ptr; ptr++) {
                ls = 0;
-               if (*ptr == '%') {
+               if (*ptr == '\\') {
+                       ptr++;
+                       switch (*ptr) {
+                       case 'n':
+                               printf("\n");
+                               break;
+                       case 't':
+                               printf("\t");
+                               break;
+                       case 'r':
+                               printf("\r");
+                               break;
+                       case '\\':
+                               printf("\\");
+                               break;
+                       default:
+                               printf("%c", *ptr);
+                               break;
+                       }
+
+               } else if (*ptr == '%') {
                        saveptr = ptr;
                        show_func = 0;
  cont_process:
@@ -2843,6 +2921,15 @@ static void parse_header_field(char *type,
                return;
        *size = atoi(token);
        free_token(token);
+       if (read_expected(EVENT_OP, (char *)";") < 0)
+               return;
+       if (read_expected(EVENT_ITEM, (char *)"signed") < 0)
+               return;
+       if (read_expected(EVENT_OP, (char *)":") < 0)
+               return;
+       if (read_expect_type(EVENT_ITEM, &token) < 0)
+               return;
+       free_token(token);
        if (read_expected(EVENT_OP, (char *)";") < 0)
                return;
        if (read_expect_type(EVENT_NEWLINE, &token) < 0)
@@ -2926,7 +3013,7 @@ int parse_ftrace_file(char *buf, unsigned long size)
        return 0;
 }
 
-int parse_event_file(char *buf, unsigned long size, char *system__unused __unused)
+int parse_event_file(char *buf, unsigned long size, char *sys)
 {
        struct event *event;
        int ret;
@@ -2953,6 +3040,8 @@ int parse_event_file(char *buf, unsigned long size, char *system__unused __unuse
        if (ret < 0)
                die("failed to read event print fmt");
 
+       event->system = strdup(sys);
+
 #define PRINT_ARGS 0
        if (PRINT_ARGS && event->print_fmt.args)
                print_args(event->print_fmt.args);