diff options
author | Steven Rostedt <srostedt@redhat.com> | 2010-02-17 09:52:56 -0500 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2010-02-17 09:52:56 -0500 |
commit | a5f716419f133132dfc6e1813aff7eb87344f526 (patch) | |
tree | 0046c5654a8fd52087232164b2764339532f7a32 | |
parent | 03c370ca8b2f45fde8e8e56a59f481981b901780 (diff) |
parse-events: Add pevent_filter_make_string()
Add the function pevent_filter_make_string() that will return an
allocated string that translates a filter of an event. This can
be used to display the defined filters back to the user.
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r-- | parse-events.h | 2 | ||||
-rw-r--r-- | parse-filter.c | 260 |
2 files changed, 262 insertions, 0 deletions
diff --git a/parse-events.h b/parse-events.h index 1573869..641aaf2 100644 --- a/parse-events.h +++ b/parse-events.h | |||
@@ -597,4 +597,6 @@ void pevent_filter_reset(struct event_filter *filter); | |||
597 | 597 | ||
598 | void pevent_filter_free(struct event_filter *filter); | 598 | void pevent_filter_free(struct event_filter *filter); |
599 | 599 | ||
600 | char *pevent_filter_make_string(struct event_filter *filter, int event_id); | ||
601 | |||
600 | #endif /* _PARSE_EVENTS_H */ | 602 | #endif /* _PARSE_EVENTS_H */ |
diff --git a/parse-filter.c b/parse-filter.c index 8944644..c047560 100644 --- a/parse-filter.c +++ b/parse-filter.c | |||
@@ -1071,3 +1071,263 @@ int pevent_filter_match(struct event_filter *filter, | |||
1071 | FILTER_MATCH : FILTER_MISS; | 1071 | FILTER_MATCH : FILTER_MISS; |
1072 | } | 1072 | } |
1073 | 1073 | ||
1074 | static char *arg_to_str(struct event_filter *filter, struct filter_arg *arg); | ||
1075 | |||
1076 | static char *op_to_str(struct event_filter *filter, struct filter_arg *arg) | ||
1077 | { | ||
1078 | char *str = NULL; | ||
1079 | char *left = NULL; | ||
1080 | char *right = NULL; | ||
1081 | char *op = NULL; | ||
1082 | int left_val = -1; | ||
1083 | int right_val = -1; | ||
1084 | int val; | ||
1085 | int len; | ||
1086 | |||
1087 | switch (arg->op.type) { | ||
1088 | case FILTER_OP_AND: | ||
1089 | op = "&&"; | ||
1090 | /* fall through */ | ||
1091 | case FILTER_OP_OR: | ||
1092 | if (!op) | ||
1093 | op = "||"; | ||
1094 | |||
1095 | left = arg_to_str(filter, arg->op.left); | ||
1096 | right = arg_to_str(filter, arg->op.right); | ||
1097 | if (!left || !right) | ||
1098 | break; | ||
1099 | |||
1100 | /* Try to consolidate boolean values */ | ||
1101 | if (strcmp(left, "TRUE") == 0) | ||
1102 | left_val = 1; | ||
1103 | else if (strcmp(left, "FALSE") == 0) | ||
1104 | left_val = 0; | ||
1105 | |||
1106 | if (strcmp(right, "TRUE") == 0) | ||
1107 | right_val = 1; | ||
1108 | else if (strcmp(right, "FALSE") == 0) | ||
1109 | right_val = 0; | ||
1110 | |||
1111 | if (left_val >= 0) { | ||
1112 | if ((arg->op.type == FILTER_OP_AND && !left_val) || | ||
1113 | (arg->op.type == FILTER_OP_OR && left_val)) { | ||
1114 | /* Just return left value */ | ||
1115 | str = left; | ||
1116 | left = NULL; | ||
1117 | break; | ||
1118 | } | ||
1119 | if (right_val >= 0) { | ||
1120 | /* just evaluate this. */ | ||
1121 | val = 0; | ||
1122 | switch (arg->op.type) { | ||
1123 | case FILTER_OP_AND: | ||
1124 | val = left_val && right_val; | ||
1125 | break; | ||
1126 | case FILTER_OP_OR: | ||
1127 | val = left_val || right_val; | ||
1128 | break; | ||
1129 | default: | ||
1130 | break; | ||
1131 | } | ||
1132 | str = malloc_or_die(6); | ||
1133 | if (val) | ||
1134 | strcpy(str, "TRUE"); | ||
1135 | else | ||
1136 | strcpy(str, "FALSE"); | ||
1137 | break; | ||
1138 | } | ||
1139 | } | ||
1140 | if (right_val >= 0) { | ||
1141 | if ((arg->op.type == FILTER_OP_AND && !right_val) || | ||
1142 | (arg->op.type == FILTER_OP_OR && right_val)) { | ||
1143 | /* Just return right value */ | ||
1144 | str = right; | ||
1145 | right = NULL; | ||
1146 | break; | ||
1147 | } | ||
1148 | /* The right value is meaningless */ | ||
1149 | str = left; | ||
1150 | left = NULL; | ||
1151 | break; | ||
1152 | } | ||
1153 | |||
1154 | len = strlen(left) + strlen(right) + strlen(op) + 10; | ||
1155 | str = malloc_or_die(len); | ||
1156 | snprintf(str, len, "(%s) %s (%s)", | ||
1157 | left, op, right); | ||
1158 | break; | ||
1159 | |||
1160 | case FILTER_OP_NOT: | ||
1161 | op = "!"; | ||
1162 | right = arg_to_str(filter, arg->op.right); | ||
1163 | if (!right) | ||
1164 | break; | ||
1165 | |||
1166 | /* See if we can consolidate */ | ||
1167 | if (strcmp(right, "TRUE") == 0) | ||
1168 | right_val = 1; | ||
1169 | else if (strcmp(right, "FALSE") == 0) | ||
1170 | right_val = 0; | ||
1171 | if (right_val >= 0) { | ||
1172 | /* just return the opposite */ | ||
1173 | str = malloc_or_die(6); | ||
1174 | if (right_val) | ||
1175 | strcpy(str, "FALSE"); | ||
1176 | else | ||
1177 | strcpy(str, "TRUE"); | ||
1178 | break; | ||
1179 | } | ||
1180 | len = strlen(right) + strlen(op) + 3; | ||
1181 | str = malloc_or_die(len); | ||
1182 | snprintf(str, len, "%s(%s)", op, right); | ||
1183 | break; | ||
1184 | |||
1185 | default: | ||
1186 | /* ?? */ | ||
1187 | break; | ||
1188 | } | ||
1189 | free(left); | ||
1190 | free(right); | ||
1191 | return str; | ||
1192 | } | ||
1193 | |||
1194 | static char *num_to_str(struct event_filter *filter, struct filter_arg *arg) | ||
1195 | { | ||
1196 | char *str = NULL; | ||
1197 | char *op = NULL; | ||
1198 | int len; | ||
1199 | |||
1200 | switch (arg->num.type) { | ||
1201 | case FILTER_CMP_EQ: | ||
1202 | op = "=="; | ||
1203 | /* fall through */ | ||
1204 | case FILTER_CMP_NE: | ||
1205 | if (!op) | ||
1206 | op = "!="; | ||
1207 | /* fall through */ | ||
1208 | case FILTER_CMP_GT: | ||
1209 | if (!op) | ||
1210 | op = ">"; | ||
1211 | /* fall through */ | ||
1212 | case FILTER_CMP_LT: | ||
1213 | if (!op) | ||
1214 | op = "<"; | ||
1215 | /* fall through */ | ||
1216 | case FILTER_CMP_GE: | ||
1217 | if (!op) | ||
1218 | op = ">="; | ||
1219 | /* fall through */ | ||
1220 | case FILTER_CMP_LE: | ||
1221 | if (!op) | ||
1222 | op = "<="; | ||
1223 | |||
1224 | len = strlen(arg->num.field->name) + strlen(op) + 30; | ||
1225 | str = malloc_or_die(len); | ||
1226 | if (arg->num.field->flags & FIELD_IS_SIGNED) | ||
1227 | snprintf(str, len, "%s %s %lld", | ||
1228 | arg->num.field->name, | ||
1229 | op, arg->num.val); | ||
1230 | else | ||
1231 | snprintf(str, len, "%s %s %llu", | ||
1232 | arg->num.field->name, | ||
1233 | op, arg->num.val); | ||
1234 | break; | ||
1235 | |||
1236 | default: | ||
1237 | /* ?? */ | ||
1238 | break; | ||
1239 | } | ||
1240 | return str; | ||
1241 | } | ||
1242 | |||
1243 | static char *str_to_str(struct event_filter *filter, struct filter_arg *arg) | ||
1244 | { | ||
1245 | char *str = NULL; | ||
1246 | char *op = NULL; | ||
1247 | int len; | ||
1248 | |||
1249 | switch (arg->str.type) { | ||
1250 | case FILTER_CMP_MATCH: | ||
1251 | op = "=="; | ||
1252 | /* fall through */ | ||
1253 | case FILTER_CMP_NOT_MATCH: | ||
1254 | if (!op) | ||
1255 | op = "!="; | ||
1256 | /* fall through */ | ||
1257 | case FILTER_CMP_REGEX: | ||
1258 | if (!op) | ||
1259 | op = "=~"; | ||
1260 | /* fall through */ | ||
1261 | case FILTER_CMP_NOT_REGEX: | ||
1262 | if (!op) | ||
1263 | op = "!~"; | ||
1264 | |||
1265 | len = strlen(arg->str.field->name) + strlen(op) + | ||
1266 | strlen(arg->str.val) + 6; | ||
1267 | str = malloc_or_die(len); | ||
1268 | snprintf(str, len, "%s %s \"%s\"", | ||
1269 | arg->str.field->name, | ||
1270 | op, arg->str.val); | ||
1271 | break; | ||
1272 | |||
1273 | default: | ||
1274 | /* ?? */ | ||
1275 | break; | ||
1276 | } | ||
1277 | return str; | ||
1278 | } | ||
1279 | |||
1280 | static char *arg_to_str(struct event_filter *filter, struct filter_arg *arg) | ||
1281 | { | ||
1282 | char *str; | ||
1283 | |||
1284 | switch (arg->type) { | ||
1285 | case FILTER_ARG_BOOLEAN: | ||
1286 | str = malloc_or_die(6); | ||
1287 | if (arg->bool.value) | ||
1288 | strcpy(str, "TRUE"); | ||
1289 | else | ||
1290 | strcpy(str, "FALSE"); | ||
1291 | return str; | ||
1292 | |||
1293 | case FILTER_ARG_OP: | ||
1294 | return op_to_str(filter, arg); | ||
1295 | |||
1296 | case FILTER_ARG_NUM: | ||
1297 | return num_to_str(filter, arg); | ||
1298 | |||
1299 | case FILTER_ARG_STR: | ||
1300 | return str_to_str(filter, arg); | ||
1301 | |||
1302 | default: | ||
1303 | /* ?? */ | ||
1304 | return NULL; | ||
1305 | } | ||
1306 | |||
1307 | } | ||
1308 | |||
1309 | /** | ||
1310 | * pevent_filter_make_string - return a string showing the filter | ||
1311 | * @filter: filter struct with filter information | ||
1312 | * @event_id: the event id to return the filter string with | ||
1313 | * | ||
1314 | * Returns a string that displays the filter contents. | ||
1315 | * This string must be freed with free(str). | ||
1316 | * NULL is returned if no filter is found. | ||
1317 | */ | ||
1318 | char * | ||
1319 | pevent_filter_make_string(struct event_filter *filter, int event_id) | ||
1320 | { | ||
1321 | struct filter_type *filter_type; | ||
1322 | |||
1323 | if (!filter->filters) | ||
1324 | return NULL; | ||
1325 | |||
1326 | filter_type = find_filter_type(filter, event_id); | ||
1327 | |||
1328 | if (!filter_type) | ||
1329 | return NULL; | ||
1330 | |||
1331 | return arg_to_str(filter, filter_type->filter); | ||
1332 | } | ||
1333 | |||