diff options
| -rw-r--r-- | tools/lib/traceevent/event-parse.h | 5 | ||||
| -rw-r--r-- | tools/lib/traceevent/parse-filter.c | 94 |
2 files changed, 64 insertions, 35 deletions
diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h index 89e4dfd40db6..5e4392d8e2d4 100644 --- a/tools/lib/traceevent/event-parse.h +++ b/tools/lib/traceevent/event-parse.h | |||
| @@ -364,7 +364,10 @@ enum pevent_flag { | |||
| 364 | _PE(ILLEGAL_LVALUE, "illegal lvalue for string comparison"), \ | 364 | _PE(ILLEGAL_LVALUE, "illegal lvalue for string comparison"), \ |
| 365 | _PE(INVALID_REGEX, "regex did not compute"), \ | 365 | _PE(INVALID_REGEX, "regex did not compute"), \ |
| 366 | _PE(ILLEGAL_STRING_CMP, "illegal comparison for string"), \ | 366 | _PE(ILLEGAL_STRING_CMP, "illegal comparison for string"), \ |
| 367 | _PE(ILLEGAL_INTEGER_CMP,"illegal comparison for integer") | 367 | _PE(ILLEGAL_INTEGER_CMP,"illegal comparison for integer"), \ |
| 368 | _PE(REPARENT_NOT_OP, "cannot reparent other than OP"), \ | ||
| 369 | _PE(REPARENT_FAILED, "failed to reparent filter OP"), \ | ||
| 370 | _PE(BAD_FILTER_ARG, "bad arg in filter tree") | ||
| 368 | 371 | ||
| 369 | #undef _PE | 372 | #undef _PE |
| 370 | #define _PE(__code, __str) PEVENT_ERRNO__ ## __code | 373 | #define _PE(__code, __str) PEVENT_ERRNO__ ## __code |
diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c index 774c3e4c1d9f..9b05892566e0 100644 --- a/tools/lib/traceevent/parse-filter.c +++ b/tools/lib/traceevent/parse-filter.c | |||
| @@ -784,15 +784,18 @@ enum filter_vals { | |||
| 784 | FILTER_VAL_TRUE, | 784 | FILTER_VAL_TRUE, |
| 785 | }; | 785 | }; |
| 786 | 786 | ||
| 787 | void reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child, | 787 | static enum pevent_errno |
| 788 | struct filter_arg *arg) | 788 | reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child, |
| 789 | struct filter_arg *arg, char **error_str) | ||
| 789 | { | 790 | { |
| 790 | struct filter_arg *other_child; | 791 | struct filter_arg *other_child; |
| 791 | struct filter_arg **ptr; | 792 | struct filter_arg **ptr; |
| 792 | 793 | ||
| 793 | if (parent->type != FILTER_ARG_OP && | 794 | if (parent->type != FILTER_ARG_OP && |
| 794 | arg->type != FILTER_ARG_OP) | 795 | arg->type != FILTER_ARG_OP) { |
| 795 | die("can not reparent other than OP"); | 796 | show_error(error_str, "can not reparent other than OP"); |
| 797 | return PEVENT_ERRNO__REPARENT_NOT_OP; | ||
| 798 | } | ||
| 796 | 799 | ||
| 797 | /* Get the sibling */ | 800 | /* Get the sibling */ |
| 798 | if (old_child->op.right == arg) { | 801 | if (old_child->op.right == arg) { |
| @@ -801,8 +804,10 @@ void reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child, | |||
| 801 | } else if (old_child->op.left == arg) { | 804 | } else if (old_child->op.left == arg) { |
| 802 | ptr = &old_child->op.left; | 805 | ptr = &old_child->op.left; |
| 803 | other_child = old_child->op.right; | 806 | other_child = old_child->op.right; |
| 804 | } else | 807 | } else { |
| 805 | die("Error in reparent op, find other child"); | 808 | show_error(error_str, "Error in reparent op, find other child"); |
| 809 | return PEVENT_ERRNO__REPARENT_FAILED; | ||
| 810 | } | ||
| 806 | 811 | ||
| 807 | /* Detach arg from old_child */ | 812 | /* Detach arg from old_child */ |
| 808 | *ptr = NULL; | 813 | *ptr = NULL; |
| @@ -813,23 +818,29 @@ void reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child, | |||
| 813 | *parent = *arg; | 818 | *parent = *arg; |
| 814 | /* Free arg without recussion */ | 819 | /* Free arg without recussion */ |
| 815 | free(arg); | 820 | free(arg); |
| 816 | return; | 821 | return 0; |
| 817 | } | 822 | } |
| 818 | 823 | ||
| 819 | if (parent->op.right == old_child) | 824 | if (parent->op.right == old_child) |
| 820 | ptr = &parent->op.right; | 825 | ptr = &parent->op.right; |
| 821 | else if (parent->op.left == old_child) | 826 | else if (parent->op.left == old_child) |
| 822 | ptr = &parent->op.left; | 827 | ptr = &parent->op.left; |
| 823 | else | 828 | else { |
| 824 | die("Error in reparent op"); | 829 | show_error(error_str, "Error in reparent op"); |
| 830 | return PEVENT_ERRNO__REPARENT_FAILED; | ||
| 831 | } | ||
| 832 | |||
| 825 | *ptr = arg; | 833 | *ptr = arg; |
| 826 | 834 | ||
| 827 | free_arg(old_child); | 835 | free_arg(old_child); |
| 836 | return 0; | ||
| 828 | } | 837 | } |
| 829 | 838 | ||
| 830 | enum filter_vals test_arg(struct filter_arg *parent, struct filter_arg *arg) | 839 | /* Returns either filter_vals (success) or pevent_errno (failfure) */ |
| 840 | static int test_arg(struct filter_arg *parent, struct filter_arg *arg, | ||
| 841 | char **error_str) | ||
| 831 | { | 842 | { |
| 832 | enum filter_vals lval, rval; | 843 | int lval, rval; |
| 833 | 844 | ||
| 834 | switch (arg->type) { | 845 | switch (arg->type) { |
| 835 | 846 | ||
| @@ -844,63 +855,68 @@ enum filter_vals test_arg(struct filter_arg *parent, struct filter_arg *arg) | |||
| 844 | return FILTER_VAL_NORM; | 855 | return FILTER_VAL_NORM; |
| 845 | 856 | ||
| 846 | case FILTER_ARG_EXP: | 857 | case FILTER_ARG_EXP: |
| 847 | lval = test_arg(arg, arg->exp.left); | 858 | lval = test_arg(arg, arg->exp.left, error_str); |
| 848 | if (lval != FILTER_VAL_NORM) | 859 | if (lval != FILTER_VAL_NORM) |
| 849 | return lval; | 860 | return lval; |
| 850 | rval = test_arg(arg, arg->exp.right); | 861 | rval = test_arg(arg, arg->exp.right, error_str); |
| 851 | if (rval != FILTER_VAL_NORM) | 862 | if (rval != FILTER_VAL_NORM) |
| 852 | return rval; | 863 | return rval; |
| 853 | return FILTER_VAL_NORM; | 864 | return FILTER_VAL_NORM; |
| 854 | 865 | ||
| 855 | case FILTER_ARG_NUM: | 866 | case FILTER_ARG_NUM: |
| 856 | lval = test_arg(arg, arg->num.left); | 867 | lval = test_arg(arg, arg->num.left, error_str); |
| 857 | if (lval != FILTER_VAL_NORM) | 868 | if (lval != FILTER_VAL_NORM) |
| 858 | return lval; | 869 | return lval; |
| 859 | rval = test_arg(arg, arg->num.right); | 870 | rval = test_arg(arg, arg->num.right, error_str); |
| 860 | if (rval != FILTER_VAL_NORM) | 871 | if (rval != FILTER_VAL_NORM) |
| 861 | return rval; | 872 | return rval; |
| 862 | return FILTER_VAL_NORM; | 873 | return FILTER_VAL_NORM; |
| 863 | 874 | ||
| 864 | case FILTER_ARG_OP: | 875 | case FILTER_ARG_OP: |
| 865 | if (arg->op.type != FILTER_OP_NOT) { | 876 | if (arg->op.type != FILTER_OP_NOT) { |
| 866 | lval = test_arg(arg, arg->op.left); | 877 | lval = test_arg(arg, arg->op.left, error_str); |
| 867 | switch (lval) { | 878 | switch (lval) { |
| 868 | case FILTER_VAL_NORM: | 879 | case FILTER_VAL_NORM: |
| 869 | break; | 880 | break; |
| 870 | case FILTER_VAL_TRUE: | 881 | case FILTER_VAL_TRUE: |
| 871 | if (arg->op.type == FILTER_OP_OR) | 882 | if (arg->op.type == FILTER_OP_OR) |
| 872 | return FILTER_VAL_TRUE; | 883 | return FILTER_VAL_TRUE; |
| 873 | rval = test_arg(arg, arg->op.right); | 884 | rval = test_arg(arg, arg->op.right, error_str); |
| 874 | if (rval != FILTER_VAL_NORM) | 885 | if (rval != FILTER_VAL_NORM) |
| 875 | return rval; | 886 | return rval; |
| 876 | 887 | ||
| 877 | reparent_op_arg(parent, arg, arg->op.right); | 888 | return reparent_op_arg(parent, arg, arg->op.right, |
| 878 | return FILTER_VAL_NORM; | 889 | error_str); |
| 879 | 890 | ||
| 880 | case FILTER_VAL_FALSE: | 891 | case FILTER_VAL_FALSE: |
| 881 | if (arg->op.type == FILTER_OP_AND) | 892 | if (arg->op.type == FILTER_OP_AND) |
| 882 | return FILTER_VAL_FALSE; | 893 | return FILTER_VAL_FALSE; |
| 883 | rval = test_arg(arg, arg->op.right); | 894 | rval = test_arg(arg, arg->op.right, error_str); |
| 884 | if (rval != FILTER_VAL_NORM) | 895 | if (rval != FILTER_VAL_NORM) |
| 885 | return rval; | 896 | return rval; |
| 886 | 897 | ||
| 887 | reparent_op_arg(parent, arg, arg->op.right); | 898 | return reparent_op_arg(parent, arg, arg->op.right, |
| 888 | return FILTER_VAL_NORM; | 899 | error_str); |
| 900 | |||
| 901 | default: | ||
| 902 | return lval; | ||
| 889 | } | 903 | } |
| 890 | } | 904 | } |
| 891 | 905 | ||
| 892 | rval = test_arg(arg, arg->op.right); | 906 | rval = test_arg(arg, arg->op.right, error_str); |
| 893 | switch (rval) { | 907 | switch (rval) { |
| 894 | case FILTER_VAL_NORM: | 908 | case FILTER_VAL_NORM: |
| 909 | default: | ||
| 895 | break; | 910 | break; |
| 911 | |||
| 896 | case FILTER_VAL_TRUE: | 912 | case FILTER_VAL_TRUE: |
| 897 | if (arg->op.type == FILTER_OP_OR) | 913 | if (arg->op.type == FILTER_OP_OR) |
| 898 | return FILTER_VAL_TRUE; | 914 | return FILTER_VAL_TRUE; |
| 899 | if (arg->op.type == FILTER_OP_NOT) | 915 | if (arg->op.type == FILTER_OP_NOT) |
| 900 | return FILTER_VAL_FALSE; | 916 | return FILTER_VAL_FALSE; |
| 901 | 917 | ||
| 902 | reparent_op_arg(parent, arg, arg->op.left); | 918 | return reparent_op_arg(parent, arg, arg->op.left, |
| 903 | return FILTER_VAL_NORM; | 919 | error_str); |
| 904 | 920 | ||
| 905 | case FILTER_VAL_FALSE: | 921 | case FILTER_VAL_FALSE: |
| 906 | if (arg->op.type == FILTER_OP_AND) | 922 | if (arg->op.type == FILTER_OP_AND) |
| @@ -908,26 +924,27 @@ enum filter_vals test_arg(struct filter_arg *parent, struct filter_arg *arg) | |||
| 908 | if (arg->op.type == FILTER_OP_NOT) | 924 | if (arg->op.type == FILTER_OP_NOT) |
| 909 | return FILTER_VAL_TRUE; | 925 | return FILTER_VAL_TRUE; |
| 910 | 926 | ||
| 911 | reparent_op_arg(parent, arg, arg->op.left); | 927 | return reparent_op_arg(parent, arg, arg->op.left, |
| 912 | return FILTER_VAL_NORM; | 928 | error_str); |
| 913 | } | 929 | } |
| 914 | 930 | ||
| 915 | return FILTER_VAL_NORM; | 931 | return rval; |
| 916 | default: | 932 | default: |
| 917 | die("bad arg in filter tree"); | 933 | show_error(error_str, "bad arg in filter tree"); |
| 934 | return PEVENT_ERRNO__BAD_FILTER_ARG; | ||
| 918 | } | 935 | } |
| 919 | return FILTER_VAL_NORM; | 936 | return FILTER_VAL_NORM; |
| 920 | } | 937 | } |
| 921 | 938 | ||
| 922 | /* Remove any unknown event fields */ | 939 | /* Remove any unknown event fields */ |
| 923 | static struct filter_arg *collapse_tree(struct filter_arg *arg) | 940 | static struct filter_arg *collapse_tree(struct filter_arg *arg, char **error_str) |
| 924 | { | 941 | { |
| 925 | enum filter_vals ret; | 942 | enum filter_vals ret; |
| 926 | 943 | ||
| 927 | ret = test_arg(arg, arg); | 944 | ret = test_arg(arg, arg, error_str); |
| 928 | switch (ret) { | 945 | switch (ret) { |
| 929 | case FILTER_VAL_NORM: | 946 | case FILTER_VAL_NORM: |
| 930 | return arg; | 947 | break; |
| 931 | 948 | ||
| 932 | case FILTER_VAL_TRUE: | 949 | case FILTER_VAL_TRUE: |
| 933 | case FILTER_VAL_FALSE: | 950 | case FILTER_VAL_FALSE: |
| @@ -936,7 +953,16 @@ static struct filter_arg *collapse_tree(struct filter_arg *arg) | |||
| 936 | if (arg) { | 953 | if (arg) { |
| 937 | arg->type = FILTER_ARG_BOOLEAN; | 954 | arg->type = FILTER_ARG_BOOLEAN; |
| 938 | arg->boolean.value = ret == FILTER_VAL_TRUE; | 955 | arg->boolean.value = ret == FILTER_VAL_TRUE; |
| 956 | } else { | ||
| 957 | show_error(error_str, "Failed to allocate filter arg"); | ||
| 939 | } | 958 | } |
| 959 | break; | ||
| 960 | |||
| 961 | default: | ||
| 962 | /* test_arg() already set the error_str */ | ||
| 963 | free_arg(arg); | ||
| 964 | arg = NULL; | ||
| 965 | break; | ||
| 940 | } | 966 | } |
| 941 | 967 | ||
| 942 | return arg; | 968 | return arg; |
| @@ -1152,9 +1178,9 @@ process_filter(struct event_format *event, struct filter_arg **parg, | |||
| 1152 | if (!current_op) | 1178 | if (!current_op) |
| 1153 | current_op = current_exp; | 1179 | current_op = current_exp; |
| 1154 | 1180 | ||
| 1155 | current_op = collapse_tree(current_op); | 1181 | current_op = collapse_tree(current_op, error_str); |
| 1156 | if (current_op == NULL) | 1182 | if (current_op == NULL) |
| 1157 | goto fail_alloc; | 1183 | goto fail; |
| 1158 | 1184 | ||
| 1159 | *parg = current_op; | 1185 | *parg = current_op; |
| 1160 | 1186 | ||
