diff mbox series

[v2] libtraceevent: Be able to handle some sizeof() calls

Message ID 20221213233645.04fc15ed@gandalf.local.home (mailing list archive)
State Accepted
Commit 2d0573af4dfda7fa739f9b4c0444f42ef03d3587
Headers show
Series [v2] libtraceevent: Be able to handle some sizeof() calls | expand

Commit Message

Steven Rostedt Dec. 14, 2022, 4:36 a.m. UTC
From: "Steven Rostedt (Google)" <rostedt@goodmis.org>

Parse sizeof() for known types as well as fields.

 sizeof(int) is 4
 sizeof(unsigned int) is 4
 sizeof(long) is tep->long_size
 sizeof(unsigned long) is tep->long_size
 sizeof(long long) is 8
 sizeof(unsigned long long) is 8
 sizeof(REC->foo) is the field "foo" size value.

This will now parse the sample events of trace_events in the kernel.

Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
Changes since v1: https://lore.kernel.org/linux-trace-devel/20221213222238.65a9c539@gandalf.local.home

 - Fixed parsing of sizeof(REC->foo) as I forgot to get the next token

 - Fixed parsing of long, as it had just "strcmp()" and not "strcmp() == 0"

 src/event-parse.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 86 insertions(+)
diff mbox series

Patch

diff --git a/src/event-parse.c b/src/event-parse.c
index 1aeed953a120..aaa06b336efe 100644
--- a/src/event-parse.c
+++ b/src/event-parse.c
@@ -3509,6 +3509,88 @@  out_free:
 	return TEP_EVENT_ERROR;
 }
 
+static enum tep_event_type
+process_sizeof(struct tep_event *event, struct tep_print_arg *arg, char **tok)
+{
+	struct tep_format_field *field;
+	enum tep_event_type type;
+	char *token = NULL;
+	bool ok = false;
+	int ret;
+
+	type = read_token_item(&token);
+
+	arg->type = TEP_PRINT_ATOM;
+
+	/* We handle some sizeof types */
+	if (strcmp(token, "unsigned") == 0) {
+		free_token(token);
+		type = read_token_item(&token);
+
+		if (type == TEP_EVENT_ERROR)
+			goto error;
+
+		if (type != TEP_EVENT_ITEM)
+			ok = true;
+	}
+
+	if (ok || strcmp(token, "int") == 0) {
+		arg->atom.atom = strdup("4");
+
+	} else if (strcmp(token, "long") == 0) {
+		free_token(token);
+		type = read_token_item(&token);
+
+		if (token && strcmp(token, "long") == 0) {
+			arg->atom.atom = strdup("8");
+		} else {
+			if (event->tep->long_size == 4)
+				arg->atom.atom = strdup("4");
+			else
+				arg->atom.atom = strdup("8");
+			/* The token is the next token */
+			ok = true;
+		}
+	} else if (strcmp(token, "REC") == 0) {
+
+		free_token(token);
+		type = read_token_item(&token);
+
+		if (test_type_token(type, token,  TEP_EVENT_OP, "->"))
+			goto error;
+		free_token(token);
+
+		if (read_expect_type(TEP_EVENT_ITEM, &token) < 0)
+			goto error;
+
+		field = tep_find_any_field(event, token);
+		/* Can't handle arrays (yet) */
+		if (!field || field->flags & TEP_FIELD_IS_ARRAY)
+			goto error;
+
+		ret = asprintf(&arg->atom.atom, "%d", field->size);
+		if (ret < 0)
+			goto error;
+
+	} else if (!ok) {
+		goto error;
+	}
+
+	if (!ok) {
+		free_token(token);
+		type = read_token_item(tok);
+	}
+	if (test_type_token(type, token,  TEP_EVENT_DELIM, ")"))
+		goto error;
+
+	free_token(token);
+	return read_token_item(tok);
+error:
+	free_token(token);
+	*tok = NULL;
+	return TEP_EVENT_ERROR;
+}
+
 static enum tep_event_type
 process_function(struct tep_event *event, struct tep_print_arg *arg,
 		 char *token, char **tok)
@@ -3568,6 +3650,10 @@  process_function(struct tep_event *event, struct tep_print_arg *arg,
 		free_token(token);
 		return process_builtin_expect(event, arg, tok);
 	}
+	if (strcmp(token, "sizeof") == 0) {
+		free_token(token);
+		return process_sizeof(event, arg, tok);
+	}
 
 	func = find_func_handler(event->tep, token);
 	if (func) {