18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: LGPL-2.1
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci *  The parts for function graph printing was taken and modified from the
78c2ecf20Sopenharmony_ci *  Linux Kernel that were written by
88c2ecf20Sopenharmony_ci *    - Copyright (C) 2009  Frederic Weisbecker,
98c2ecf20Sopenharmony_ci *  Frederic Weisbecker gave his permission to relicense the code to
108c2ecf20Sopenharmony_ci *  the Lesser General Public License.
118c2ecf20Sopenharmony_ci */
128c2ecf20Sopenharmony_ci#include <inttypes.h>
138c2ecf20Sopenharmony_ci#include <stdio.h>
148c2ecf20Sopenharmony_ci#include <stdlib.h>
158c2ecf20Sopenharmony_ci#include <string.h>
168c2ecf20Sopenharmony_ci#include <stdarg.h>
178c2ecf20Sopenharmony_ci#include <ctype.h>
188c2ecf20Sopenharmony_ci#include <errno.h>
198c2ecf20Sopenharmony_ci#include <stdint.h>
208c2ecf20Sopenharmony_ci#include <limits.h>
218c2ecf20Sopenharmony_ci#include <linux/time64.h>
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci#include <netinet/in.h>
248c2ecf20Sopenharmony_ci#include "event-parse.h"
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci#include "event-parse-local.h"
278c2ecf20Sopenharmony_ci#include "event-utils.h"
288c2ecf20Sopenharmony_ci#include "trace-seq.h"
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_cistatic const char *input_buf;
318c2ecf20Sopenharmony_cistatic unsigned long long input_buf_ptr;
328c2ecf20Sopenharmony_cistatic unsigned long long input_buf_siz;
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_cistatic int is_flag_field;
358c2ecf20Sopenharmony_cistatic int is_symbolic_field;
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_cistatic int show_warning = 1;
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci#define do_warning(fmt, ...)				\
408c2ecf20Sopenharmony_ci	do {						\
418c2ecf20Sopenharmony_ci		if (show_warning)			\
428c2ecf20Sopenharmony_ci			warning(fmt, ##__VA_ARGS__);	\
438c2ecf20Sopenharmony_ci	} while (0)
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci#define do_warning_event(event, fmt, ...)			\
468c2ecf20Sopenharmony_ci	do {							\
478c2ecf20Sopenharmony_ci		if (!show_warning)				\
488c2ecf20Sopenharmony_ci			continue;				\
498c2ecf20Sopenharmony_ci								\
508c2ecf20Sopenharmony_ci		if (event)					\
518c2ecf20Sopenharmony_ci			warning("[%s:%s] " fmt, event->system,	\
528c2ecf20Sopenharmony_ci				event->name, ##__VA_ARGS__);	\
538c2ecf20Sopenharmony_ci		else						\
548c2ecf20Sopenharmony_ci			warning(fmt, ##__VA_ARGS__);		\
558c2ecf20Sopenharmony_ci	} while (0)
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci/**
588c2ecf20Sopenharmony_ci * init_input_buf - init buffer for parsing
598c2ecf20Sopenharmony_ci * @buf: buffer to parse
608c2ecf20Sopenharmony_ci * @size: the size of the buffer
618c2ecf20Sopenharmony_ci *
628c2ecf20Sopenharmony_ci * Initializes the internal buffer that tep_read_token() will parse.
638c2ecf20Sopenharmony_ci */
648c2ecf20Sopenharmony_ci__hidden void init_input_buf(const char *buf, unsigned long long size)
658c2ecf20Sopenharmony_ci{
668c2ecf20Sopenharmony_ci	input_buf = buf;
678c2ecf20Sopenharmony_ci	input_buf_siz = size;
688c2ecf20Sopenharmony_ci	input_buf_ptr = 0;
698c2ecf20Sopenharmony_ci}
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci__hidden const char *get_input_buf(void)
728c2ecf20Sopenharmony_ci{
738c2ecf20Sopenharmony_ci	return input_buf;
748c2ecf20Sopenharmony_ci}
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci__hidden unsigned long long get_input_buf_ptr(void)
778c2ecf20Sopenharmony_ci{
788c2ecf20Sopenharmony_ci	return input_buf_ptr;
798c2ecf20Sopenharmony_ci}
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_cistruct event_handler {
828c2ecf20Sopenharmony_ci	struct event_handler		*next;
838c2ecf20Sopenharmony_ci	int				id;
848c2ecf20Sopenharmony_ci	const char			*sys_name;
858c2ecf20Sopenharmony_ci	const char			*event_name;
868c2ecf20Sopenharmony_ci	tep_event_handler_func		func;
878c2ecf20Sopenharmony_ci	void				*context;
888c2ecf20Sopenharmony_ci};
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_cistruct func_params {
918c2ecf20Sopenharmony_ci	struct func_params	*next;
928c2ecf20Sopenharmony_ci	enum tep_func_arg_type	type;
938c2ecf20Sopenharmony_ci};
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_cistruct tep_function_handler {
968c2ecf20Sopenharmony_ci	struct tep_function_handler	*next;
978c2ecf20Sopenharmony_ci	enum tep_func_arg_type		ret_type;
988c2ecf20Sopenharmony_ci	char				*name;
998c2ecf20Sopenharmony_ci	tep_func_handler		func;
1008c2ecf20Sopenharmony_ci	struct func_params		*params;
1018c2ecf20Sopenharmony_ci	int				nr_args;
1028c2ecf20Sopenharmony_ci};
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_cistatic unsigned long long
1058c2ecf20Sopenharmony_ciprocess_defined_func(struct trace_seq *s, void *data, int size,
1068c2ecf20Sopenharmony_ci		     struct tep_event *event, struct tep_print_arg *arg);
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_cistatic void free_func_handle(struct tep_function_handler *func);
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_civoid breakpoint(void)
1118c2ecf20Sopenharmony_ci{
1128c2ecf20Sopenharmony_ci	static int x;
1138c2ecf20Sopenharmony_ci	x++;
1148c2ecf20Sopenharmony_ci}
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_cistatic struct tep_print_arg *alloc_arg(void)
1178c2ecf20Sopenharmony_ci{
1188c2ecf20Sopenharmony_ci	return calloc(1, sizeof(struct tep_print_arg));
1198c2ecf20Sopenharmony_ci}
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_cistruct tep_cmdline {
1228c2ecf20Sopenharmony_ci	char *comm;
1238c2ecf20Sopenharmony_ci	int pid;
1248c2ecf20Sopenharmony_ci};
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_cistatic int cmdline_cmp(const void *a, const void *b)
1278c2ecf20Sopenharmony_ci{
1288c2ecf20Sopenharmony_ci	const struct tep_cmdline *ca = a;
1298c2ecf20Sopenharmony_ci	const struct tep_cmdline *cb = b;
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci	if (ca->pid < cb->pid)
1328c2ecf20Sopenharmony_ci		return -1;
1338c2ecf20Sopenharmony_ci	if (ca->pid > cb->pid)
1348c2ecf20Sopenharmony_ci		return 1;
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ci	return 0;
1378c2ecf20Sopenharmony_ci}
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci/* Looking for where to place the key */
1408c2ecf20Sopenharmony_cistatic int cmdline_slot_cmp(const void *a, const void *b)
1418c2ecf20Sopenharmony_ci{
1428c2ecf20Sopenharmony_ci	const struct tep_cmdline *ca = a;
1438c2ecf20Sopenharmony_ci	const struct tep_cmdline *cb = b;
1448c2ecf20Sopenharmony_ci	const struct tep_cmdline *cb1 = cb + 1;
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci	if (ca->pid < cb->pid)
1478c2ecf20Sopenharmony_ci		return -1;
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci	if (ca->pid > cb->pid) {
1508c2ecf20Sopenharmony_ci		if (ca->pid <= cb1->pid)
1518c2ecf20Sopenharmony_ci			return 0;
1528c2ecf20Sopenharmony_ci		return 1;
1538c2ecf20Sopenharmony_ci	}
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci	return 0;
1568c2ecf20Sopenharmony_ci}
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_cistruct cmdline_list {
1598c2ecf20Sopenharmony_ci	struct cmdline_list	*next;
1608c2ecf20Sopenharmony_ci	char			*comm;
1618c2ecf20Sopenharmony_ci	int			pid;
1628c2ecf20Sopenharmony_ci};
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_cistatic int cmdline_init(struct tep_handle *tep)
1658c2ecf20Sopenharmony_ci{
1668c2ecf20Sopenharmony_ci	struct cmdline_list *cmdlist = tep->cmdlist;
1678c2ecf20Sopenharmony_ci	struct cmdline_list *item;
1688c2ecf20Sopenharmony_ci	struct tep_cmdline *cmdlines;
1698c2ecf20Sopenharmony_ci	int i;
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci	cmdlines = malloc(sizeof(*cmdlines) * tep->cmdline_count);
1728c2ecf20Sopenharmony_ci	if (!cmdlines)
1738c2ecf20Sopenharmony_ci		return -1;
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ci	i = 0;
1768c2ecf20Sopenharmony_ci	while (cmdlist) {
1778c2ecf20Sopenharmony_ci		cmdlines[i].pid = cmdlist->pid;
1788c2ecf20Sopenharmony_ci		cmdlines[i].comm = cmdlist->comm;
1798c2ecf20Sopenharmony_ci		i++;
1808c2ecf20Sopenharmony_ci		item = cmdlist;
1818c2ecf20Sopenharmony_ci		cmdlist = cmdlist->next;
1828c2ecf20Sopenharmony_ci		free(item);
1838c2ecf20Sopenharmony_ci	}
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_ci	qsort(cmdlines, tep->cmdline_count, sizeof(*cmdlines), cmdline_cmp);
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci	tep->cmdlines = cmdlines;
1888c2ecf20Sopenharmony_ci	tep->cmdlist = NULL;
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ci	return 0;
1918c2ecf20Sopenharmony_ci}
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_cistatic const char *find_cmdline(struct tep_handle *tep, int pid)
1948c2ecf20Sopenharmony_ci{
1958c2ecf20Sopenharmony_ci	const struct tep_cmdline *comm;
1968c2ecf20Sopenharmony_ci	struct tep_cmdline key;
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ci	if (!pid)
1998c2ecf20Sopenharmony_ci		return "<idle>";
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_ci	if (!tep->cmdlines && cmdline_init(tep))
2028c2ecf20Sopenharmony_ci		return "<not enough memory for cmdlines!>";
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_ci	key.pid = pid;
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci	comm = bsearch(&key, tep->cmdlines, tep->cmdline_count,
2078c2ecf20Sopenharmony_ci		       sizeof(*tep->cmdlines), cmdline_cmp);
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci	if (comm)
2108c2ecf20Sopenharmony_ci		return comm->comm;
2118c2ecf20Sopenharmony_ci	return "<...>";
2128c2ecf20Sopenharmony_ci}
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_ci/**
2158c2ecf20Sopenharmony_ci * tep_is_pid_registered - return if a pid has a cmdline registered
2168c2ecf20Sopenharmony_ci * @tep: a handle to the trace event parser context
2178c2ecf20Sopenharmony_ci * @pid: The pid to check if it has a cmdline registered with.
2188c2ecf20Sopenharmony_ci *
2198c2ecf20Sopenharmony_ci * Returns true if the pid has a cmdline mapped to it
2208c2ecf20Sopenharmony_ci * false otherwise.
2218c2ecf20Sopenharmony_ci */
2228c2ecf20Sopenharmony_cibool tep_is_pid_registered(struct tep_handle *tep, int pid)
2238c2ecf20Sopenharmony_ci{
2248c2ecf20Sopenharmony_ci	const struct tep_cmdline *comm;
2258c2ecf20Sopenharmony_ci	struct tep_cmdline key;
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_ci	if (!pid)
2288c2ecf20Sopenharmony_ci		return true;
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci	if (!tep->cmdlines && cmdline_init(tep))
2318c2ecf20Sopenharmony_ci		return false;
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci	key.pid = pid;
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci	comm = bsearch(&key, tep->cmdlines, tep->cmdline_count,
2368c2ecf20Sopenharmony_ci		       sizeof(*tep->cmdlines), cmdline_cmp);
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_ci	if (comm)
2398c2ecf20Sopenharmony_ci		return true;
2408c2ecf20Sopenharmony_ci	return false;
2418c2ecf20Sopenharmony_ci}
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci/*
2448c2ecf20Sopenharmony_ci * If the command lines have been converted to an array, then
2458c2ecf20Sopenharmony_ci * we must add this pid. This is much slower than when cmdlines
2468c2ecf20Sopenharmony_ci * are added before the array is initialized.
2478c2ecf20Sopenharmony_ci */
2488c2ecf20Sopenharmony_cistatic int add_new_comm(struct tep_handle *tep,
2498c2ecf20Sopenharmony_ci			const char *comm, int pid, bool override)
2508c2ecf20Sopenharmony_ci{
2518c2ecf20Sopenharmony_ci	struct tep_cmdline *cmdlines = tep->cmdlines;
2528c2ecf20Sopenharmony_ci	struct tep_cmdline *cmdline;
2538c2ecf20Sopenharmony_ci	struct tep_cmdline key;
2548c2ecf20Sopenharmony_ci	char *new_comm;
2558c2ecf20Sopenharmony_ci	int cnt;
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci	if (!pid)
2588c2ecf20Sopenharmony_ci		return 0;
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_ci	/* avoid duplicates */
2618c2ecf20Sopenharmony_ci	key.pid = pid;
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_ci	cmdline = bsearch(&key, tep->cmdlines, tep->cmdline_count,
2648c2ecf20Sopenharmony_ci			  sizeof(*tep->cmdlines), cmdline_cmp);
2658c2ecf20Sopenharmony_ci	if (cmdline) {
2668c2ecf20Sopenharmony_ci		if (!override) {
2678c2ecf20Sopenharmony_ci			errno = EEXIST;
2688c2ecf20Sopenharmony_ci			return -1;
2698c2ecf20Sopenharmony_ci		}
2708c2ecf20Sopenharmony_ci		new_comm = strdup(comm);
2718c2ecf20Sopenharmony_ci		if (!new_comm) {
2728c2ecf20Sopenharmony_ci			errno = ENOMEM;
2738c2ecf20Sopenharmony_ci			return -1;
2748c2ecf20Sopenharmony_ci		}
2758c2ecf20Sopenharmony_ci		free(cmdline->comm);
2768c2ecf20Sopenharmony_ci		cmdline->comm = new_comm;
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ci		return 0;
2798c2ecf20Sopenharmony_ci	}
2808c2ecf20Sopenharmony_ci
2818c2ecf20Sopenharmony_ci	cmdlines = realloc(cmdlines, sizeof(*cmdlines) * (tep->cmdline_count + 1));
2828c2ecf20Sopenharmony_ci	if (!cmdlines) {
2838c2ecf20Sopenharmony_ci		errno = ENOMEM;
2848c2ecf20Sopenharmony_ci		return -1;
2858c2ecf20Sopenharmony_ci	}
2868c2ecf20Sopenharmony_ci	tep->cmdlines = cmdlines;
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci	key.comm = strdup(comm);
2898c2ecf20Sopenharmony_ci	if (!key.comm) {
2908c2ecf20Sopenharmony_ci		errno = ENOMEM;
2918c2ecf20Sopenharmony_ci		return -1;
2928c2ecf20Sopenharmony_ci	}
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci	if (!tep->cmdline_count) {
2958c2ecf20Sopenharmony_ci		/* no entries yet */
2968c2ecf20Sopenharmony_ci		tep->cmdlines[0] = key;
2978c2ecf20Sopenharmony_ci		tep->cmdline_count++;
2988c2ecf20Sopenharmony_ci		return 0;
2998c2ecf20Sopenharmony_ci	}
3008c2ecf20Sopenharmony_ci
3018c2ecf20Sopenharmony_ci	/* Now find where we want to store the new cmdline */
3028c2ecf20Sopenharmony_ci	cmdline = bsearch(&key, tep->cmdlines, tep->cmdline_count - 1,
3038c2ecf20Sopenharmony_ci			  sizeof(*tep->cmdlines), cmdline_slot_cmp);
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci	cnt = tep->cmdline_count;
3068c2ecf20Sopenharmony_ci	if (cmdline) {
3078c2ecf20Sopenharmony_ci		/* cmdline points to the one before the spot we want */
3088c2ecf20Sopenharmony_ci		cmdline++;
3098c2ecf20Sopenharmony_ci		cnt -= cmdline - tep->cmdlines;
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_ci	} else {
3128c2ecf20Sopenharmony_ci		/* The new entry is either before or after the list */
3138c2ecf20Sopenharmony_ci		if (key.pid > tep->cmdlines[tep->cmdline_count - 1].pid) {
3148c2ecf20Sopenharmony_ci			tep->cmdlines[tep->cmdline_count++] = key;
3158c2ecf20Sopenharmony_ci			return 0;
3168c2ecf20Sopenharmony_ci		}
3178c2ecf20Sopenharmony_ci		cmdline = &tep->cmdlines[0];
3188c2ecf20Sopenharmony_ci	}
3198c2ecf20Sopenharmony_ci	memmove(cmdline + 1, cmdline, (cnt * sizeof(*cmdline)));
3208c2ecf20Sopenharmony_ci	*cmdline = key;
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_ci	tep->cmdline_count++;
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci	return 0;
3258c2ecf20Sopenharmony_ci}
3268c2ecf20Sopenharmony_ci
3278c2ecf20Sopenharmony_cistatic int _tep_register_comm(struct tep_handle *tep,
3288c2ecf20Sopenharmony_ci			      const char *comm, int pid, bool override)
3298c2ecf20Sopenharmony_ci{
3308c2ecf20Sopenharmony_ci	struct cmdline_list *item;
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ci	if (tep->cmdlines)
3338c2ecf20Sopenharmony_ci		return add_new_comm(tep, comm, pid, override);
3348c2ecf20Sopenharmony_ci
3358c2ecf20Sopenharmony_ci	item = malloc(sizeof(*item));
3368c2ecf20Sopenharmony_ci	if (!item)
3378c2ecf20Sopenharmony_ci		return -1;
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_ci	if (comm)
3408c2ecf20Sopenharmony_ci		item->comm = strdup(comm);
3418c2ecf20Sopenharmony_ci	else
3428c2ecf20Sopenharmony_ci		item->comm = strdup("<...>");
3438c2ecf20Sopenharmony_ci	if (!item->comm) {
3448c2ecf20Sopenharmony_ci		free(item);
3458c2ecf20Sopenharmony_ci		return -1;
3468c2ecf20Sopenharmony_ci	}
3478c2ecf20Sopenharmony_ci	item->pid = pid;
3488c2ecf20Sopenharmony_ci	item->next = tep->cmdlist;
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_ci	tep->cmdlist = item;
3518c2ecf20Sopenharmony_ci	tep->cmdline_count++;
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_ci	return 0;
3548c2ecf20Sopenharmony_ci}
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_ci/**
3578c2ecf20Sopenharmony_ci * tep_register_comm - register a pid / comm mapping
3588c2ecf20Sopenharmony_ci * @tep: a handle to the trace event parser context
3598c2ecf20Sopenharmony_ci * @comm: the command line to register
3608c2ecf20Sopenharmony_ci * @pid: the pid to map the command line to
3618c2ecf20Sopenharmony_ci *
3628c2ecf20Sopenharmony_ci * This adds a mapping to search for command line names with
3638c2ecf20Sopenharmony_ci * a given pid. The comm is duplicated. If a command with the same pid
3648c2ecf20Sopenharmony_ci * already exist, -1 is returned and errno is set to EEXIST
3658c2ecf20Sopenharmony_ci */
3668c2ecf20Sopenharmony_ciint tep_register_comm(struct tep_handle *tep, const char *comm, int pid)
3678c2ecf20Sopenharmony_ci{
3688c2ecf20Sopenharmony_ci	return _tep_register_comm(tep, comm, pid, false);
3698c2ecf20Sopenharmony_ci}
3708c2ecf20Sopenharmony_ci
3718c2ecf20Sopenharmony_ci/**
3728c2ecf20Sopenharmony_ci * tep_override_comm - register a pid / comm mapping
3738c2ecf20Sopenharmony_ci * @tep: a handle to the trace event parser context
3748c2ecf20Sopenharmony_ci * @comm: the command line to register
3758c2ecf20Sopenharmony_ci * @pid: the pid to map the command line to
3768c2ecf20Sopenharmony_ci *
3778c2ecf20Sopenharmony_ci * This adds a mapping to search for command line names with
3788c2ecf20Sopenharmony_ci * a given pid. The comm is duplicated. If a command with the same pid
3798c2ecf20Sopenharmony_ci * already exist, the command string is udapted with the new one
3808c2ecf20Sopenharmony_ci */
3818c2ecf20Sopenharmony_ciint tep_override_comm(struct tep_handle *tep, const char *comm, int pid)
3828c2ecf20Sopenharmony_ci{
3838c2ecf20Sopenharmony_ci	if (!tep->cmdlines && cmdline_init(tep)) {
3848c2ecf20Sopenharmony_ci		errno = ENOMEM;
3858c2ecf20Sopenharmony_ci		return -1;
3868c2ecf20Sopenharmony_ci	}
3878c2ecf20Sopenharmony_ci	return _tep_register_comm(tep, comm, pid, true);
3888c2ecf20Sopenharmony_ci}
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_cistruct func_map {
3918c2ecf20Sopenharmony_ci	unsigned long long		addr;
3928c2ecf20Sopenharmony_ci	char				*func;
3938c2ecf20Sopenharmony_ci	char				*mod;
3948c2ecf20Sopenharmony_ci};
3958c2ecf20Sopenharmony_ci
3968c2ecf20Sopenharmony_cistruct func_list {
3978c2ecf20Sopenharmony_ci	struct func_list	*next;
3988c2ecf20Sopenharmony_ci	unsigned long long	addr;
3998c2ecf20Sopenharmony_ci	char			*func;
4008c2ecf20Sopenharmony_ci	char			*mod;
4018c2ecf20Sopenharmony_ci};
4028c2ecf20Sopenharmony_ci
4038c2ecf20Sopenharmony_cistatic int func_cmp(const void *a, const void *b)
4048c2ecf20Sopenharmony_ci{
4058c2ecf20Sopenharmony_ci	const struct func_map *fa = a;
4068c2ecf20Sopenharmony_ci	const struct func_map *fb = b;
4078c2ecf20Sopenharmony_ci
4088c2ecf20Sopenharmony_ci	if (fa->addr < fb->addr)
4098c2ecf20Sopenharmony_ci		return -1;
4108c2ecf20Sopenharmony_ci	if (fa->addr > fb->addr)
4118c2ecf20Sopenharmony_ci		return 1;
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_ci	return 0;
4148c2ecf20Sopenharmony_ci}
4158c2ecf20Sopenharmony_ci
4168c2ecf20Sopenharmony_ci/*
4178c2ecf20Sopenharmony_ci * We are searching for a record in between, not an exact
4188c2ecf20Sopenharmony_ci * match.
4198c2ecf20Sopenharmony_ci */
4208c2ecf20Sopenharmony_cistatic int func_bcmp(const void *a, const void *b)
4218c2ecf20Sopenharmony_ci{
4228c2ecf20Sopenharmony_ci	const struct func_map *fa = a;
4238c2ecf20Sopenharmony_ci	const struct func_map *fb = b;
4248c2ecf20Sopenharmony_ci
4258c2ecf20Sopenharmony_ci	if ((fa->addr == fb->addr) ||
4268c2ecf20Sopenharmony_ci
4278c2ecf20Sopenharmony_ci	    (fa->addr > fb->addr &&
4288c2ecf20Sopenharmony_ci	     fa->addr < (fb+1)->addr))
4298c2ecf20Sopenharmony_ci		return 0;
4308c2ecf20Sopenharmony_ci
4318c2ecf20Sopenharmony_ci	if (fa->addr < fb->addr)
4328c2ecf20Sopenharmony_ci		return -1;
4338c2ecf20Sopenharmony_ci
4348c2ecf20Sopenharmony_ci	return 1;
4358c2ecf20Sopenharmony_ci}
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_cistatic int func_map_init(struct tep_handle *tep)
4388c2ecf20Sopenharmony_ci{
4398c2ecf20Sopenharmony_ci	struct func_list *funclist;
4408c2ecf20Sopenharmony_ci	struct func_list *item;
4418c2ecf20Sopenharmony_ci	struct func_map *func_map;
4428c2ecf20Sopenharmony_ci	int i;
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_ci	func_map = malloc(sizeof(*func_map) * (tep->func_count + 1));
4458c2ecf20Sopenharmony_ci	if (!func_map)
4468c2ecf20Sopenharmony_ci		return -1;
4478c2ecf20Sopenharmony_ci
4488c2ecf20Sopenharmony_ci	funclist = tep->funclist;
4498c2ecf20Sopenharmony_ci
4508c2ecf20Sopenharmony_ci	i = 0;
4518c2ecf20Sopenharmony_ci	while (funclist) {
4528c2ecf20Sopenharmony_ci		func_map[i].func = funclist->func;
4538c2ecf20Sopenharmony_ci		func_map[i].addr = funclist->addr;
4548c2ecf20Sopenharmony_ci		func_map[i].mod = funclist->mod;
4558c2ecf20Sopenharmony_ci		i++;
4568c2ecf20Sopenharmony_ci		item = funclist;
4578c2ecf20Sopenharmony_ci		funclist = funclist->next;
4588c2ecf20Sopenharmony_ci		free(item);
4598c2ecf20Sopenharmony_ci	}
4608c2ecf20Sopenharmony_ci
4618c2ecf20Sopenharmony_ci	qsort(func_map, tep->func_count, sizeof(*func_map), func_cmp);
4628c2ecf20Sopenharmony_ci
4638c2ecf20Sopenharmony_ci	/*
4648c2ecf20Sopenharmony_ci	 * Add a special record at the end.
4658c2ecf20Sopenharmony_ci	 */
4668c2ecf20Sopenharmony_ci	func_map[tep->func_count].func = NULL;
4678c2ecf20Sopenharmony_ci	func_map[tep->func_count].addr = 0;
4688c2ecf20Sopenharmony_ci	func_map[tep->func_count].mod = NULL;
4698c2ecf20Sopenharmony_ci
4708c2ecf20Sopenharmony_ci	tep->func_map = func_map;
4718c2ecf20Sopenharmony_ci	tep->funclist = NULL;
4728c2ecf20Sopenharmony_ci
4738c2ecf20Sopenharmony_ci	return 0;
4748c2ecf20Sopenharmony_ci}
4758c2ecf20Sopenharmony_ci
4768c2ecf20Sopenharmony_cistatic struct func_map *
4778c2ecf20Sopenharmony_ci__find_func(struct tep_handle *tep, unsigned long long addr)
4788c2ecf20Sopenharmony_ci{
4798c2ecf20Sopenharmony_ci	struct func_map *func;
4808c2ecf20Sopenharmony_ci	struct func_map key;
4818c2ecf20Sopenharmony_ci
4828c2ecf20Sopenharmony_ci	if (!tep->func_map)
4838c2ecf20Sopenharmony_ci		func_map_init(tep);
4848c2ecf20Sopenharmony_ci
4858c2ecf20Sopenharmony_ci	key.addr = addr;
4868c2ecf20Sopenharmony_ci
4878c2ecf20Sopenharmony_ci	func = bsearch(&key, tep->func_map, tep->func_count,
4888c2ecf20Sopenharmony_ci		       sizeof(*tep->func_map), func_bcmp);
4898c2ecf20Sopenharmony_ci
4908c2ecf20Sopenharmony_ci	return func;
4918c2ecf20Sopenharmony_ci}
4928c2ecf20Sopenharmony_ci
4938c2ecf20Sopenharmony_cistruct func_resolver {
4948c2ecf20Sopenharmony_ci	tep_func_resolver_t	*func;
4958c2ecf20Sopenharmony_ci	void			*priv;
4968c2ecf20Sopenharmony_ci	struct func_map		map;
4978c2ecf20Sopenharmony_ci};
4988c2ecf20Sopenharmony_ci
4998c2ecf20Sopenharmony_ci/**
5008c2ecf20Sopenharmony_ci * tep_set_function_resolver - set an alternative function resolver
5018c2ecf20Sopenharmony_ci * @tep: a handle to the trace event parser context
5028c2ecf20Sopenharmony_ci * @resolver: function to be used
5038c2ecf20Sopenharmony_ci * @priv: resolver function private state.
5048c2ecf20Sopenharmony_ci *
5058c2ecf20Sopenharmony_ci * Some tools may have already a way to resolve kernel functions, allow them to
5068c2ecf20Sopenharmony_ci * keep using it instead of duplicating all the entries inside tep->funclist.
5078c2ecf20Sopenharmony_ci */
5088c2ecf20Sopenharmony_ciint tep_set_function_resolver(struct tep_handle *tep,
5098c2ecf20Sopenharmony_ci			      tep_func_resolver_t *func, void *priv)
5108c2ecf20Sopenharmony_ci{
5118c2ecf20Sopenharmony_ci	struct func_resolver *resolver = malloc(sizeof(*resolver));
5128c2ecf20Sopenharmony_ci
5138c2ecf20Sopenharmony_ci	if (resolver == NULL)
5148c2ecf20Sopenharmony_ci		return -1;
5158c2ecf20Sopenharmony_ci
5168c2ecf20Sopenharmony_ci	resolver->func = func;
5178c2ecf20Sopenharmony_ci	resolver->priv = priv;
5188c2ecf20Sopenharmony_ci
5198c2ecf20Sopenharmony_ci	free(tep->func_resolver);
5208c2ecf20Sopenharmony_ci	tep->func_resolver = resolver;
5218c2ecf20Sopenharmony_ci
5228c2ecf20Sopenharmony_ci	return 0;
5238c2ecf20Sopenharmony_ci}
5248c2ecf20Sopenharmony_ci
5258c2ecf20Sopenharmony_ci/**
5268c2ecf20Sopenharmony_ci * tep_reset_function_resolver - reset alternative function resolver
5278c2ecf20Sopenharmony_ci * @tep: a handle to the trace event parser context
5288c2ecf20Sopenharmony_ci *
5298c2ecf20Sopenharmony_ci * Stop using whatever alternative resolver was set, use the default
5308c2ecf20Sopenharmony_ci * one instead.
5318c2ecf20Sopenharmony_ci */
5328c2ecf20Sopenharmony_civoid tep_reset_function_resolver(struct tep_handle *tep)
5338c2ecf20Sopenharmony_ci{
5348c2ecf20Sopenharmony_ci	free(tep->func_resolver);
5358c2ecf20Sopenharmony_ci	tep->func_resolver = NULL;
5368c2ecf20Sopenharmony_ci}
5378c2ecf20Sopenharmony_ci
5388c2ecf20Sopenharmony_cistatic struct func_map *
5398c2ecf20Sopenharmony_cifind_func(struct tep_handle *tep, unsigned long long addr)
5408c2ecf20Sopenharmony_ci{
5418c2ecf20Sopenharmony_ci	struct func_map *map;
5428c2ecf20Sopenharmony_ci
5438c2ecf20Sopenharmony_ci	if (!tep->func_resolver)
5448c2ecf20Sopenharmony_ci		return __find_func(tep, addr);
5458c2ecf20Sopenharmony_ci
5468c2ecf20Sopenharmony_ci	map = &tep->func_resolver->map;
5478c2ecf20Sopenharmony_ci	map->mod  = NULL;
5488c2ecf20Sopenharmony_ci	map->addr = addr;
5498c2ecf20Sopenharmony_ci	map->func = tep->func_resolver->func(tep->func_resolver->priv,
5508c2ecf20Sopenharmony_ci					     &map->addr, &map->mod);
5518c2ecf20Sopenharmony_ci	if (map->func == NULL)
5528c2ecf20Sopenharmony_ci		return NULL;
5538c2ecf20Sopenharmony_ci
5548c2ecf20Sopenharmony_ci	return map;
5558c2ecf20Sopenharmony_ci}
5568c2ecf20Sopenharmony_ci
5578c2ecf20Sopenharmony_ci/**
5588c2ecf20Sopenharmony_ci * tep_find_function - find a function by a given address
5598c2ecf20Sopenharmony_ci * @tep: a handle to the trace event parser context
5608c2ecf20Sopenharmony_ci * @addr: the address to find the function with
5618c2ecf20Sopenharmony_ci *
5628c2ecf20Sopenharmony_ci * Returns a pointer to the function stored that has the given
5638c2ecf20Sopenharmony_ci * address. Note, the address does not have to be exact, it
5648c2ecf20Sopenharmony_ci * will select the function that would contain the address.
5658c2ecf20Sopenharmony_ci */
5668c2ecf20Sopenharmony_ciconst char *tep_find_function(struct tep_handle *tep, unsigned long long addr)
5678c2ecf20Sopenharmony_ci{
5688c2ecf20Sopenharmony_ci	struct func_map *map;
5698c2ecf20Sopenharmony_ci
5708c2ecf20Sopenharmony_ci	map = find_func(tep, addr);
5718c2ecf20Sopenharmony_ci	if (!map)
5728c2ecf20Sopenharmony_ci		return NULL;
5738c2ecf20Sopenharmony_ci
5748c2ecf20Sopenharmony_ci	return map->func;
5758c2ecf20Sopenharmony_ci}
5768c2ecf20Sopenharmony_ci
5778c2ecf20Sopenharmony_ci/**
5788c2ecf20Sopenharmony_ci * tep_find_function_address - find a function address by a given address
5798c2ecf20Sopenharmony_ci * @tep: a handle to the trace event parser context
5808c2ecf20Sopenharmony_ci * @addr: the address to find the function with
5818c2ecf20Sopenharmony_ci *
5828c2ecf20Sopenharmony_ci * Returns the address the function starts at. This can be used in
5838c2ecf20Sopenharmony_ci * conjunction with tep_find_function to print both the function
5848c2ecf20Sopenharmony_ci * name and the function offset.
5858c2ecf20Sopenharmony_ci */
5868c2ecf20Sopenharmony_ciunsigned long long
5878c2ecf20Sopenharmony_citep_find_function_address(struct tep_handle *tep, unsigned long long addr)
5888c2ecf20Sopenharmony_ci{
5898c2ecf20Sopenharmony_ci	struct func_map *map;
5908c2ecf20Sopenharmony_ci
5918c2ecf20Sopenharmony_ci	map = find_func(tep, addr);
5928c2ecf20Sopenharmony_ci	if (!map)
5938c2ecf20Sopenharmony_ci		return 0;
5948c2ecf20Sopenharmony_ci
5958c2ecf20Sopenharmony_ci	return map->addr;
5968c2ecf20Sopenharmony_ci}
5978c2ecf20Sopenharmony_ci
5988c2ecf20Sopenharmony_ci/**
5998c2ecf20Sopenharmony_ci * tep_register_function - register a function with a given address
6008c2ecf20Sopenharmony_ci * @tep: a handle to the trace event parser context
6018c2ecf20Sopenharmony_ci * @function: the function name to register
6028c2ecf20Sopenharmony_ci * @addr: the address the function starts at
6038c2ecf20Sopenharmony_ci * @mod: the kernel module the function may be in (NULL for none)
6048c2ecf20Sopenharmony_ci *
6058c2ecf20Sopenharmony_ci * This registers a function name with an address and module.
6068c2ecf20Sopenharmony_ci * The @func passed in is duplicated.
6078c2ecf20Sopenharmony_ci */
6088c2ecf20Sopenharmony_ciint tep_register_function(struct tep_handle *tep, char *func,
6098c2ecf20Sopenharmony_ci			  unsigned long long addr, char *mod)
6108c2ecf20Sopenharmony_ci{
6118c2ecf20Sopenharmony_ci	struct func_list *item = malloc(sizeof(*item));
6128c2ecf20Sopenharmony_ci
6138c2ecf20Sopenharmony_ci	if (!item)
6148c2ecf20Sopenharmony_ci		return -1;
6158c2ecf20Sopenharmony_ci
6168c2ecf20Sopenharmony_ci	item->next = tep->funclist;
6178c2ecf20Sopenharmony_ci	item->func = strdup(func);
6188c2ecf20Sopenharmony_ci	if (!item->func)
6198c2ecf20Sopenharmony_ci		goto out_free;
6208c2ecf20Sopenharmony_ci
6218c2ecf20Sopenharmony_ci	if (mod) {
6228c2ecf20Sopenharmony_ci		item->mod = strdup(mod);
6238c2ecf20Sopenharmony_ci		if (!item->mod)
6248c2ecf20Sopenharmony_ci			goto out_free_func;
6258c2ecf20Sopenharmony_ci	} else
6268c2ecf20Sopenharmony_ci		item->mod = NULL;
6278c2ecf20Sopenharmony_ci	item->addr = addr;
6288c2ecf20Sopenharmony_ci
6298c2ecf20Sopenharmony_ci	tep->funclist = item;
6308c2ecf20Sopenharmony_ci	tep->func_count++;
6318c2ecf20Sopenharmony_ci
6328c2ecf20Sopenharmony_ci	return 0;
6338c2ecf20Sopenharmony_ci
6348c2ecf20Sopenharmony_ciout_free_func:
6358c2ecf20Sopenharmony_ci	free(item->func);
6368c2ecf20Sopenharmony_ci	item->func = NULL;
6378c2ecf20Sopenharmony_ciout_free:
6388c2ecf20Sopenharmony_ci	free(item);
6398c2ecf20Sopenharmony_ci	errno = ENOMEM;
6408c2ecf20Sopenharmony_ci	return -1;
6418c2ecf20Sopenharmony_ci}
6428c2ecf20Sopenharmony_ci
6438c2ecf20Sopenharmony_ci/**
6448c2ecf20Sopenharmony_ci * tep_print_funcs - print out the stored functions
6458c2ecf20Sopenharmony_ci * @tep: a handle to the trace event parser context
6468c2ecf20Sopenharmony_ci *
6478c2ecf20Sopenharmony_ci * This prints out the stored functions.
6488c2ecf20Sopenharmony_ci */
6498c2ecf20Sopenharmony_civoid tep_print_funcs(struct tep_handle *tep)
6508c2ecf20Sopenharmony_ci{
6518c2ecf20Sopenharmony_ci	int i;
6528c2ecf20Sopenharmony_ci
6538c2ecf20Sopenharmony_ci	if (!tep->func_map)
6548c2ecf20Sopenharmony_ci		func_map_init(tep);
6558c2ecf20Sopenharmony_ci
6568c2ecf20Sopenharmony_ci	for (i = 0; i < (int)tep->func_count; i++) {
6578c2ecf20Sopenharmony_ci		printf("%016llx %s",
6588c2ecf20Sopenharmony_ci		       tep->func_map[i].addr,
6598c2ecf20Sopenharmony_ci		       tep->func_map[i].func);
6608c2ecf20Sopenharmony_ci		if (tep->func_map[i].mod)
6618c2ecf20Sopenharmony_ci			printf(" [%s]\n", tep->func_map[i].mod);
6628c2ecf20Sopenharmony_ci		else
6638c2ecf20Sopenharmony_ci			printf("\n");
6648c2ecf20Sopenharmony_ci	}
6658c2ecf20Sopenharmony_ci}
6668c2ecf20Sopenharmony_ci
6678c2ecf20Sopenharmony_cistruct printk_map {
6688c2ecf20Sopenharmony_ci	unsigned long long		addr;
6698c2ecf20Sopenharmony_ci	char				*printk;
6708c2ecf20Sopenharmony_ci};
6718c2ecf20Sopenharmony_ci
6728c2ecf20Sopenharmony_cistruct printk_list {
6738c2ecf20Sopenharmony_ci	struct printk_list	*next;
6748c2ecf20Sopenharmony_ci	unsigned long long	addr;
6758c2ecf20Sopenharmony_ci	char			*printk;
6768c2ecf20Sopenharmony_ci};
6778c2ecf20Sopenharmony_ci
6788c2ecf20Sopenharmony_cistatic int printk_cmp(const void *a, const void *b)
6798c2ecf20Sopenharmony_ci{
6808c2ecf20Sopenharmony_ci	const struct printk_map *pa = a;
6818c2ecf20Sopenharmony_ci	const struct printk_map *pb = b;
6828c2ecf20Sopenharmony_ci
6838c2ecf20Sopenharmony_ci	if (pa->addr < pb->addr)
6848c2ecf20Sopenharmony_ci		return -1;
6858c2ecf20Sopenharmony_ci	if (pa->addr > pb->addr)
6868c2ecf20Sopenharmony_ci		return 1;
6878c2ecf20Sopenharmony_ci
6888c2ecf20Sopenharmony_ci	return 0;
6898c2ecf20Sopenharmony_ci}
6908c2ecf20Sopenharmony_ci
6918c2ecf20Sopenharmony_cistatic int printk_map_init(struct tep_handle *tep)
6928c2ecf20Sopenharmony_ci{
6938c2ecf20Sopenharmony_ci	struct printk_list *printklist;
6948c2ecf20Sopenharmony_ci	struct printk_list *item;
6958c2ecf20Sopenharmony_ci	struct printk_map *printk_map;
6968c2ecf20Sopenharmony_ci	int i;
6978c2ecf20Sopenharmony_ci
6988c2ecf20Sopenharmony_ci	printk_map = malloc(sizeof(*printk_map) * (tep->printk_count + 1));
6998c2ecf20Sopenharmony_ci	if (!printk_map)
7008c2ecf20Sopenharmony_ci		return -1;
7018c2ecf20Sopenharmony_ci
7028c2ecf20Sopenharmony_ci	printklist = tep->printklist;
7038c2ecf20Sopenharmony_ci
7048c2ecf20Sopenharmony_ci	i = 0;
7058c2ecf20Sopenharmony_ci	while (printklist) {
7068c2ecf20Sopenharmony_ci		printk_map[i].printk = printklist->printk;
7078c2ecf20Sopenharmony_ci		printk_map[i].addr = printklist->addr;
7088c2ecf20Sopenharmony_ci		i++;
7098c2ecf20Sopenharmony_ci		item = printklist;
7108c2ecf20Sopenharmony_ci		printklist = printklist->next;
7118c2ecf20Sopenharmony_ci		free(item);
7128c2ecf20Sopenharmony_ci	}
7138c2ecf20Sopenharmony_ci
7148c2ecf20Sopenharmony_ci	qsort(printk_map, tep->printk_count, sizeof(*printk_map), printk_cmp);
7158c2ecf20Sopenharmony_ci
7168c2ecf20Sopenharmony_ci	tep->printk_map = printk_map;
7178c2ecf20Sopenharmony_ci	tep->printklist = NULL;
7188c2ecf20Sopenharmony_ci
7198c2ecf20Sopenharmony_ci	return 0;
7208c2ecf20Sopenharmony_ci}
7218c2ecf20Sopenharmony_ci
7228c2ecf20Sopenharmony_cistatic struct printk_map *
7238c2ecf20Sopenharmony_cifind_printk(struct tep_handle *tep, unsigned long long addr)
7248c2ecf20Sopenharmony_ci{
7258c2ecf20Sopenharmony_ci	struct printk_map *printk;
7268c2ecf20Sopenharmony_ci	struct printk_map key;
7278c2ecf20Sopenharmony_ci
7288c2ecf20Sopenharmony_ci	if (!tep->printk_map && printk_map_init(tep))
7298c2ecf20Sopenharmony_ci		return NULL;
7308c2ecf20Sopenharmony_ci
7318c2ecf20Sopenharmony_ci	key.addr = addr;
7328c2ecf20Sopenharmony_ci
7338c2ecf20Sopenharmony_ci	printk = bsearch(&key, tep->printk_map, tep->printk_count,
7348c2ecf20Sopenharmony_ci			 sizeof(*tep->printk_map), printk_cmp);
7358c2ecf20Sopenharmony_ci
7368c2ecf20Sopenharmony_ci	return printk;
7378c2ecf20Sopenharmony_ci}
7388c2ecf20Sopenharmony_ci
7398c2ecf20Sopenharmony_ci/**
7408c2ecf20Sopenharmony_ci * tep_register_print_string - register a string by its address
7418c2ecf20Sopenharmony_ci * @tep: a handle to the trace event parser context
7428c2ecf20Sopenharmony_ci * @fmt: the string format to register
7438c2ecf20Sopenharmony_ci * @addr: the address the string was located at
7448c2ecf20Sopenharmony_ci *
7458c2ecf20Sopenharmony_ci * This registers a string by the address it was stored in the kernel.
7468c2ecf20Sopenharmony_ci * The @fmt passed in is duplicated.
7478c2ecf20Sopenharmony_ci */
7488c2ecf20Sopenharmony_ciint tep_register_print_string(struct tep_handle *tep, const char *fmt,
7498c2ecf20Sopenharmony_ci			      unsigned long long addr)
7508c2ecf20Sopenharmony_ci{
7518c2ecf20Sopenharmony_ci	struct printk_list *item = malloc(sizeof(*item));
7528c2ecf20Sopenharmony_ci	char *p;
7538c2ecf20Sopenharmony_ci
7548c2ecf20Sopenharmony_ci	if (!item)
7558c2ecf20Sopenharmony_ci		return -1;
7568c2ecf20Sopenharmony_ci
7578c2ecf20Sopenharmony_ci	item->next = tep->printklist;
7588c2ecf20Sopenharmony_ci	item->addr = addr;
7598c2ecf20Sopenharmony_ci
7608c2ecf20Sopenharmony_ci	/* Strip off quotes and '\n' from the end */
7618c2ecf20Sopenharmony_ci	if (fmt[0] == '"')
7628c2ecf20Sopenharmony_ci		fmt++;
7638c2ecf20Sopenharmony_ci	item->printk = strdup(fmt);
7648c2ecf20Sopenharmony_ci	if (!item->printk)
7658c2ecf20Sopenharmony_ci		goto out_free;
7668c2ecf20Sopenharmony_ci
7678c2ecf20Sopenharmony_ci	p = item->printk + strlen(item->printk) - 1;
7688c2ecf20Sopenharmony_ci	if (*p == '"')
7698c2ecf20Sopenharmony_ci		*p = 0;
7708c2ecf20Sopenharmony_ci
7718c2ecf20Sopenharmony_ci	p -= 2;
7728c2ecf20Sopenharmony_ci	if (strcmp(p, "\\n") == 0)
7738c2ecf20Sopenharmony_ci		*p = 0;
7748c2ecf20Sopenharmony_ci
7758c2ecf20Sopenharmony_ci	tep->printklist = item;
7768c2ecf20Sopenharmony_ci	tep->printk_count++;
7778c2ecf20Sopenharmony_ci
7788c2ecf20Sopenharmony_ci	return 0;
7798c2ecf20Sopenharmony_ci
7808c2ecf20Sopenharmony_ciout_free:
7818c2ecf20Sopenharmony_ci	free(item);
7828c2ecf20Sopenharmony_ci	errno = ENOMEM;
7838c2ecf20Sopenharmony_ci	return -1;
7848c2ecf20Sopenharmony_ci}
7858c2ecf20Sopenharmony_ci
7868c2ecf20Sopenharmony_ci/**
7878c2ecf20Sopenharmony_ci * tep_print_printk - print out the stored strings
7888c2ecf20Sopenharmony_ci * @tep: a handle to the trace event parser context
7898c2ecf20Sopenharmony_ci *
7908c2ecf20Sopenharmony_ci * This prints the string formats that were stored.
7918c2ecf20Sopenharmony_ci */
7928c2ecf20Sopenharmony_civoid tep_print_printk(struct tep_handle *tep)
7938c2ecf20Sopenharmony_ci{
7948c2ecf20Sopenharmony_ci	int i;
7958c2ecf20Sopenharmony_ci
7968c2ecf20Sopenharmony_ci	if (!tep->printk_map)
7978c2ecf20Sopenharmony_ci		printk_map_init(tep);
7988c2ecf20Sopenharmony_ci
7998c2ecf20Sopenharmony_ci	for (i = 0; i < (int)tep->printk_count; i++) {
8008c2ecf20Sopenharmony_ci		printf("%016llx %s\n",
8018c2ecf20Sopenharmony_ci		       tep->printk_map[i].addr,
8028c2ecf20Sopenharmony_ci		       tep->printk_map[i].printk);
8038c2ecf20Sopenharmony_ci	}
8048c2ecf20Sopenharmony_ci}
8058c2ecf20Sopenharmony_ci
8068c2ecf20Sopenharmony_cistatic struct tep_event *alloc_event(void)
8078c2ecf20Sopenharmony_ci{
8088c2ecf20Sopenharmony_ci	return calloc(1, sizeof(struct tep_event));
8098c2ecf20Sopenharmony_ci}
8108c2ecf20Sopenharmony_ci
8118c2ecf20Sopenharmony_cistatic int add_event(struct tep_handle *tep, struct tep_event *event)
8128c2ecf20Sopenharmony_ci{
8138c2ecf20Sopenharmony_ci	int i;
8148c2ecf20Sopenharmony_ci	struct tep_event **events = realloc(tep->events, sizeof(event) *
8158c2ecf20Sopenharmony_ci					    (tep->nr_events + 1));
8168c2ecf20Sopenharmony_ci	if (!events)
8178c2ecf20Sopenharmony_ci		return -1;
8188c2ecf20Sopenharmony_ci
8198c2ecf20Sopenharmony_ci	tep->events = events;
8208c2ecf20Sopenharmony_ci
8218c2ecf20Sopenharmony_ci	for (i = 0; i < tep->nr_events; i++) {
8228c2ecf20Sopenharmony_ci		if (tep->events[i]->id > event->id)
8238c2ecf20Sopenharmony_ci			break;
8248c2ecf20Sopenharmony_ci	}
8258c2ecf20Sopenharmony_ci	if (i < tep->nr_events)
8268c2ecf20Sopenharmony_ci		memmove(&tep->events[i + 1],
8278c2ecf20Sopenharmony_ci			&tep->events[i],
8288c2ecf20Sopenharmony_ci			sizeof(event) * (tep->nr_events - i));
8298c2ecf20Sopenharmony_ci
8308c2ecf20Sopenharmony_ci	tep->events[i] = event;
8318c2ecf20Sopenharmony_ci	tep->nr_events++;
8328c2ecf20Sopenharmony_ci
8338c2ecf20Sopenharmony_ci	event->tep = tep;
8348c2ecf20Sopenharmony_ci
8358c2ecf20Sopenharmony_ci	return 0;
8368c2ecf20Sopenharmony_ci}
8378c2ecf20Sopenharmony_ci
8388c2ecf20Sopenharmony_cistatic int event_item_type(enum tep_event_type type)
8398c2ecf20Sopenharmony_ci{
8408c2ecf20Sopenharmony_ci	switch (type) {
8418c2ecf20Sopenharmony_ci	case TEP_EVENT_ITEM ... TEP_EVENT_SQUOTE:
8428c2ecf20Sopenharmony_ci		return 1;
8438c2ecf20Sopenharmony_ci	case TEP_EVENT_ERROR ... TEP_EVENT_DELIM:
8448c2ecf20Sopenharmony_ci	default:
8458c2ecf20Sopenharmony_ci		return 0;
8468c2ecf20Sopenharmony_ci	}
8478c2ecf20Sopenharmony_ci}
8488c2ecf20Sopenharmony_ci
8498c2ecf20Sopenharmony_cistatic void free_flag_sym(struct tep_print_flag_sym *fsym)
8508c2ecf20Sopenharmony_ci{
8518c2ecf20Sopenharmony_ci	struct tep_print_flag_sym *next;
8528c2ecf20Sopenharmony_ci
8538c2ecf20Sopenharmony_ci	while (fsym) {
8548c2ecf20Sopenharmony_ci		next = fsym->next;
8558c2ecf20Sopenharmony_ci		free(fsym->value);
8568c2ecf20Sopenharmony_ci		free(fsym->str);
8578c2ecf20Sopenharmony_ci		free(fsym);
8588c2ecf20Sopenharmony_ci		fsym = next;
8598c2ecf20Sopenharmony_ci	}
8608c2ecf20Sopenharmony_ci}
8618c2ecf20Sopenharmony_ci
8628c2ecf20Sopenharmony_cistatic void free_arg(struct tep_print_arg *arg)
8638c2ecf20Sopenharmony_ci{
8648c2ecf20Sopenharmony_ci	struct tep_print_arg *farg;
8658c2ecf20Sopenharmony_ci
8668c2ecf20Sopenharmony_ci	if (!arg)
8678c2ecf20Sopenharmony_ci		return;
8688c2ecf20Sopenharmony_ci
8698c2ecf20Sopenharmony_ci	switch (arg->type) {
8708c2ecf20Sopenharmony_ci	case TEP_PRINT_ATOM:
8718c2ecf20Sopenharmony_ci		free(arg->atom.atom);
8728c2ecf20Sopenharmony_ci		break;
8738c2ecf20Sopenharmony_ci	case TEP_PRINT_FIELD:
8748c2ecf20Sopenharmony_ci		free(arg->field.name);
8758c2ecf20Sopenharmony_ci		break;
8768c2ecf20Sopenharmony_ci	case TEP_PRINT_FLAGS:
8778c2ecf20Sopenharmony_ci		free_arg(arg->flags.field);
8788c2ecf20Sopenharmony_ci		free(arg->flags.delim);
8798c2ecf20Sopenharmony_ci		free_flag_sym(arg->flags.flags);
8808c2ecf20Sopenharmony_ci		break;
8818c2ecf20Sopenharmony_ci	case TEP_PRINT_SYMBOL:
8828c2ecf20Sopenharmony_ci		free_arg(arg->symbol.field);
8838c2ecf20Sopenharmony_ci		free_flag_sym(arg->symbol.symbols);
8848c2ecf20Sopenharmony_ci		break;
8858c2ecf20Sopenharmony_ci	case TEP_PRINT_HEX:
8868c2ecf20Sopenharmony_ci	case TEP_PRINT_HEX_STR:
8878c2ecf20Sopenharmony_ci		free_arg(arg->hex.field);
8888c2ecf20Sopenharmony_ci		free_arg(arg->hex.size);
8898c2ecf20Sopenharmony_ci		break;
8908c2ecf20Sopenharmony_ci	case TEP_PRINT_INT_ARRAY:
8918c2ecf20Sopenharmony_ci		free_arg(arg->int_array.field);
8928c2ecf20Sopenharmony_ci		free_arg(arg->int_array.count);
8938c2ecf20Sopenharmony_ci		free_arg(arg->int_array.el_size);
8948c2ecf20Sopenharmony_ci		break;
8958c2ecf20Sopenharmony_ci	case TEP_PRINT_TYPE:
8968c2ecf20Sopenharmony_ci		free(arg->typecast.type);
8978c2ecf20Sopenharmony_ci		free_arg(arg->typecast.item);
8988c2ecf20Sopenharmony_ci		break;
8998c2ecf20Sopenharmony_ci	case TEP_PRINT_STRING:
9008c2ecf20Sopenharmony_ci	case TEP_PRINT_BSTRING:
9018c2ecf20Sopenharmony_ci		free(arg->string.string);
9028c2ecf20Sopenharmony_ci		break;
9038c2ecf20Sopenharmony_ci	case TEP_PRINT_BITMASK:
9048c2ecf20Sopenharmony_ci		free(arg->bitmask.bitmask);
9058c2ecf20Sopenharmony_ci		break;
9068c2ecf20Sopenharmony_ci	case TEP_PRINT_DYNAMIC_ARRAY:
9078c2ecf20Sopenharmony_ci	case TEP_PRINT_DYNAMIC_ARRAY_LEN:
9088c2ecf20Sopenharmony_ci		free(arg->dynarray.index);
9098c2ecf20Sopenharmony_ci		break;
9108c2ecf20Sopenharmony_ci	case TEP_PRINT_OP:
9118c2ecf20Sopenharmony_ci		free(arg->op.op);
9128c2ecf20Sopenharmony_ci		free_arg(arg->op.left);
9138c2ecf20Sopenharmony_ci		free_arg(arg->op.right);
9148c2ecf20Sopenharmony_ci		break;
9158c2ecf20Sopenharmony_ci	case TEP_PRINT_FUNC:
9168c2ecf20Sopenharmony_ci		while (arg->func.args) {
9178c2ecf20Sopenharmony_ci			farg = arg->func.args;
9188c2ecf20Sopenharmony_ci			arg->func.args = farg->next;
9198c2ecf20Sopenharmony_ci			free_arg(farg);
9208c2ecf20Sopenharmony_ci		}
9218c2ecf20Sopenharmony_ci		break;
9228c2ecf20Sopenharmony_ci
9238c2ecf20Sopenharmony_ci	case TEP_PRINT_NULL:
9248c2ecf20Sopenharmony_ci	default:
9258c2ecf20Sopenharmony_ci		break;
9268c2ecf20Sopenharmony_ci	}
9278c2ecf20Sopenharmony_ci
9288c2ecf20Sopenharmony_ci	free(arg);
9298c2ecf20Sopenharmony_ci}
9308c2ecf20Sopenharmony_ci
9318c2ecf20Sopenharmony_cistatic enum tep_event_type get_type(int ch)
9328c2ecf20Sopenharmony_ci{
9338c2ecf20Sopenharmony_ci	if (ch == '\n')
9348c2ecf20Sopenharmony_ci		return TEP_EVENT_NEWLINE;
9358c2ecf20Sopenharmony_ci	if (isspace(ch))
9368c2ecf20Sopenharmony_ci		return TEP_EVENT_SPACE;
9378c2ecf20Sopenharmony_ci	if (isalnum(ch) || ch == '_')
9388c2ecf20Sopenharmony_ci		return TEP_EVENT_ITEM;
9398c2ecf20Sopenharmony_ci	if (ch == '\'')
9408c2ecf20Sopenharmony_ci		return TEP_EVENT_SQUOTE;
9418c2ecf20Sopenharmony_ci	if (ch == '"')
9428c2ecf20Sopenharmony_ci		return TEP_EVENT_DQUOTE;
9438c2ecf20Sopenharmony_ci	if (!isprint(ch))
9448c2ecf20Sopenharmony_ci		return TEP_EVENT_NONE;
9458c2ecf20Sopenharmony_ci	if (ch == '(' || ch == ')' || ch == ',')
9468c2ecf20Sopenharmony_ci		return TEP_EVENT_DELIM;
9478c2ecf20Sopenharmony_ci
9488c2ecf20Sopenharmony_ci	return TEP_EVENT_OP;
9498c2ecf20Sopenharmony_ci}
9508c2ecf20Sopenharmony_ci
9518c2ecf20Sopenharmony_cistatic int __read_char(void)
9528c2ecf20Sopenharmony_ci{
9538c2ecf20Sopenharmony_ci	if (input_buf_ptr >= input_buf_siz)
9548c2ecf20Sopenharmony_ci		return -1;
9558c2ecf20Sopenharmony_ci
9568c2ecf20Sopenharmony_ci	return input_buf[input_buf_ptr++];
9578c2ecf20Sopenharmony_ci}
9588c2ecf20Sopenharmony_ci
9598c2ecf20Sopenharmony_ci/**
9608c2ecf20Sopenharmony_ci * peek_char - peek at the next character that will be read
9618c2ecf20Sopenharmony_ci *
9628c2ecf20Sopenharmony_ci * Returns the next character read, or -1 if end of buffer.
9638c2ecf20Sopenharmony_ci */
9648c2ecf20Sopenharmony_ci__hidden int peek_char(void)
9658c2ecf20Sopenharmony_ci{
9668c2ecf20Sopenharmony_ci	if (input_buf_ptr >= input_buf_siz)
9678c2ecf20Sopenharmony_ci		return -1;
9688c2ecf20Sopenharmony_ci
9698c2ecf20Sopenharmony_ci	return input_buf[input_buf_ptr];
9708c2ecf20Sopenharmony_ci}
9718c2ecf20Sopenharmony_ci
9728c2ecf20Sopenharmony_cistatic int extend_token(char **tok, char *buf, int size)
9738c2ecf20Sopenharmony_ci{
9748c2ecf20Sopenharmony_ci	char *newtok = realloc(*tok, size);
9758c2ecf20Sopenharmony_ci
9768c2ecf20Sopenharmony_ci	if (!newtok) {
9778c2ecf20Sopenharmony_ci		free(*tok);
9788c2ecf20Sopenharmony_ci		*tok = NULL;
9798c2ecf20Sopenharmony_ci		return -1;
9808c2ecf20Sopenharmony_ci	}
9818c2ecf20Sopenharmony_ci
9828c2ecf20Sopenharmony_ci	if (!*tok)
9838c2ecf20Sopenharmony_ci		strcpy(newtok, buf);
9848c2ecf20Sopenharmony_ci	else
9858c2ecf20Sopenharmony_ci		strcat(newtok, buf);
9868c2ecf20Sopenharmony_ci	*tok = newtok;
9878c2ecf20Sopenharmony_ci
9888c2ecf20Sopenharmony_ci	return 0;
9898c2ecf20Sopenharmony_ci}
9908c2ecf20Sopenharmony_ci
9918c2ecf20Sopenharmony_cistatic enum tep_event_type force_token(const char *str, char **tok);
9928c2ecf20Sopenharmony_ci
9938c2ecf20Sopenharmony_cistatic enum tep_event_type __read_token(char **tok)
9948c2ecf20Sopenharmony_ci{
9958c2ecf20Sopenharmony_ci	char buf[BUFSIZ];
9968c2ecf20Sopenharmony_ci	int ch, last_ch, quote_ch, next_ch;
9978c2ecf20Sopenharmony_ci	int i = 0;
9988c2ecf20Sopenharmony_ci	int tok_size = 0;
9998c2ecf20Sopenharmony_ci	enum tep_event_type type;
10008c2ecf20Sopenharmony_ci
10018c2ecf20Sopenharmony_ci	*tok = NULL;
10028c2ecf20Sopenharmony_ci
10038c2ecf20Sopenharmony_ci
10048c2ecf20Sopenharmony_ci	ch = __read_char();
10058c2ecf20Sopenharmony_ci	if (ch < 0)
10068c2ecf20Sopenharmony_ci		return TEP_EVENT_NONE;
10078c2ecf20Sopenharmony_ci
10088c2ecf20Sopenharmony_ci	type = get_type(ch);
10098c2ecf20Sopenharmony_ci	if (type == TEP_EVENT_NONE)
10108c2ecf20Sopenharmony_ci		return type;
10118c2ecf20Sopenharmony_ci
10128c2ecf20Sopenharmony_ci	buf[i++] = ch;
10138c2ecf20Sopenharmony_ci
10148c2ecf20Sopenharmony_ci	switch (type) {
10158c2ecf20Sopenharmony_ci	case TEP_EVENT_NEWLINE:
10168c2ecf20Sopenharmony_ci	case TEP_EVENT_DELIM:
10178c2ecf20Sopenharmony_ci		if (asprintf(tok, "%c", ch) < 0)
10188c2ecf20Sopenharmony_ci			return TEP_EVENT_ERROR;
10198c2ecf20Sopenharmony_ci
10208c2ecf20Sopenharmony_ci		return type;
10218c2ecf20Sopenharmony_ci
10228c2ecf20Sopenharmony_ci	case TEP_EVENT_OP:
10238c2ecf20Sopenharmony_ci		switch (ch) {
10248c2ecf20Sopenharmony_ci		case '-':
10258c2ecf20Sopenharmony_ci			next_ch = peek_char();
10268c2ecf20Sopenharmony_ci			if (next_ch == '>') {
10278c2ecf20Sopenharmony_ci				buf[i++] = __read_char();
10288c2ecf20Sopenharmony_ci				break;
10298c2ecf20Sopenharmony_ci			}
10308c2ecf20Sopenharmony_ci			/* fall through */
10318c2ecf20Sopenharmony_ci		case '+':
10328c2ecf20Sopenharmony_ci		case '|':
10338c2ecf20Sopenharmony_ci		case '&':
10348c2ecf20Sopenharmony_ci		case '>':
10358c2ecf20Sopenharmony_ci		case '<':
10368c2ecf20Sopenharmony_ci			last_ch = ch;
10378c2ecf20Sopenharmony_ci			ch = peek_char();
10388c2ecf20Sopenharmony_ci			if (ch != last_ch)
10398c2ecf20Sopenharmony_ci				goto test_equal;
10408c2ecf20Sopenharmony_ci			buf[i++] = __read_char();
10418c2ecf20Sopenharmony_ci			switch (last_ch) {
10428c2ecf20Sopenharmony_ci			case '>':
10438c2ecf20Sopenharmony_ci			case '<':
10448c2ecf20Sopenharmony_ci				goto test_equal;
10458c2ecf20Sopenharmony_ci			default:
10468c2ecf20Sopenharmony_ci				break;
10478c2ecf20Sopenharmony_ci			}
10488c2ecf20Sopenharmony_ci			break;
10498c2ecf20Sopenharmony_ci		case '!':
10508c2ecf20Sopenharmony_ci		case '=':
10518c2ecf20Sopenharmony_ci			goto test_equal;
10528c2ecf20Sopenharmony_ci		default: /* what should we do instead? */
10538c2ecf20Sopenharmony_ci			break;
10548c2ecf20Sopenharmony_ci		}
10558c2ecf20Sopenharmony_ci		buf[i] = 0;
10568c2ecf20Sopenharmony_ci		*tok = strdup(buf);
10578c2ecf20Sopenharmony_ci		return type;
10588c2ecf20Sopenharmony_ci
10598c2ecf20Sopenharmony_ci test_equal:
10608c2ecf20Sopenharmony_ci		ch = peek_char();
10618c2ecf20Sopenharmony_ci		if (ch == '=')
10628c2ecf20Sopenharmony_ci			buf[i++] = __read_char();
10638c2ecf20Sopenharmony_ci		goto out;
10648c2ecf20Sopenharmony_ci
10658c2ecf20Sopenharmony_ci	case TEP_EVENT_DQUOTE:
10668c2ecf20Sopenharmony_ci	case TEP_EVENT_SQUOTE:
10678c2ecf20Sopenharmony_ci		/* don't keep quotes */
10688c2ecf20Sopenharmony_ci		i--;
10698c2ecf20Sopenharmony_ci		quote_ch = ch;
10708c2ecf20Sopenharmony_ci		last_ch = 0;
10718c2ecf20Sopenharmony_ci concat:
10728c2ecf20Sopenharmony_ci		do {
10738c2ecf20Sopenharmony_ci			if (i == (BUFSIZ - 1)) {
10748c2ecf20Sopenharmony_ci				buf[i] = 0;
10758c2ecf20Sopenharmony_ci				tok_size += BUFSIZ;
10768c2ecf20Sopenharmony_ci
10778c2ecf20Sopenharmony_ci				if (extend_token(tok, buf, tok_size) < 0)
10788c2ecf20Sopenharmony_ci					return TEP_EVENT_NONE;
10798c2ecf20Sopenharmony_ci				i = 0;
10808c2ecf20Sopenharmony_ci			}
10818c2ecf20Sopenharmony_ci			last_ch = ch;
10828c2ecf20Sopenharmony_ci			ch = __read_char();
10838c2ecf20Sopenharmony_ci			buf[i++] = ch;
10848c2ecf20Sopenharmony_ci			/* the '\' '\' will cancel itself */
10858c2ecf20Sopenharmony_ci			if (ch == '\\' && last_ch == '\\')
10868c2ecf20Sopenharmony_ci				last_ch = 0;
10878c2ecf20Sopenharmony_ci		} while (ch != quote_ch || last_ch == '\\');
10888c2ecf20Sopenharmony_ci		/* remove the last quote */
10898c2ecf20Sopenharmony_ci		i--;
10908c2ecf20Sopenharmony_ci
10918c2ecf20Sopenharmony_ci		/*
10928c2ecf20Sopenharmony_ci		 * For strings (double quotes) check the next token.
10938c2ecf20Sopenharmony_ci		 * If it is another string, concatinate the two.
10948c2ecf20Sopenharmony_ci		 */
10958c2ecf20Sopenharmony_ci		if (type == TEP_EVENT_DQUOTE) {
10968c2ecf20Sopenharmony_ci			unsigned long long save_input_buf_ptr = input_buf_ptr;
10978c2ecf20Sopenharmony_ci
10988c2ecf20Sopenharmony_ci			do {
10998c2ecf20Sopenharmony_ci				ch = __read_char();
11008c2ecf20Sopenharmony_ci			} while (isspace(ch));
11018c2ecf20Sopenharmony_ci			if (ch == '"')
11028c2ecf20Sopenharmony_ci				goto concat;
11038c2ecf20Sopenharmony_ci			input_buf_ptr = save_input_buf_ptr;
11048c2ecf20Sopenharmony_ci		}
11058c2ecf20Sopenharmony_ci
11068c2ecf20Sopenharmony_ci		goto out;
11078c2ecf20Sopenharmony_ci
11088c2ecf20Sopenharmony_ci	case TEP_EVENT_ERROR ... TEP_EVENT_SPACE:
11098c2ecf20Sopenharmony_ci	case TEP_EVENT_ITEM:
11108c2ecf20Sopenharmony_ci	default:
11118c2ecf20Sopenharmony_ci		break;
11128c2ecf20Sopenharmony_ci	}
11138c2ecf20Sopenharmony_ci
11148c2ecf20Sopenharmony_ci	while (get_type(peek_char()) == type) {
11158c2ecf20Sopenharmony_ci		if (i == (BUFSIZ - 1)) {
11168c2ecf20Sopenharmony_ci			buf[i] = 0;
11178c2ecf20Sopenharmony_ci			tok_size += BUFSIZ;
11188c2ecf20Sopenharmony_ci
11198c2ecf20Sopenharmony_ci			if (extend_token(tok, buf, tok_size) < 0)
11208c2ecf20Sopenharmony_ci				return TEP_EVENT_NONE;
11218c2ecf20Sopenharmony_ci			i = 0;
11228c2ecf20Sopenharmony_ci		}
11238c2ecf20Sopenharmony_ci		ch = __read_char();
11248c2ecf20Sopenharmony_ci		buf[i++] = ch;
11258c2ecf20Sopenharmony_ci	}
11268c2ecf20Sopenharmony_ci
11278c2ecf20Sopenharmony_ci out:
11288c2ecf20Sopenharmony_ci	buf[i] = 0;
11298c2ecf20Sopenharmony_ci	if (extend_token(tok, buf, tok_size + i + 1) < 0)
11308c2ecf20Sopenharmony_ci		return TEP_EVENT_NONE;
11318c2ecf20Sopenharmony_ci
11328c2ecf20Sopenharmony_ci	if (type == TEP_EVENT_ITEM) {
11338c2ecf20Sopenharmony_ci		/*
11348c2ecf20Sopenharmony_ci		 * Older versions of the kernel has a bug that
11358c2ecf20Sopenharmony_ci		 * creates invalid symbols and will break the mac80211
11368c2ecf20Sopenharmony_ci		 * parsing. This is a work around to that bug.
11378c2ecf20Sopenharmony_ci		 *
11388c2ecf20Sopenharmony_ci		 * See Linux kernel commit:
11398c2ecf20Sopenharmony_ci		 *  811cb50baf63461ce0bdb234927046131fc7fa8b
11408c2ecf20Sopenharmony_ci		 */
11418c2ecf20Sopenharmony_ci		if (strcmp(*tok, "LOCAL_PR_FMT") == 0) {
11428c2ecf20Sopenharmony_ci			free(*tok);
11438c2ecf20Sopenharmony_ci			*tok = NULL;
11448c2ecf20Sopenharmony_ci			return force_token("\"%s\" ", tok);
11458c2ecf20Sopenharmony_ci		} else if (strcmp(*tok, "STA_PR_FMT") == 0) {
11468c2ecf20Sopenharmony_ci			free(*tok);
11478c2ecf20Sopenharmony_ci			*tok = NULL;
11488c2ecf20Sopenharmony_ci			return force_token("\" sta:%pM\" ", tok);
11498c2ecf20Sopenharmony_ci		} else if (strcmp(*tok, "VIF_PR_FMT") == 0) {
11508c2ecf20Sopenharmony_ci			free(*tok);
11518c2ecf20Sopenharmony_ci			*tok = NULL;
11528c2ecf20Sopenharmony_ci			return force_token("\" vif:%p(%d)\" ", tok);
11538c2ecf20Sopenharmony_ci		}
11548c2ecf20Sopenharmony_ci	}
11558c2ecf20Sopenharmony_ci
11568c2ecf20Sopenharmony_ci	return type;
11578c2ecf20Sopenharmony_ci}
11588c2ecf20Sopenharmony_ci
11598c2ecf20Sopenharmony_cistatic enum tep_event_type force_token(const char *str, char **tok)
11608c2ecf20Sopenharmony_ci{
11618c2ecf20Sopenharmony_ci	const char *save_input_buf;
11628c2ecf20Sopenharmony_ci	unsigned long long save_input_buf_ptr;
11638c2ecf20Sopenharmony_ci	unsigned long long save_input_buf_siz;
11648c2ecf20Sopenharmony_ci	enum tep_event_type type;
11658c2ecf20Sopenharmony_ci
11668c2ecf20Sopenharmony_ci	/* save off the current input pointers */
11678c2ecf20Sopenharmony_ci	save_input_buf = input_buf;
11688c2ecf20Sopenharmony_ci	save_input_buf_ptr = input_buf_ptr;
11698c2ecf20Sopenharmony_ci	save_input_buf_siz = input_buf_siz;
11708c2ecf20Sopenharmony_ci
11718c2ecf20Sopenharmony_ci	init_input_buf(str, strlen(str));
11728c2ecf20Sopenharmony_ci
11738c2ecf20Sopenharmony_ci	type = __read_token(tok);
11748c2ecf20Sopenharmony_ci
11758c2ecf20Sopenharmony_ci	/* reset back to original token */
11768c2ecf20Sopenharmony_ci	input_buf = save_input_buf;
11778c2ecf20Sopenharmony_ci	input_buf_ptr = save_input_buf_ptr;
11788c2ecf20Sopenharmony_ci	input_buf_siz = save_input_buf_siz;
11798c2ecf20Sopenharmony_ci
11808c2ecf20Sopenharmony_ci	return type;
11818c2ecf20Sopenharmony_ci}
11828c2ecf20Sopenharmony_ci
11838c2ecf20Sopenharmony_ci/**
11848c2ecf20Sopenharmony_ci * free_token - free a token returned by tep_read_token
11858c2ecf20Sopenharmony_ci * @token: the token to free
11868c2ecf20Sopenharmony_ci */
11878c2ecf20Sopenharmony_ci__hidden void free_token(char *tok)
11888c2ecf20Sopenharmony_ci{
11898c2ecf20Sopenharmony_ci	if (tok)
11908c2ecf20Sopenharmony_ci		free(tok);
11918c2ecf20Sopenharmony_ci}
11928c2ecf20Sopenharmony_ci
11938c2ecf20Sopenharmony_ci/**
11948c2ecf20Sopenharmony_ci * read_token - access to utilities to use the tep parser
11958c2ecf20Sopenharmony_ci * @tok: The token to return
11968c2ecf20Sopenharmony_ci *
11978c2ecf20Sopenharmony_ci * This will parse tokens from the string given by
11988c2ecf20Sopenharmony_ci * tep_init_data().
11998c2ecf20Sopenharmony_ci *
12008c2ecf20Sopenharmony_ci * Returns the token type.
12018c2ecf20Sopenharmony_ci */
12028c2ecf20Sopenharmony_ci__hidden enum tep_event_type read_token(char **tok)
12038c2ecf20Sopenharmony_ci{
12048c2ecf20Sopenharmony_ci	enum tep_event_type type;
12058c2ecf20Sopenharmony_ci
12068c2ecf20Sopenharmony_ci	for (;;) {
12078c2ecf20Sopenharmony_ci		type = __read_token(tok);
12088c2ecf20Sopenharmony_ci		if (type != TEP_EVENT_SPACE)
12098c2ecf20Sopenharmony_ci			return type;
12108c2ecf20Sopenharmony_ci
12118c2ecf20Sopenharmony_ci		free_token(*tok);
12128c2ecf20Sopenharmony_ci	}
12138c2ecf20Sopenharmony_ci
12148c2ecf20Sopenharmony_ci	/* not reached */
12158c2ecf20Sopenharmony_ci	*tok = NULL;
12168c2ecf20Sopenharmony_ci	return TEP_EVENT_NONE;
12178c2ecf20Sopenharmony_ci}
12188c2ecf20Sopenharmony_ci
12198c2ecf20Sopenharmony_ci/* no newline */
12208c2ecf20Sopenharmony_cistatic enum tep_event_type read_token_item(char **tok)
12218c2ecf20Sopenharmony_ci{
12228c2ecf20Sopenharmony_ci	enum tep_event_type type;
12238c2ecf20Sopenharmony_ci
12248c2ecf20Sopenharmony_ci	for (;;) {
12258c2ecf20Sopenharmony_ci		type = __read_token(tok);
12268c2ecf20Sopenharmony_ci		if (type != TEP_EVENT_SPACE && type != TEP_EVENT_NEWLINE)
12278c2ecf20Sopenharmony_ci			return type;
12288c2ecf20Sopenharmony_ci		free_token(*tok);
12298c2ecf20Sopenharmony_ci		*tok = NULL;
12308c2ecf20Sopenharmony_ci	}
12318c2ecf20Sopenharmony_ci
12328c2ecf20Sopenharmony_ci	/* not reached */
12338c2ecf20Sopenharmony_ci	*tok = NULL;
12348c2ecf20Sopenharmony_ci	return TEP_EVENT_NONE;
12358c2ecf20Sopenharmony_ci}
12368c2ecf20Sopenharmony_ci
12378c2ecf20Sopenharmony_cistatic int test_type(enum tep_event_type type, enum tep_event_type expect)
12388c2ecf20Sopenharmony_ci{
12398c2ecf20Sopenharmony_ci	if (type != expect) {
12408c2ecf20Sopenharmony_ci		do_warning("Error: expected type %d but read %d",
12418c2ecf20Sopenharmony_ci		    expect, type);
12428c2ecf20Sopenharmony_ci		return -1;
12438c2ecf20Sopenharmony_ci	}
12448c2ecf20Sopenharmony_ci	return 0;
12458c2ecf20Sopenharmony_ci}
12468c2ecf20Sopenharmony_ci
12478c2ecf20Sopenharmony_cistatic int test_type_token(enum tep_event_type type, const char *token,
12488c2ecf20Sopenharmony_ci		    enum tep_event_type expect, const char *expect_tok)
12498c2ecf20Sopenharmony_ci{
12508c2ecf20Sopenharmony_ci	if (type != expect) {
12518c2ecf20Sopenharmony_ci		do_warning("Error: expected type %d but read %d",
12528c2ecf20Sopenharmony_ci		    expect, type);
12538c2ecf20Sopenharmony_ci		return -1;
12548c2ecf20Sopenharmony_ci	}
12558c2ecf20Sopenharmony_ci
12568c2ecf20Sopenharmony_ci	if (strcmp(token, expect_tok) != 0) {
12578c2ecf20Sopenharmony_ci		do_warning("Error: expected '%s' but read '%s'",
12588c2ecf20Sopenharmony_ci		    expect_tok, token);
12598c2ecf20Sopenharmony_ci		return -1;
12608c2ecf20Sopenharmony_ci	}
12618c2ecf20Sopenharmony_ci	return 0;
12628c2ecf20Sopenharmony_ci}
12638c2ecf20Sopenharmony_ci
12648c2ecf20Sopenharmony_cistatic int __read_expect_type(enum tep_event_type expect, char **tok, int newline_ok)
12658c2ecf20Sopenharmony_ci{
12668c2ecf20Sopenharmony_ci	enum tep_event_type type;
12678c2ecf20Sopenharmony_ci
12688c2ecf20Sopenharmony_ci	if (newline_ok)
12698c2ecf20Sopenharmony_ci		type = read_token(tok);
12708c2ecf20Sopenharmony_ci	else
12718c2ecf20Sopenharmony_ci		type = read_token_item(tok);
12728c2ecf20Sopenharmony_ci	return test_type(type, expect);
12738c2ecf20Sopenharmony_ci}
12748c2ecf20Sopenharmony_ci
12758c2ecf20Sopenharmony_cistatic int read_expect_type(enum tep_event_type expect, char **tok)
12768c2ecf20Sopenharmony_ci{
12778c2ecf20Sopenharmony_ci	return __read_expect_type(expect, tok, 1);
12788c2ecf20Sopenharmony_ci}
12798c2ecf20Sopenharmony_ci
12808c2ecf20Sopenharmony_cistatic int __read_expected(enum tep_event_type expect, const char *str,
12818c2ecf20Sopenharmony_ci			   int newline_ok)
12828c2ecf20Sopenharmony_ci{
12838c2ecf20Sopenharmony_ci	enum tep_event_type type;
12848c2ecf20Sopenharmony_ci	char *token;
12858c2ecf20Sopenharmony_ci	int ret;
12868c2ecf20Sopenharmony_ci
12878c2ecf20Sopenharmony_ci	if (newline_ok)
12888c2ecf20Sopenharmony_ci		type = read_token(&token);
12898c2ecf20Sopenharmony_ci	else
12908c2ecf20Sopenharmony_ci		type = read_token_item(&token);
12918c2ecf20Sopenharmony_ci
12928c2ecf20Sopenharmony_ci	ret = test_type_token(type, token, expect, str);
12938c2ecf20Sopenharmony_ci
12948c2ecf20Sopenharmony_ci	free_token(token);
12958c2ecf20Sopenharmony_ci
12968c2ecf20Sopenharmony_ci	return ret;
12978c2ecf20Sopenharmony_ci}
12988c2ecf20Sopenharmony_ci
12998c2ecf20Sopenharmony_cistatic int read_expected(enum tep_event_type expect, const char *str)
13008c2ecf20Sopenharmony_ci{
13018c2ecf20Sopenharmony_ci	return __read_expected(expect, str, 1);
13028c2ecf20Sopenharmony_ci}
13038c2ecf20Sopenharmony_ci
13048c2ecf20Sopenharmony_cistatic int read_expected_item(enum tep_event_type expect, const char *str)
13058c2ecf20Sopenharmony_ci{
13068c2ecf20Sopenharmony_ci	return __read_expected(expect, str, 0);
13078c2ecf20Sopenharmony_ci}
13088c2ecf20Sopenharmony_ci
13098c2ecf20Sopenharmony_cistatic char *event_read_name(void)
13108c2ecf20Sopenharmony_ci{
13118c2ecf20Sopenharmony_ci	char *token;
13128c2ecf20Sopenharmony_ci
13138c2ecf20Sopenharmony_ci	if (read_expected(TEP_EVENT_ITEM, "name") < 0)
13148c2ecf20Sopenharmony_ci		return NULL;
13158c2ecf20Sopenharmony_ci
13168c2ecf20Sopenharmony_ci	if (read_expected(TEP_EVENT_OP, ":") < 0)
13178c2ecf20Sopenharmony_ci		return NULL;
13188c2ecf20Sopenharmony_ci
13198c2ecf20Sopenharmony_ci	if (read_expect_type(TEP_EVENT_ITEM, &token) < 0)
13208c2ecf20Sopenharmony_ci		goto fail;
13218c2ecf20Sopenharmony_ci
13228c2ecf20Sopenharmony_ci	return token;
13238c2ecf20Sopenharmony_ci
13248c2ecf20Sopenharmony_ci fail:
13258c2ecf20Sopenharmony_ci	free_token(token);
13268c2ecf20Sopenharmony_ci	return NULL;
13278c2ecf20Sopenharmony_ci}
13288c2ecf20Sopenharmony_ci
13298c2ecf20Sopenharmony_cistatic int event_read_id(void)
13308c2ecf20Sopenharmony_ci{
13318c2ecf20Sopenharmony_ci	char *token;
13328c2ecf20Sopenharmony_ci	int id;
13338c2ecf20Sopenharmony_ci
13348c2ecf20Sopenharmony_ci	if (read_expected_item(TEP_EVENT_ITEM, "ID") < 0)
13358c2ecf20Sopenharmony_ci		return -1;
13368c2ecf20Sopenharmony_ci
13378c2ecf20Sopenharmony_ci	if (read_expected(TEP_EVENT_OP, ":") < 0)
13388c2ecf20Sopenharmony_ci		return -1;
13398c2ecf20Sopenharmony_ci
13408c2ecf20Sopenharmony_ci	if (read_expect_type(TEP_EVENT_ITEM, &token) < 0)
13418c2ecf20Sopenharmony_ci		goto fail;
13428c2ecf20Sopenharmony_ci
13438c2ecf20Sopenharmony_ci	id = strtoul(token, NULL, 0);
13448c2ecf20Sopenharmony_ci	free_token(token);
13458c2ecf20Sopenharmony_ci	return id;
13468c2ecf20Sopenharmony_ci
13478c2ecf20Sopenharmony_ci fail:
13488c2ecf20Sopenharmony_ci	free_token(token);
13498c2ecf20Sopenharmony_ci	return -1;
13508c2ecf20Sopenharmony_ci}
13518c2ecf20Sopenharmony_ci
13528c2ecf20Sopenharmony_cistatic int field_is_string(struct tep_format_field *field)
13538c2ecf20Sopenharmony_ci{
13548c2ecf20Sopenharmony_ci	if ((field->flags & TEP_FIELD_IS_ARRAY) &&
13558c2ecf20Sopenharmony_ci	    (strstr(field->type, "char") || strstr(field->type, "u8") ||
13568c2ecf20Sopenharmony_ci	     strstr(field->type, "s8")))
13578c2ecf20Sopenharmony_ci		return 1;
13588c2ecf20Sopenharmony_ci
13598c2ecf20Sopenharmony_ci	return 0;
13608c2ecf20Sopenharmony_ci}
13618c2ecf20Sopenharmony_ci
13628c2ecf20Sopenharmony_cistatic int field_is_dynamic(struct tep_format_field *field)
13638c2ecf20Sopenharmony_ci{
13648c2ecf20Sopenharmony_ci	if (strncmp(field->type, "__data_loc", 10) == 0)
13658c2ecf20Sopenharmony_ci		return 1;
13668c2ecf20Sopenharmony_ci
13678c2ecf20Sopenharmony_ci	return 0;
13688c2ecf20Sopenharmony_ci}
13698c2ecf20Sopenharmony_ci
13708c2ecf20Sopenharmony_cistatic int field_is_long(struct tep_format_field *field)
13718c2ecf20Sopenharmony_ci{
13728c2ecf20Sopenharmony_ci	/* includes long long */
13738c2ecf20Sopenharmony_ci	if (strstr(field->type, "long"))
13748c2ecf20Sopenharmony_ci		return 1;
13758c2ecf20Sopenharmony_ci
13768c2ecf20Sopenharmony_ci	return 0;
13778c2ecf20Sopenharmony_ci}
13788c2ecf20Sopenharmony_ci
13798c2ecf20Sopenharmony_cistatic unsigned int type_size(const char *name)
13808c2ecf20Sopenharmony_ci{
13818c2ecf20Sopenharmony_ci	/* This covers all TEP_FIELD_IS_STRING types. */
13828c2ecf20Sopenharmony_ci	static struct {
13838c2ecf20Sopenharmony_ci		const char *type;
13848c2ecf20Sopenharmony_ci		unsigned int size;
13858c2ecf20Sopenharmony_ci	} table[] = {
13868c2ecf20Sopenharmony_ci		{ "u8",   1 },
13878c2ecf20Sopenharmony_ci		{ "u16",  2 },
13888c2ecf20Sopenharmony_ci		{ "u32",  4 },
13898c2ecf20Sopenharmony_ci		{ "u64",  8 },
13908c2ecf20Sopenharmony_ci		{ "s8",   1 },
13918c2ecf20Sopenharmony_ci		{ "s16",  2 },
13928c2ecf20Sopenharmony_ci		{ "s32",  4 },
13938c2ecf20Sopenharmony_ci		{ "s64",  8 },
13948c2ecf20Sopenharmony_ci		{ "char", 1 },
13958c2ecf20Sopenharmony_ci		{ },
13968c2ecf20Sopenharmony_ci	};
13978c2ecf20Sopenharmony_ci	int i;
13988c2ecf20Sopenharmony_ci
13998c2ecf20Sopenharmony_ci	for (i = 0; table[i].type; i++) {
14008c2ecf20Sopenharmony_ci		if (!strcmp(table[i].type, name))
14018c2ecf20Sopenharmony_ci			return table[i].size;
14028c2ecf20Sopenharmony_ci	}
14038c2ecf20Sopenharmony_ci
14048c2ecf20Sopenharmony_ci	return 0;
14058c2ecf20Sopenharmony_ci}
14068c2ecf20Sopenharmony_ci
14078c2ecf20Sopenharmony_cistatic int append(char **buf, const char *delim, const char *str)
14088c2ecf20Sopenharmony_ci{
14098c2ecf20Sopenharmony_ci	char *new_buf;
14108c2ecf20Sopenharmony_ci
14118c2ecf20Sopenharmony_ci	new_buf = realloc(*buf, strlen(*buf) + strlen(delim) + strlen(str) + 1);
14128c2ecf20Sopenharmony_ci	if (!new_buf)
14138c2ecf20Sopenharmony_ci		return -1;
14148c2ecf20Sopenharmony_ci	strcat(new_buf, delim);
14158c2ecf20Sopenharmony_ci	strcat(new_buf, str);
14168c2ecf20Sopenharmony_ci	*buf = new_buf;
14178c2ecf20Sopenharmony_ci	return 0;
14188c2ecf20Sopenharmony_ci}
14198c2ecf20Sopenharmony_ci
14208c2ecf20Sopenharmony_cistatic int event_read_fields(struct tep_event *event, struct tep_format_field **fields)
14218c2ecf20Sopenharmony_ci{
14228c2ecf20Sopenharmony_ci	struct tep_format_field *field = NULL;
14238c2ecf20Sopenharmony_ci	enum tep_event_type type;
14248c2ecf20Sopenharmony_ci	char *token;
14258c2ecf20Sopenharmony_ci	char *last_token;
14268c2ecf20Sopenharmony_ci	char *delim = " ";
14278c2ecf20Sopenharmony_ci	int count = 0;
14288c2ecf20Sopenharmony_ci	int ret;
14298c2ecf20Sopenharmony_ci
14308c2ecf20Sopenharmony_ci	do {
14318c2ecf20Sopenharmony_ci		unsigned int size_dynamic = 0;
14328c2ecf20Sopenharmony_ci
14338c2ecf20Sopenharmony_ci		type = read_token(&token);
14348c2ecf20Sopenharmony_ci		if (type == TEP_EVENT_NEWLINE) {
14358c2ecf20Sopenharmony_ci			free_token(token);
14368c2ecf20Sopenharmony_ci			return count;
14378c2ecf20Sopenharmony_ci		}
14388c2ecf20Sopenharmony_ci
14398c2ecf20Sopenharmony_ci		count++;
14408c2ecf20Sopenharmony_ci
14418c2ecf20Sopenharmony_ci		if (test_type_token(type, token, TEP_EVENT_ITEM, "field"))
14428c2ecf20Sopenharmony_ci			goto fail;
14438c2ecf20Sopenharmony_ci		free_token(token);
14448c2ecf20Sopenharmony_ci
14458c2ecf20Sopenharmony_ci		type = read_token(&token);
14468c2ecf20Sopenharmony_ci		/*
14478c2ecf20Sopenharmony_ci		 * The ftrace fields may still use the "special" name.
14488c2ecf20Sopenharmony_ci		 * Just ignore it.
14498c2ecf20Sopenharmony_ci		 */
14508c2ecf20Sopenharmony_ci		if (event->flags & TEP_EVENT_FL_ISFTRACE &&
14518c2ecf20Sopenharmony_ci		    type == TEP_EVENT_ITEM && strcmp(token, "special") == 0) {
14528c2ecf20Sopenharmony_ci			free_token(token);
14538c2ecf20Sopenharmony_ci			type = read_token(&token);
14548c2ecf20Sopenharmony_ci		}
14558c2ecf20Sopenharmony_ci
14568c2ecf20Sopenharmony_ci		if (test_type_token(type, token, TEP_EVENT_OP, ":") < 0)
14578c2ecf20Sopenharmony_ci			goto fail;
14588c2ecf20Sopenharmony_ci
14598c2ecf20Sopenharmony_ci		free_token(token);
14608c2ecf20Sopenharmony_ci		if (read_expect_type(TEP_EVENT_ITEM, &token) < 0)
14618c2ecf20Sopenharmony_ci			goto fail;
14628c2ecf20Sopenharmony_ci
14638c2ecf20Sopenharmony_ci		last_token = token;
14648c2ecf20Sopenharmony_ci
14658c2ecf20Sopenharmony_ci		field = calloc(1, sizeof(*field));
14668c2ecf20Sopenharmony_ci		if (!field)
14678c2ecf20Sopenharmony_ci			goto fail;
14688c2ecf20Sopenharmony_ci
14698c2ecf20Sopenharmony_ci		field->event = event;
14708c2ecf20Sopenharmony_ci
14718c2ecf20Sopenharmony_ci		/* read the rest of the type */
14728c2ecf20Sopenharmony_ci		for (;;) {
14738c2ecf20Sopenharmony_ci			type = read_token(&token);
14748c2ecf20Sopenharmony_ci			if (type == TEP_EVENT_ITEM ||
14758c2ecf20Sopenharmony_ci			    (type == TEP_EVENT_OP && strcmp(token, "*") == 0) ||
14768c2ecf20Sopenharmony_ci			    /*
14778c2ecf20Sopenharmony_ci			     * Some of the ftrace fields are broken and have
14788c2ecf20Sopenharmony_ci			     * an illegal "." in them.
14798c2ecf20Sopenharmony_ci			     */
14808c2ecf20Sopenharmony_ci			    (event->flags & TEP_EVENT_FL_ISFTRACE &&
14818c2ecf20Sopenharmony_ci			     type == TEP_EVENT_OP && strcmp(token, ".") == 0)) {
14828c2ecf20Sopenharmony_ci
14838c2ecf20Sopenharmony_ci				if (strcmp(token, "*") == 0)
14848c2ecf20Sopenharmony_ci					field->flags |= TEP_FIELD_IS_POINTER;
14858c2ecf20Sopenharmony_ci
14868c2ecf20Sopenharmony_ci				if (field->type) {
14878c2ecf20Sopenharmony_ci					ret = append(&field->type, delim, last_token);
14888c2ecf20Sopenharmony_ci					free(last_token);
14898c2ecf20Sopenharmony_ci					if (ret < 0)
14908c2ecf20Sopenharmony_ci						goto fail;
14918c2ecf20Sopenharmony_ci				} else
14928c2ecf20Sopenharmony_ci					field->type = last_token;
14938c2ecf20Sopenharmony_ci				last_token = token;
14948c2ecf20Sopenharmony_ci				delim = " ";
14958c2ecf20Sopenharmony_ci				continue;
14968c2ecf20Sopenharmony_ci			}
14978c2ecf20Sopenharmony_ci
14988c2ecf20Sopenharmony_ci			/* Handle __attribute__((user)) */
14998c2ecf20Sopenharmony_ci			if ((type == TEP_EVENT_DELIM) &&
15008c2ecf20Sopenharmony_ci			    strcmp("__attribute__", last_token) == 0 &&
15018c2ecf20Sopenharmony_ci			    token[0] == '(') {
15028c2ecf20Sopenharmony_ci				int depth = 1;
15038c2ecf20Sopenharmony_ci				int ret;
15048c2ecf20Sopenharmony_ci
15058c2ecf20Sopenharmony_ci				ret = append(&field->type, " ", last_token);
15068c2ecf20Sopenharmony_ci				ret |= append(&field->type, "", "(");
15078c2ecf20Sopenharmony_ci				if (ret < 0)
15088c2ecf20Sopenharmony_ci					goto fail;
15098c2ecf20Sopenharmony_ci
15108c2ecf20Sopenharmony_ci				delim = " ";
15118c2ecf20Sopenharmony_ci				while ((type = read_token(&token)) != TEP_EVENT_NONE) {
15128c2ecf20Sopenharmony_ci					if (type == TEP_EVENT_DELIM) {
15138c2ecf20Sopenharmony_ci						if (token[0] == '(')
15148c2ecf20Sopenharmony_ci							depth++;
15158c2ecf20Sopenharmony_ci						else if (token[0] == ')')
15168c2ecf20Sopenharmony_ci							depth--;
15178c2ecf20Sopenharmony_ci						if (!depth)
15188c2ecf20Sopenharmony_ci							break;
15198c2ecf20Sopenharmony_ci						ret = append(&field->type, "", token);
15208c2ecf20Sopenharmony_ci						delim = "";
15218c2ecf20Sopenharmony_ci					} else {
15228c2ecf20Sopenharmony_ci						ret = append(&field->type, delim, token);
15238c2ecf20Sopenharmony_ci						delim = " ";
15248c2ecf20Sopenharmony_ci					}
15258c2ecf20Sopenharmony_ci					if (ret < 0)
15268c2ecf20Sopenharmony_ci						goto fail;
15278c2ecf20Sopenharmony_ci					free(last_token);
15288c2ecf20Sopenharmony_ci					last_token = token;
15298c2ecf20Sopenharmony_ci				}
15308c2ecf20Sopenharmony_ci				continue;
15318c2ecf20Sopenharmony_ci			}
15328c2ecf20Sopenharmony_ci			break;
15338c2ecf20Sopenharmony_ci		}
15348c2ecf20Sopenharmony_ci
15358c2ecf20Sopenharmony_ci		if (!field->type) {
15368c2ecf20Sopenharmony_ci			do_warning_event(event, "%s: no type found", __func__);
15378c2ecf20Sopenharmony_ci			goto fail;
15388c2ecf20Sopenharmony_ci		}
15398c2ecf20Sopenharmony_ci		field->name = field->alias = last_token;
15408c2ecf20Sopenharmony_ci
15418c2ecf20Sopenharmony_ci		if (test_type(type, TEP_EVENT_OP))
15428c2ecf20Sopenharmony_ci			goto fail;
15438c2ecf20Sopenharmony_ci
15448c2ecf20Sopenharmony_ci		if (strcmp(token, "[") == 0) {
15458c2ecf20Sopenharmony_ci			enum tep_event_type last_type = type;
15468c2ecf20Sopenharmony_ci			char *brackets = token;
15478c2ecf20Sopenharmony_ci
15488c2ecf20Sopenharmony_ci			field->flags |= TEP_FIELD_IS_ARRAY;
15498c2ecf20Sopenharmony_ci
15508c2ecf20Sopenharmony_ci			type = read_token(&token);
15518c2ecf20Sopenharmony_ci
15528c2ecf20Sopenharmony_ci			if (type == TEP_EVENT_ITEM)
15538c2ecf20Sopenharmony_ci				field->arraylen = strtoul(token, NULL, 0);
15548c2ecf20Sopenharmony_ci			else
15558c2ecf20Sopenharmony_ci				field->arraylen = 0;
15568c2ecf20Sopenharmony_ci
15578c2ecf20Sopenharmony_ci		        while (strcmp(token, "]") != 0) {
15588c2ecf20Sopenharmony_ci				const char *delim;
15598c2ecf20Sopenharmony_ci
15608c2ecf20Sopenharmony_ci				if (last_type == TEP_EVENT_ITEM &&
15618c2ecf20Sopenharmony_ci				    type == TEP_EVENT_ITEM)
15628c2ecf20Sopenharmony_ci					delim = " ";
15638c2ecf20Sopenharmony_ci				else
15648c2ecf20Sopenharmony_ci					delim = "";
15658c2ecf20Sopenharmony_ci
15668c2ecf20Sopenharmony_ci				last_type = type;
15678c2ecf20Sopenharmony_ci
15688c2ecf20Sopenharmony_ci				ret = append(&brackets, delim, token);
15698c2ecf20Sopenharmony_ci				if (ret < 0) {
15708c2ecf20Sopenharmony_ci					free(brackets);
15718c2ecf20Sopenharmony_ci					goto fail;
15728c2ecf20Sopenharmony_ci				}
15738c2ecf20Sopenharmony_ci				/* We only care about the last token */
15748c2ecf20Sopenharmony_ci				field->arraylen = strtoul(token, NULL, 0);
15758c2ecf20Sopenharmony_ci				free_token(token);
15768c2ecf20Sopenharmony_ci				type = read_token(&token);
15778c2ecf20Sopenharmony_ci				if (type == TEP_EVENT_NONE) {
15788c2ecf20Sopenharmony_ci					free(brackets);
15798c2ecf20Sopenharmony_ci					do_warning_event(event, "failed to find token");
15808c2ecf20Sopenharmony_ci					goto fail;
15818c2ecf20Sopenharmony_ci				}
15828c2ecf20Sopenharmony_ci			}
15838c2ecf20Sopenharmony_ci
15848c2ecf20Sopenharmony_ci			free_token(token);
15858c2ecf20Sopenharmony_ci
15868c2ecf20Sopenharmony_ci			ret = append(&brackets, "", "]");
15878c2ecf20Sopenharmony_ci			if (ret < 0) {
15888c2ecf20Sopenharmony_ci				free(brackets);
15898c2ecf20Sopenharmony_ci				goto fail;
15908c2ecf20Sopenharmony_ci			}
15918c2ecf20Sopenharmony_ci
15928c2ecf20Sopenharmony_ci			/* add brackets to type */
15938c2ecf20Sopenharmony_ci
15948c2ecf20Sopenharmony_ci			type = read_token(&token);
15958c2ecf20Sopenharmony_ci			/*
15968c2ecf20Sopenharmony_ci			 * If the next token is not an OP, then it is of
15978c2ecf20Sopenharmony_ci			 * the format: type [] item;
15988c2ecf20Sopenharmony_ci			 */
15998c2ecf20Sopenharmony_ci			if (type == TEP_EVENT_ITEM) {
16008c2ecf20Sopenharmony_ci				ret = append(&field->type, " ", field->name);
16018c2ecf20Sopenharmony_ci				if (ret < 0) {
16028c2ecf20Sopenharmony_ci					free(brackets);
16038c2ecf20Sopenharmony_ci					goto fail;
16048c2ecf20Sopenharmony_ci				}
16058c2ecf20Sopenharmony_ci				ret = append(&field->type, "", brackets);
16068c2ecf20Sopenharmony_ci
16078c2ecf20Sopenharmony_ci				size_dynamic = type_size(field->name);
16088c2ecf20Sopenharmony_ci				free_token(field->name);
16098c2ecf20Sopenharmony_ci				field->name = field->alias = token;
16108c2ecf20Sopenharmony_ci				type = read_token(&token);
16118c2ecf20Sopenharmony_ci			} else {
16128c2ecf20Sopenharmony_ci				ret = append(&field->type, "", brackets);
16138c2ecf20Sopenharmony_ci				if (ret < 0) {
16148c2ecf20Sopenharmony_ci					free(brackets);
16158c2ecf20Sopenharmony_ci					goto fail;
16168c2ecf20Sopenharmony_ci				}
16178c2ecf20Sopenharmony_ci			}
16188c2ecf20Sopenharmony_ci			free(brackets);
16198c2ecf20Sopenharmony_ci		}
16208c2ecf20Sopenharmony_ci
16218c2ecf20Sopenharmony_ci		if (field_is_string(field))
16228c2ecf20Sopenharmony_ci			field->flags |= TEP_FIELD_IS_STRING;
16238c2ecf20Sopenharmony_ci		if (field_is_dynamic(field))
16248c2ecf20Sopenharmony_ci			field->flags |= TEP_FIELD_IS_DYNAMIC;
16258c2ecf20Sopenharmony_ci		if (field_is_long(field))
16268c2ecf20Sopenharmony_ci			field->flags |= TEP_FIELD_IS_LONG;
16278c2ecf20Sopenharmony_ci
16288c2ecf20Sopenharmony_ci		if (test_type_token(type, token,  TEP_EVENT_OP, ";"))
16298c2ecf20Sopenharmony_ci			goto fail;
16308c2ecf20Sopenharmony_ci		free_token(token);
16318c2ecf20Sopenharmony_ci
16328c2ecf20Sopenharmony_ci		if (read_expected(TEP_EVENT_ITEM, "offset") < 0)
16338c2ecf20Sopenharmony_ci			goto fail_expect;
16348c2ecf20Sopenharmony_ci
16358c2ecf20Sopenharmony_ci		if (read_expected(TEP_EVENT_OP, ":") < 0)
16368c2ecf20Sopenharmony_ci			goto fail_expect;
16378c2ecf20Sopenharmony_ci
16388c2ecf20Sopenharmony_ci		if (read_expect_type(TEP_EVENT_ITEM, &token))
16398c2ecf20Sopenharmony_ci			goto fail;
16408c2ecf20Sopenharmony_ci		field->offset = strtoul(token, NULL, 0);
16418c2ecf20Sopenharmony_ci		free_token(token);
16428c2ecf20Sopenharmony_ci
16438c2ecf20Sopenharmony_ci		if (read_expected(TEP_EVENT_OP, ";") < 0)
16448c2ecf20Sopenharmony_ci			goto fail_expect;
16458c2ecf20Sopenharmony_ci
16468c2ecf20Sopenharmony_ci		if (read_expected(TEP_EVENT_ITEM, "size") < 0)
16478c2ecf20Sopenharmony_ci			goto fail_expect;
16488c2ecf20Sopenharmony_ci
16498c2ecf20Sopenharmony_ci		if (read_expected(TEP_EVENT_OP, ":") < 0)
16508c2ecf20Sopenharmony_ci			goto fail_expect;
16518c2ecf20Sopenharmony_ci
16528c2ecf20Sopenharmony_ci		if (read_expect_type(TEP_EVENT_ITEM, &token))
16538c2ecf20Sopenharmony_ci			goto fail;
16548c2ecf20Sopenharmony_ci		field->size = strtoul(token, NULL, 0);
16558c2ecf20Sopenharmony_ci		free_token(token);
16568c2ecf20Sopenharmony_ci
16578c2ecf20Sopenharmony_ci		if (read_expected(TEP_EVENT_OP, ";") < 0)
16588c2ecf20Sopenharmony_ci			goto fail_expect;
16598c2ecf20Sopenharmony_ci
16608c2ecf20Sopenharmony_ci		type = read_token(&token);
16618c2ecf20Sopenharmony_ci		if (type != TEP_EVENT_NEWLINE) {
16628c2ecf20Sopenharmony_ci			/* newer versions of the kernel have a "signed" type */
16638c2ecf20Sopenharmony_ci			if (test_type_token(type, token, TEP_EVENT_ITEM, "signed"))
16648c2ecf20Sopenharmony_ci				goto fail;
16658c2ecf20Sopenharmony_ci
16668c2ecf20Sopenharmony_ci			free_token(token);
16678c2ecf20Sopenharmony_ci
16688c2ecf20Sopenharmony_ci			if (read_expected(TEP_EVENT_OP, ":") < 0)
16698c2ecf20Sopenharmony_ci				goto fail_expect;
16708c2ecf20Sopenharmony_ci
16718c2ecf20Sopenharmony_ci			if (read_expect_type(TEP_EVENT_ITEM, &token))
16728c2ecf20Sopenharmony_ci				goto fail;
16738c2ecf20Sopenharmony_ci
16748c2ecf20Sopenharmony_ci			if (strtoul(token, NULL, 0))
16758c2ecf20Sopenharmony_ci				field->flags |= TEP_FIELD_IS_SIGNED;
16768c2ecf20Sopenharmony_ci
16778c2ecf20Sopenharmony_ci			free_token(token);
16788c2ecf20Sopenharmony_ci			if (read_expected(TEP_EVENT_OP, ";") < 0)
16798c2ecf20Sopenharmony_ci				goto fail_expect;
16808c2ecf20Sopenharmony_ci
16818c2ecf20Sopenharmony_ci			if (read_expect_type(TEP_EVENT_NEWLINE, &token))
16828c2ecf20Sopenharmony_ci				goto fail;
16838c2ecf20Sopenharmony_ci		}
16848c2ecf20Sopenharmony_ci
16858c2ecf20Sopenharmony_ci		free_token(token);
16868c2ecf20Sopenharmony_ci
16878c2ecf20Sopenharmony_ci		if (field->flags & TEP_FIELD_IS_ARRAY) {
16888c2ecf20Sopenharmony_ci			if (field->arraylen)
16898c2ecf20Sopenharmony_ci				field->elementsize = field->size / field->arraylen;
16908c2ecf20Sopenharmony_ci			else if (field->flags & TEP_FIELD_IS_DYNAMIC)
16918c2ecf20Sopenharmony_ci				field->elementsize = size_dynamic;
16928c2ecf20Sopenharmony_ci			else if (field->flags & TEP_FIELD_IS_STRING)
16938c2ecf20Sopenharmony_ci				field->elementsize = 1;
16948c2ecf20Sopenharmony_ci			else if (field->flags & TEP_FIELD_IS_LONG)
16958c2ecf20Sopenharmony_ci				field->elementsize = event->tep ?
16968c2ecf20Sopenharmony_ci						     event->tep->long_size :
16978c2ecf20Sopenharmony_ci						     sizeof(long);
16988c2ecf20Sopenharmony_ci		} else
16998c2ecf20Sopenharmony_ci			field->elementsize = field->size;
17008c2ecf20Sopenharmony_ci
17018c2ecf20Sopenharmony_ci		*fields = field;
17028c2ecf20Sopenharmony_ci		fields = &field->next;
17038c2ecf20Sopenharmony_ci
17048c2ecf20Sopenharmony_ci	} while (1);
17058c2ecf20Sopenharmony_ci
17068c2ecf20Sopenharmony_ci	return 0;
17078c2ecf20Sopenharmony_ci
17088c2ecf20Sopenharmony_cifail:
17098c2ecf20Sopenharmony_ci	free_token(token);
17108c2ecf20Sopenharmony_cifail_expect:
17118c2ecf20Sopenharmony_ci	if (field) {
17128c2ecf20Sopenharmony_ci		free(field->type);
17138c2ecf20Sopenharmony_ci		free(field->name);
17148c2ecf20Sopenharmony_ci		free(field);
17158c2ecf20Sopenharmony_ci	}
17168c2ecf20Sopenharmony_ci	return -1;
17178c2ecf20Sopenharmony_ci}
17188c2ecf20Sopenharmony_ci
17198c2ecf20Sopenharmony_cistatic int event_read_format(struct tep_event *event)
17208c2ecf20Sopenharmony_ci{
17218c2ecf20Sopenharmony_ci	char *token;
17228c2ecf20Sopenharmony_ci	int ret;
17238c2ecf20Sopenharmony_ci
17248c2ecf20Sopenharmony_ci	if (read_expected_item(TEP_EVENT_ITEM, "format") < 0)
17258c2ecf20Sopenharmony_ci		return -1;
17268c2ecf20Sopenharmony_ci
17278c2ecf20Sopenharmony_ci	if (read_expected(TEP_EVENT_OP, ":") < 0)
17288c2ecf20Sopenharmony_ci		return -1;
17298c2ecf20Sopenharmony_ci
17308c2ecf20Sopenharmony_ci	if (read_expect_type(TEP_EVENT_NEWLINE, &token))
17318c2ecf20Sopenharmony_ci		goto fail;
17328c2ecf20Sopenharmony_ci	free_token(token);
17338c2ecf20Sopenharmony_ci
17348c2ecf20Sopenharmony_ci	ret = event_read_fields(event, &event->format.common_fields);
17358c2ecf20Sopenharmony_ci	if (ret < 0)
17368c2ecf20Sopenharmony_ci		return ret;
17378c2ecf20Sopenharmony_ci	event->format.nr_common = ret;
17388c2ecf20Sopenharmony_ci
17398c2ecf20Sopenharmony_ci	ret = event_read_fields(event, &event->format.fields);
17408c2ecf20Sopenharmony_ci	if (ret < 0)
17418c2ecf20Sopenharmony_ci		return ret;
17428c2ecf20Sopenharmony_ci	event->format.nr_fields = ret;
17438c2ecf20Sopenharmony_ci
17448c2ecf20Sopenharmony_ci	return 0;
17458c2ecf20Sopenharmony_ci
17468c2ecf20Sopenharmony_ci fail:
17478c2ecf20Sopenharmony_ci	free_token(token);
17488c2ecf20Sopenharmony_ci	return -1;
17498c2ecf20Sopenharmony_ci}
17508c2ecf20Sopenharmony_ci
17518c2ecf20Sopenharmony_cistatic enum tep_event_type
17528c2ecf20Sopenharmony_ciprocess_arg_token(struct tep_event *event, struct tep_print_arg *arg,
17538c2ecf20Sopenharmony_ci		  char **tok, enum tep_event_type type);
17548c2ecf20Sopenharmony_ci
17558c2ecf20Sopenharmony_cistatic enum tep_event_type
17568c2ecf20Sopenharmony_ciprocess_arg(struct tep_event *event, struct tep_print_arg *arg, char **tok)
17578c2ecf20Sopenharmony_ci{
17588c2ecf20Sopenharmony_ci	enum tep_event_type type;
17598c2ecf20Sopenharmony_ci	char *token;
17608c2ecf20Sopenharmony_ci
17618c2ecf20Sopenharmony_ci	type = read_token(&token);
17628c2ecf20Sopenharmony_ci	*tok = token;
17638c2ecf20Sopenharmony_ci
17648c2ecf20Sopenharmony_ci	return process_arg_token(event, arg, tok, type);
17658c2ecf20Sopenharmony_ci}
17668c2ecf20Sopenharmony_ci
17678c2ecf20Sopenharmony_cistatic enum tep_event_type
17688c2ecf20Sopenharmony_ciprocess_op(struct tep_event *event, struct tep_print_arg *arg, char **tok);
17698c2ecf20Sopenharmony_ci
17708c2ecf20Sopenharmony_ci/*
17718c2ecf20Sopenharmony_ci * For __print_symbolic() and __print_flags, we need to completely
17728c2ecf20Sopenharmony_ci * evaluate the first argument, which defines what to print next.
17738c2ecf20Sopenharmony_ci */
17748c2ecf20Sopenharmony_cistatic enum tep_event_type
17758c2ecf20Sopenharmony_ciprocess_field_arg(struct tep_event *event, struct tep_print_arg *arg, char **tok)
17768c2ecf20Sopenharmony_ci{
17778c2ecf20Sopenharmony_ci	enum tep_event_type type;
17788c2ecf20Sopenharmony_ci
17798c2ecf20Sopenharmony_ci	type = process_arg(event, arg, tok);
17808c2ecf20Sopenharmony_ci
17818c2ecf20Sopenharmony_ci	while (type == TEP_EVENT_OP) {
17828c2ecf20Sopenharmony_ci		type = process_op(event, arg, tok);
17838c2ecf20Sopenharmony_ci	}
17848c2ecf20Sopenharmony_ci
17858c2ecf20Sopenharmony_ci	return type;
17868c2ecf20Sopenharmony_ci}
17878c2ecf20Sopenharmony_ci
17888c2ecf20Sopenharmony_cistatic enum tep_event_type
17898c2ecf20Sopenharmony_ciprocess_cond(struct tep_event *event, struct tep_print_arg *top, char **tok)
17908c2ecf20Sopenharmony_ci{
17918c2ecf20Sopenharmony_ci	struct tep_print_arg *arg, *left, *right;
17928c2ecf20Sopenharmony_ci	enum tep_event_type type;
17938c2ecf20Sopenharmony_ci	char *token = NULL;
17948c2ecf20Sopenharmony_ci
17958c2ecf20Sopenharmony_ci	arg = alloc_arg();
17968c2ecf20Sopenharmony_ci	left = alloc_arg();
17978c2ecf20Sopenharmony_ci	right = alloc_arg();
17988c2ecf20Sopenharmony_ci
17998c2ecf20Sopenharmony_ci	if (!arg || !left || !right) {
18008c2ecf20Sopenharmony_ci		do_warning_event(event, "%s: not enough memory!", __func__);
18018c2ecf20Sopenharmony_ci		/* arg will be freed at out_free */
18028c2ecf20Sopenharmony_ci		free_arg(left);
18038c2ecf20Sopenharmony_ci		free_arg(right);
18048c2ecf20Sopenharmony_ci		goto out_free;
18058c2ecf20Sopenharmony_ci	}
18068c2ecf20Sopenharmony_ci
18078c2ecf20Sopenharmony_ci	arg->type = TEP_PRINT_OP;
18088c2ecf20Sopenharmony_ci	arg->op.left = left;
18098c2ecf20Sopenharmony_ci	arg->op.right = right;
18108c2ecf20Sopenharmony_ci
18118c2ecf20Sopenharmony_ci	*tok = NULL;
18128c2ecf20Sopenharmony_ci	type = process_arg(event, left, &token);
18138c2ecf20Sopenharmony_ci
18148c2ecf20Sopenharmony_ci again:
18158c2ecf20Sopenharmony_ci	if (type == TEP_EVENT_ERROR)
18168c2ecf20Sopenharmony_ci		goto out_free;
18178c2ecf20Sopenharmony_ci
18188c2ecf20Sopenharmony_ci	/* Handle other operations in the arguments */
18198c2ecf20Sopenharmony_ci	if (type == TEP_EVENT_OP && strcmp(token, ":") != 0) {
18208c2ecf20Sopenharmony_ci		type = process_op(event, left, &token);
18218c2ecf20Sopenharmony_ci		goto again;
18228c2ecf20Sopenharmony_ci	}
18238c2ecf20Sopenharmony_ci
18248c2ecf20Sopenharmony_ci	if (test_type_token(type, token, TEP_EVENT_OP, ":"))
18258c2ecf20Sopenharmony_ci		goto out_free;
18268c2ecf20Sopenharmony_ci
18278c2ecf20Sopenharmony_ci	arg->op.op = token;
18288c2ecf20Sopenharmony_ci
18298c2ecf20Sopenharmony_ci	type = process_arg(event, right, &token);
18308c2ecf20Sopenharmony_ci
18318c2ecf20Sopenharmony_ci	top->op.right = arg;
18328c2ecf20Sopenharmony_ci
18338c2ecf20Sopenharmony_ci	*tok = token;
18348c2ecf20Sopenharmony_ci	return type;
18358c2ecf20Sopenharmony_ci
18368c2ecf20Sopenharmony_ciout_free:
18378c2ecf20Sopenharmony_ci	/* Top may point to itself */
18388c2ecf20Sopenharmony_ci	top->op.right = NULL;
18398c2ecf20Sopenharmony_ci	free_token(token);
18408c2ecf20Sopenharmony_ci	free_arg(arg);
18418c2ecf20Sopenharmony_ci	return TEP_EVENT_ERROR;
18428c2ecf20Sopenharmony_ci}
18438c2ecf20Sopenharmony_ci
18448c2ecf20Sopenharmony_cistatic enum tep_event_type
18458c2ecf20Sopenharmony_ciprocess_array(struct tep_event *event, struct tep_print_arg *top, char **tok)
18468c2ecf20Sopenharmony_ci{
18478c2ecf20Sopenharmony_ci	struct tep_print_arg *arg;
18488c2ecf20Sopenharmony_ci	enum tep_event_type type;
18498c2ecf20Sopenharmony_ci	char *token = NULL;
18508c2ecf20Sopenharmony_ci
18518c2ecf20Sopenharmony_ci	arg = alloc_arg();
18528c2ecf20Sopenharmony_ci	if (!arg) {
18538c2ecf20Sopenharmony_ci		do_warning_event(event, "%s: not enough memory!", __func__);
18548c2ecf20Sopenharmony_ci		/* '*tok' is set to top->op.op.  No need to free. */
18558c2ecf20Sopenharmony_ci		*tok = NULL;
18568c2ecf20Sopenharmony_ci		return TEP_EVENT_ERROR;
18578c2ecf20Sopenharmony_ci	}
18588c2ecf20Sopenharmony_ci
18598c2ecf20Sopenharmony_ci	*tok = NULL;
18608c2ecf20Sopenharmony_ci	type = process_arg(event, arg, &token);
18618c2ecf20Sopenharmony_ci	if (test_type_token(type, token, TEP_EVENT_OP, "]"))
18628c2ecf20Sopenharmony_ci		goto out_free;
18638c2ecf20Sopenharmony_ci
18648c2ecf20Sopenharmony_ci	top->op.right = arg;
18658c2ecf20Sopenharmony_ci
18668c2ecf20Sopenharmony_ci	free_token(token);
18678c2ecf20Sopenharmony_ci	type = read_token_item(&token);
18688c2ecf20Sopenharmony_ci	*tok = token;
18698c2ecf20Sopenharmony_ci
18708c2ecf20Sopenharmony_ci	return type;
18718c2ecf20Sopenharmony_ci
18728c2ecf20Sopenharmony_ciout_free:
18738c2ecf20Sopenharmony_ci	free_token(token);
18748c2ecf20Sopenharmony_ci	free_arg(arg);
18758c2ecf20Sopenharmony_ci	return TEP_EVENT_ERROR;
18768c2ecf20Sopenharmony_ci}
18778c2ecf20Sopenharmony_ci
18788c2ecf20Sopenharmony_cistatic int get_op_prio(char *op)
18798c2ecf20Sopenharmony_ci{
18808c2ecf20Sopenharmony_ci	if (!op[1]) {
18818c2ecf20Sopenharmony_ci		switch (op[0]) {
18828c2ecf20Sopenharmony_ci		case '~':
18838c2ecf20Sopenharmony_ci		case '!':
18848c2ecf20Sopenharmony_ci			return 4;
18858c2ecf20Sopenharmony_ci		case '*':
18868c2ecf20Sopenharmony_ci		case '/':
18878c2ecf20Sopenharmony_ci		case '%':
18888c2ecf20Sopenharmony_ci			return 6;
18898c2ecf20Sopenharmony_ci		case '+':
18908c2ecf20Sopenharmony_ci		case '-':
18918c2ecf20Sopenharmony_ci			return 7;
18928c2ecf20Sopenharmony_ci			/* '>>' and '<<' are 8 */
18938c2ecf20Sopenharmony_ci		case '<':
18948c2ecf20Sopenharmony_ci		case '>':
18958c2ecf20Sopenharmony_ci			return 9;
18968c2ecf20Sopenharmony_ci			/* '==' and '!=' are 10 */
18978c2ecf20Sopenharmony_ci		case '&':
18988c2ecf20Sopenharmony_ci			return 11;
18998c2ecf20Sopenharmony_ci		case '^':
19008c2ecf20Sopenharmony_ci			return 12;
19018c2ecf20Sopenharmony_ci		case '|':
19028c2ecf20Sopenharmony_ci			return 13;
19038c2ecf20Sopenharmony_ci		case '?':
19048c2ecf20Sopenharmony_ci			return 16;
19058c2ecf20Sopenharmony_ci		default:
19068c2ecf20Sopenharmony_ci			do_warning("unknown op '%c'", op[0]);
19078c2ecf20Sopenharmony_ci			return -1;
19088c2ecf20Sopenharmony_ci		}
19098c2ecf20Sopenharmony_ci	} else {
19108c2ecf20Sopenharmony_ci		if (strcmp(op, "++") == 0 ||
19118c2ecf20Sopenharmony_ci		    strcmp(op, "--") == 0) {
19128c2ecf20Sopenharmony_ci			return 3;
19138c2ecf20Sopenharmony_ci		} else if (strcmp(op, ">>") == 0 ||
19148c2ecf20Sopenharmony_ci			   strcmp(op, "<<") == 0) {
19158c2ecf20Sopenharmony_ci			return 8;
19168c2ecf20Sopenharmony_ci		} else if (strcmp(op, ">=") == 0 ||
19178c2ecf20Sopenharmony_ci			   strcmp(op, "<=") == 0) {
19188c2ecf20Sopenharmony_ci			return 9;
19198c2ecf20Sopenharmony_ci		} else if (strcmp(op, "==") == 0 ||
19208c2ecf20Sopenharmony_ci			   strcmp(op, "!=") == 0) {
19218c2ecf20Sopenharmony_ci			return 10;
19228c2ecf20Sopenharmony_ci		} else if (strcmp(op, "&&") == 0) {
19238c2ecf20Sopenharmony_ci			return 14;
19248c2ecf20Sopenharmony_ci		} else if (strcmp(op, "||") == 0) {
19258c2ecf20Sopenharmony_ci			return 15;
19268c2ecf20Sopenharmony_ci		} else {
19278c2ecf20Sopenharmony_ci			do_warning("unknown op '%s'", op);
19288c2ecf20Sopenharmony_ci			return -1;
19298c2ecf20Sopenharmony_ci		}
19308c2ecf20Sopenharmony_ci	}
19318c2ecf20Sopenharmony_ci}
19328c2ecf20Sopenharmony_ci
19338c2ecf20Sopenharmony_cistatic int set_op_prio(struct tep_print_arg *arg)
19348c2ecf20Sopenharmony_ci{
19358c2ecf20Sopenharmony_ci
19368c2ecf20Sopenharmony_ci	/* single ops are the greatest */
19378c2ecf20Sopenharmony_ci	if (!arg->op.left || arg->op.left->type == TEP_PRINT_NULL)
19388c2ecf20Sopenharmony_ci		arg->op.prio = 0;
19398c2ecf20Sopenharmony_ci	else
19408c2ecf20Sopenharmony_ci		arg->op.prio = get_op_prio(arg->op.op);
19418c2ecf20Sopenharmony_ci
19428c2ecf20Sopenharmony_ci	return arg->op.prio;
19438c2ecf20Sopenharmony_ci}
19448c2ecf20Sopenharmony_ci
19458c2ecf20Sopenharmony_ci/* Note, *tok does not get freed, but will most likely be saved */
19468c2ecf20Sopenharmony_cistatic enum tep_event_type
19478c2ecf20Sopenharmony_ciprocess_op(struct tep_event *event, struct tep_print_arg *arg, char **tok)
19488c2ecf20Sopenharmony_ci{
19498c2ecf20Sopenharmony_ci	struct tep_print_arg *left, *right = NULL;
19508c2ecf20Sopenharmony_ci	enum tep_event_type type;
19518c2ecf20Sopenharmony_ci	char *token;
19528c2ecf20Sopenharmony_ci
19538c2ecf20Sopenharmony_ci	/* the op is passed in via tok */
19548c2ecf20Sopenharmony_ci	token = *tok;
19558c2ecf20Sopenharmony_ci
19568c2ecf20Sopenharmony_ci	if (arg->type == TEP_PRINT_OP && !arg->op.left) {
19578c2ecf20Sopenharmony_ci		/* handle single op */
19588c2ecf20Sopenharmony_ci		if (token[1]) {
19598c2ecf20Sopenharmony_ci			do_warning_event(event, "bad op token %s", token);
19608c2ecf20Sopenharmony_ci			goto out_free;
19618c2ecf20Sopenharmony_ci		}
19628c2ecf20Sopenharmony_ci		switch (token[0]) {
19638c2ecf20Sopenharmony_ci		case '~':
19648c2ecf20Sopenharmony_ci		case '!':
19658c2ecf20Sopenharmony_ci		case '+':
19668c2ecf20Sopenharmony_ci		case '-':
19678c2ecf20Sopenharmony_ci			break;
19688c2ecf20Sopenharmony_ci		default:
19698c2ecf20Sopenharmony_ci			do_warning_event(event, "bad op token %s", token);
19708c2ecf20Sopenharmony_ci			goto out_free;
19718c2ecf20Sopenharmony_ci
19728c2ecf20Sopenharmony_ci		}
19738c2ecf20Sopenharmony_ci
19748c2ecf20Sopenharmony_ci		/* make an empty left */
19758c2ecf20Sopenharmony_ci		left = alloc_arg();
19768c2ecf20Sopenharmony_ci		if (!left)
19778c2ecf20Sopenharmony_ci			goto out_warn_free;
19788c2ecf20Sopenharmony_ci
19798c2ecf20Sopenharmony_ci		left->type = TEP_PRINT_NULL;
19808c2ecf20Sopenharmony_ci		arg->op.left = left;
19818c2ecf20Sopenharmony_ci
19828c2ecf20Sopenharmony_ci		right = alloc_arg();
19838c2ecf20Sopenharmony_ci		if (!right)
19848c2ecf20Sopenharmony_ci			goto out_warn_free;
19858c2ecf20Sopenharmony_ci
19868c2ecf20Sopenharmony_ci		arg->op.right = right;
19878c2ecf20Sopenharmony_ci
19888c2ecf20Sopenharmony_ci		/* do not free the token, it belongs to an op */
19898c2ecf20Sopenharmony_ci		*tok = NULL;
19908c2ecf20Sopenharmony_ci		type = process_arg(event, right, tok);
19918c2ecf20Sopenharmony_ci
19928c2ecf20Sopenharmony_ci	} else if (strcmp(token, "?") == 0) {
19938c2ecf20Sopenharmony_ci
19948c2ecf20Sopenharmony_ci		left = alloc_arg();
19958c2ecf20Sopenharmony_ci		if (!left)
19968c2ecf20Sopenharmony_ci			goto out_warn_free;
19978c2ecf20Sopenharmony_ci
19988c2ecf20Sopenharmony_ci		/* copy the top arg to the left */
19998c2ecf20Sopenharmony_ci		*left = *arg;
20008c2ecf20Sopenharmony_ci
20018c2ecf20Sopenharmony_ci		arg->type = TEP_PRINT_OP;
20028c2ecf20Sopenharmony_ci		arg->op.op = token;
20038c2ecf20Sopenharmony_ci		arg->op.left = left;
20048c2ecf20Sopenharmony_ci		arg->op.prio = 0;
20058c2ecf20Sopenharmony_ci
20068c2ecf20Sopenharmony_ci		/* it will set arg->op.right */
20078c2ecf20Sopenharmony_ci		type = process_cond(event, arg, tok);
20088c2ecf20Sopenharmony_ci
20098c2ecf20Sopenharmony_ci	} else if (strcmp(token, ">>") == 0 ||
20108c2ecf20Sopenharmony_ci		   strcmp(token, "<<") == 0 ||
20118c2ecf20Sopenharmony_ci		   strcmp(token, "&") == 0 ||
20128c2ecf20Sopenharmony_ci		   strcmp(token, "|") == 0 ||
20138c2ecf20Sopenharmony_ci		   strcmp(token, "&&") == 0 ||
20148c2ecf20Sopenharmony_ci		   strcmp(token, "||") == 0 ||
20158c2ecf20Sopenharmony_ci		   strcmp(token, "-") == 0 ||
20168c2ecf20Sopenharmony_ci		   strcmp(token, "+") == 0 ||
20178c2ecf20Sopenharmony_ci		   strcmp(token, "*") == 0 ||
20188c2ecf20Sopenharmony_ci		   strcmp(token, "^") == 0 ||
20198c2ecf20Sopenharmony_ci		   strcmp(token, "/") == 0 ||
20208c2ecf20Sopenharmony_ci		   strcmp(token, "%") == 0 ||
20218c2ecf20Sopenharmony_ci		   strcmp(token, "<") == 0 ||
20228c2ecf20Sopenharmony_ci		   strcmp(token, ">") == 0 ||
20238c2ecf20Sopenharmony_ci		   strcmp(token, "<=") == 0 ||
20248c2ecf20Sopenharmony_ci		   strcmp(token, ">=") == 0 ||
20258c2ecf20Sopenharmony_ci		   strcmp(token, "==") == 0 ||
20268c2ecf20Sopenharmony_ci		   strcmp(token, "!=") == 0) {
20278c2ecf20Sopenharmony_ci
20288c2ecf20Sopenharmony_ci		left = alloc_arg();
20298c2ecf20Sopenharmony_ci		if (!left)
20308c2ecf20Sopenharmony_ci			goto out_warn_free;
20318c2ecf20Sopenharmony_ci
20328c2ecf20Sopenharmony_ci		/* copy the top arg to the left */
20338c2ecf20Sopenharmony_ci		*left = *arg;
20348c2ecf20Sopenharmony_ci
20358c2ecf20Sopenharmony_ci		arg->type = TEP_PRINT_OP;
20368c2ecf20Sopenharmony_ci		arg->op.op = token;
20378c2ecf20Sopenharmony_ci		arg->op.left = left;
20388c2ecf20Sopenharmony_ci		arg->op.right = NULL;
20398c2ecf20Sopenharmony_ci
20408c2ecf20Sopenharmony_ci		if (set_op_prio(arg) == -1) {
20418c2ecf20Sopenharmony_ci			event->flags |= TEP_EVENT_FL_FAILED;
20428c2ecf20Sopenharmony_ci			/* arg->op.op (= token) will be freed at out_free */
20438c2ecf20Sopenharmony_ci			arg->op.op = NULL;
20448c2ecf20Sopenharmony_ci			goto out_free;
20458c2ecf20Sopenharmony_ci		}
20468c2ecf20Sopenharmony_ci
20478c2ecf20Sopenharmony_ci		type = read_token_item(&token);
20488c2ecf20Sopenharmony_ci		*tok = token;
20498c2ecf20Sopenharmony_ci
20508c2ecf20Sopenharmony_ci		/* could just be a type pointer */
20518c2ecf20Sopenharmony_ci		if ((strcmp(arg->op.op, "*") == 0) &&
20528c2ecf20Sopenharmony_ci		    type == TEP_EVENT_DELIM && (strcmp(token, ")") == 0)) {
20538c2ecf20Sopenharmony_ci			int ret;
20548c2ecf20Sopenharmony_ci
20558c2ecf20Sopenharmony_ci			if (left->type != TEP_PRINT_ATOM) {
20568c2ecf20Sopenharmony_ci				do_warning_event(event, "bad pointer type");
20578c2ecf20Sopenharmony_ci				goto out_free;
20588c2ecf20Sopenharmony_ci			}
20598c2ecf20Sopenharmony_ci			ret = append(&left->atom.atom, " ", "*");
20608c2ecf20Sopenharmony_ci			if (ret < 0)
20618c2ecf20Sopenharmony_ci				goto out_warn_free;
20628c2ecf20Sopenharmony_ci
20638c2ecf20Sopenharmony_ci			free(arg->op.op);
20648c2ecf20Sopenharmony_ci			*arg = *left;
20658c2ecf20Sopenharmony_ci			free(left);
20668c2ecf20Sopenharmony_ci
20678c2ecf20Sopenharmony_ci			return type;
20688c2ecf20Sopenharmony_ci		}
20698c2ecf20Sopenharmony_ci
20708c2ecf20Sopenharmony_ci		right = alloc_arg();
20718c2ecf20Sopenharmony_ci		if (!right)
20728c2ecf20Sopenharmony_ci			goto out_warn_free;
20738c2ecf20Sopenharmony_ci
20748c2ecf20Sopenharmony_ci		type = process_arg_token(event, right, tok, type);
20758c2ecf20Sopenharmony_ci		if (type == TEP_EVENT_ERROR) {
20768c2ecf20Sopenharmony_ci			free_arg(right);
20778c2ecf20Sopenharmony_ci			/* token was freed in process_arg_token() via *tok */
20788c2ecf20Sopenharmony_ci			token = NULL;
20798c2ecf20Sopenharmony_ci			goto out_free;
20808c2ecf20Sopenharmony_ci		}
20818c2ecf20Sopenharmony_ci
20828c2ecf20Sopenharmony_ci		if (right->type == TEP_PRINT_OP &&
20838c2ecf20Sopenharmony_ci		    get_op_prio(arg->op.op) < get_op_prio(right->op.op)) {
20848c2ecf20Sopenharmony_ci			struct tep_print_arg tmp;
20858c2ecf20Sopenharmony_ci
20868c2ecf20Sopenharmony_ci			/* rotate ops according to the priority */
20878c2ecf20Sopenharmony_ci			arg->op.right = right->op.left;
20888c2ecf20Sopenharmony_ci
20898c2ecf20Sopenharmony_ci			tmp = *arg;
20908c2ecf20Sopenharmony_ci			*arg = *right;
20918c2ecf20Sopenharmony_ci			*right = tmp;
20928c2ecf20Sopenharmony_ci
20938c2ecf20Sopenharmony_ci			arg->op.left = right;
20948c2ecf20Sopenharmony_ci		} else {
20958c2ecf20Sopenharmony_ci			arg->op.right = right;
20968c2ecf20Sopenharmony_ci		}
20978c2ecf20Sopenharmony_ci
20988c2ecf20Sopenharmony_ci	} else if (strcmp(token, "[") == 0) {
20998c2ecf20Sopenharmony_ci
21008c2ecf20Sopenharmony_ci		left = alloc_arg();
21018c2ecf20Sopenharmony_ci		if (!left)
21028c2ecf20Sopenharmony_ci			goto out_warn_free;
21038c2ecf20Sopenharmony_ci
21048c2ecf20Sopenharmony_ci		*left = *arg;
21058c2ecf20Sopenharmony_ci
21068c2ecf20Sopenharmony_ci		arg->type = TEP_PRINT_OP;
21078c2ecf20Sopenharmony_ci		arg->op.op = token;
21088c2ecf20Sopenharmony_ci		arg->op.left = left;
21098c2ecf20Sopenharmony_ci
21108c2ecf20Sopenharmony_ci		arg->op.prio = 0;
21118c2ecf20Sopenharmony_ci
21128c2ecf20Sopenharmony_ci		/* it will set arg->op.right */
21138c2ecf20Sopenharmony_ci		type = process_array(event, arg, tok);
21148c2ecf20Sopenharmony_ci
21158c2ecf20Sopenharmony_ci	} else {
21168c2ecf20Sopenharmony_ci		do_warning_event(event, "unknown op '%s'", token);
21178c2ecf20Sopenharmony_ci		event->flags |= TEP_EVENT_FL_FAILED;
21188c2ecf20Sopenharmony_ci		/* the arg is now the left side */
21198c2ecf20Sopenharmony_ci		goto out_free;
21208c2ecf20Sopenharmony_ci	}
21218c2ecf20Sopenharmony_ci
21228c2ecf20Sopenharmony_ci	if (type == TEP_EVENT_OP && strcmp(*tok, ":") != 0) {
21238c2ecf20Sopenharmony_ci		int prio;
21248c2ecf20Sopenharmony_ci
21258c2ecf20Sopenharmony_ci		/* higher prios need to be closer to the root */
21268c2ecf20Sopenharmony_ci		prio = get_op_prio(*tok);
21278c2ecf20Sopenharmony_ci
21288c2ecf20Sopenharmony_ci		if (prio > arg->op.prio)
21298c2ecf20Sopenharmony_ci			return process_op(event, arg, tok);
21308c2ecf20Sopenharmony_ci
21318c2ecf20Sopenharmony_ci		return process_op(event, right, tok);
21328c2ecf20Sopenharmony_ci	}
21338c2ecf20Sopenharmony_ci
21348c2ecf20Sopenharmony_ci	return type;
21358c2ecf20Sopenharmony_ci
21368c2ecf20Sopenharmony_ciout_warn_free:
21378c2ecf20Sopenharmony_ci	do_warning_event(event, "%s: not enough memory!", __func__);
21388c2ecf20Sopenharmony_ciout_free:
21398c2ecf20Sopenharmony_ci	free_token(token);
21408c2ecf20Sopenharmony_ci	*tok = NULL;
21418c2ecf20Sopenharmony_ci	return TEP_EVENT_ERROR;
21428c2ecf20Sopenharmony_ci}
21438c2ecf20Sopenharmony_ci
21448c2ecf20Sopenharmony_cistatic enum tep_event_type
21458c2ecf20Sopenharmony_ciprocess_entry(struct tep_event *event __maybe_unused, struct tep_print_arg *arg,
21468c2ecf20Sopenharmony_ci	      char **tok)
21478c2ecf20Sopenharmony_ci{
21488c2ecf20Sopenharmony_ci	enum tep_event_type type;
21498c2ecf20Sopenharmony_ci	char *field;
21508c2ecf20Sopenharmony_ci	char *token;
21518c2ecf20Sopenharmony_ci
21528c2ecf20Sopenharmony_ci	if (read_expected(TEP_EVENT_OP, "->") < 0)
21538c2ecf20Sopenharmony_ci		goto out_err;
21548c2ecf20Sopenharmony_ci
21558c2ecf20Sopenharmony_ci	if (read_expect_type(TEP_EVENT_ITEM, &token) < 0)
21568c2ecf20Sopenharmony_ci		goto out_free;
21578c2ecf20Sopenharmony_ci	field = token;
21588c2ecf20Sopenharmony_ci
21598c2ecf20Sopenharmony_ci	arg->type = TEP_PRINT_FIELD;
21608c2ecf20Sopenharmony_ci	arg->field.name = field;
21618c2ecf20Sopenharmony_ci
21628c2ecf20Sopenharmony_ci	if (is_flag_field) {
21638c2ecf20Sopenharmony_ci		arg->field.field = tep_find_any_field(event, arg->field.name);
21648c2ecf20Sopenharmony_ci		arg->field.field->flags |= TEP_FIELD_IS_FLAG;
21658c2ecf20Sopenharmony_ci		is_flag_field = 0;
21668c2ecf20Sopenharmony_ci	} else if (is_symbolic_field) {
21678c2ecf20Sopenharmony_ci		arg->field.field = tep_find_any_field(event, arg->field.name);
21688c2ecf20Sopenharmony_ci		arg->field.field->flags |= TEP_FIELD_IS_SYMBOLIC;
21698c2ecf20Sopenharmony_ci		is_symbolic_field = 0;
21708c2ecf20Sopenharmony_ci	}
21718c2ecf20Sopenharmony_ci
21728c2ecf20Sopenharmony_ci	type = read_token(&token);
21738c2ecf20Sopenharmony_ci	*tok = token;
21748c2ecf20Sopenharmony_ci
21758c2ecf20Sopenharmony_ci	return type;
21768c2ecf20Sopenharmony_ci
21778c2ecf20Sopenharmony_ci out_free:
21788c2ecf20Sopenharmony_ci	free_token(token);
21798c2ecf20Sopenharmony_ci out_err:
21808c2ecf20Sopenharmony_ci	*tok = NULL;
21818c2ecf20Sopenharmony_ci	return TEP_EVENT_ERROR;
21828c2ecf20Sopenharmony_ci}
21838c2ecf20Sopenharmony_ci
21848c2ecf20Sopenharmony_cistatic int alloc_and_process_delim(struct tep_event *event, char *next_token,
21858c2ecf20Sopenharmony_ci				   struct tep_print_arg **print_arg)
21868c2ecf20Sopenharmony_ci{
21878c2ecf20Sopenharmony_ci	struct tep_print_arg *field;
21888c2ecf20Sopenharmony_ci	enum tep_event_type type;
21898c2ecf20Sopenharmony_ci	char *token;
21908c2ecf20Sopenharmony_ci	int ret = 0;
21918c2ecf20Sopenharmony_ci
21928c2ecf20Sopenharmony_ci	field = alloc_arg();
21938c2ecf20Sopenharmony_ci	if (!field) {
21948c2ecf20Sopenharmony_ci		do_warning_event(event, "%s: not enough memory!", __func__);
21958c2ecf20Sopenharmony_ci		errno = ENOMEM;
21968c2ecf20Sopenharmony_ci		return -1;
21978c2ecf20Sopenharmony_ci	}
21988c2ecf20Sopenharmony_ci
21998c2ecf20Sopenharmony_ci	type = process_arg(event, field, &token);
22008c2ecf20Sopenharmony_ci
22018c2ecf20Sopenharmony_ci	if (test_type_token(type, token, TEP_EVENT_DELIM, next_token)) {
22028c2ecf20Sopenharmony_ci		errno = EINVAL;
22038c2ecf20Sopenharmony_ci		ret = -1;
22048c2ecf20Sopenharmony_ci		free_arg(field);
22058c2ecf20Sopenharmony_ci		goto out_free_token;
22068c2ecf20Sopenharmony_ci	}
22078c2ecf20Sopenharmony_ci
22088c2ecf20Sopenharmony_ci	*print_arg = field;
22098c2ecf20Sopenharmony_ci
22108c2ecf20Sopenharmony_ciout_free_token:
22118c2ecf20Sopenharmony_ci	free_token(token);
22128c2ecf20Sopenharmony_ci
22138c2ecf20Sopenharmony_ci	return ret;
22148c2ecf20Sopenharmony_ci}
22158c2ecf20Sopenharmony_ci
22168c2ecf20Sopenharmony_cistatic char *arg_eval (struct tep_print_arg *arg);
22178c2ecf20Sopenharmony_ci
22188c2ecf20Sopenharmony_cistatic unsigned long long
22198c2ecf20Sopenharmony_cieval_type_str(unsigned long long val, const char *type, int pointer)
22208c2ecf20Sopenharmony_ci{
22218c2ecf20Sopenharmony_ci	int sign = 0;
22228c2ecf20Sopenharmony_ci	char *ref;
22238c2ecf20Sopenharmony_ci	int len;
22248c2ecf20Sopenharmony_ci
22258c2ecf20Sopenharmony_ci	len = strlen(type);
22268c2ecf20Sopenharmony_ci
22278c2ecf20Sopenharmony_ci	if (pointer) {
22288c2ecf20Sopenharmony_ci
22298c2ecf20Sopenharmony_ci		if (type[len-1] != '*') {
22308c2ecf20Sopenharmony_ci			do_warning("pointer expected with non pointer type");
22318c2ecf20Sopenharmony_ci			return val;
22328c2ecf20Sopenharmony_ci		}
22338c2ecf20Sopenharmony_ci
22348c2ecf20Sopenharmony_ci		ref = malloc(len);
22358c2ecf20Sopenharmony_ci		if (!ref) {
22368c2ecf20Sopenharmony_ci			do_warning("%s: not enough memory!", __func__);
22378c2ecf20Sopenharmony_ci			return val;
22388c2ecf20Sopenharmony_ci		}
22398c2ecf20Sopenharmony_ci		memcpy(ref, type, len);
22408c2ecf20Sopenharmony_ci
22418c2ecf20Sopenharmony_ci		/* chop off the " *" */
22428c2ecf20Sopenharmony_ci		ref[len - 2] = 0;
22438c2ecf20Sopenharmony_ci
22448c2ecf20Sopenharmony_ci		val = eval_type_str(val, ref, 0);
22458c2ecf20Sopenharmony_ci		free(ref);
22468c2ecf20Sopenharmony_ci		return val;
22478c2ecf20Sopenharmony_ci	}
22488c2ecf20Sopenharmony_ci
22498c2ecf20Sopenharmony_ci	/* check if this is a pointer */
22508c2ecf20Sopenharmony_ci	if (type[len - 1] == '*')
22518c2ecf20Sopenharmony_ci		return val;
22528c2ecf20Sopenharmony_ci
22538c2ecf20Sopenharmony_ci	/* Try to figure out the arg size*/
22548c2ecf20Sopenharmony_ci	if (strncmp(type, "struct", 6) == 0)
22558c2ecf20Sopenharmony_ci		/* all bets off */
22568c2ecf20Sopenharmony_ci		return val;
22578c2ecf20Sopenharmony_ci
22588c2ecf20Sopenharmony_ci	if (strcmp(type, "u8") == 0)
22598c2ecf20Sopenharmony_ci		return val & 0xff;
22608c2ecf20Sopenharmony_ci
22618c2ecf20Sopenharmony_ci	if (strcmp(type, "u16") == 0)
22628c2ecf20Sopenharmony_ci		return val & 0xffff;
22638c2ecf20Sopenharmony_ci
22648c2ecf20Sopenharmony_ci	if (strcmp(type, "u32") == 0)
22658c2ecf20Sopenharmony_ci		return val & 0xffffffff;
22668c2ecf20Sopenharmony_ci
22678c2ecf20Sopenharmony_ci	if (strcmp(type, "u64") == 0 ||
22688c2ecf20Sopenharmony_ci	    strcmp(type, "s64") == 0)
22698c2ecf20Sopenharmony_ci		return val;
22708c2ecf20Sopenharmony_ci
22718c2ecf20Sopenharmony_ci	if (strcmp(type, "s8") == 0)
22728c2ecf20Sopenharmony_ci		return (unsigned long long)(char)val & 0xff;
22738c2ecf20Sopenharmony_ci
22748c2ecf20Sopenharmony_ci	if (strcmp(type, "s16") == 0)
22758c2ecf20Sopenharmony_ci		return (unsigned long long)(short)val & 0xffff;
22768c2ecf20Sopenharmony_ci
22778c2ecf20Sopenharmony_ci	if (strcmp(type, "s32") == 0)
22788c2ecf20Sopenharmony_ci		return (unsigned long long)(int)val & 0xffffffff;
22798c2ecf20Sopenharmony_ci
22808c2ecf20Sopenharmony_ci	if (strncmp(type, "unsigned ", 9) == 0) {
22818c2ecf20Sopenharmony_ci		sign = 0;
22828c2ecf20Sopenharmony_ci		type += 9;
22838c2ecf20Sopenharmony_ci	}
22848c2ecf20Sopenharmony_ci
22858c2ecf20Sopenharmony_ci	if (strcmp(type, "char") == 0) {
22868c2ecf20Sopenharmony_ci		if (sign)
22878c2ecf20Sopenharmony_ci			return (unsigned long long)(char)val & 0xff;
22888c2ecf20Sopenharmony_ci		else
22898c2ecf20Sopenharmony_ci			return val & 0xff;
22908c2ecf20Sopenharmony_ci	}
22918c2ecf20Sopenharmony_ci
22928c2ecf20Sopenharmony_ci	if (strcmp(type, "short") == 0) {
22938c2ecf20Sopenharmony_ci		if (sign)
22948c2ecf20Sopenharmony_ci			return (unsigned long long)(short)val & 0xffff;
22958c2ecf20Sopenharmony_ci		else
22968c2ecf20Sopenharmony_ci			return val & 0xffff;
22978c2ecf20Sopenharmony_ci	}
22988c2ecf20Sopenharmony_ci
22998c2ecf20Sopenharmony_ci	if (strcmp(type, "int") == 0) {
23008c2ecf20Sopenharmony_ci		if (sign)
23018c2ecf20Sopenharmony_ci			return (unsigned long long)(int)val & 0xffffffff;
23028c2ecf20Sopenharmony_ci		else
23038c2ecf20Sopenharmony_ci			return val & 0xffffffff;
23048c2ecf20Sopenharmony_ci	}
23058c2ecf20Sopenharmony_ci
23068c2ecf20Sopenharmony_ci	return val;
23078c2ecf20Sopenharmony_ci}
23088c2ecf20Sopenharmony_ci
23098c2ecf20Sopenharmony_ci/*
23108c2ecf20Sopenharmony_ci * Try to figure out the type.
23118c2ecf20Sopenharmony_ci */
23128c2ecf20Sopenharmony_cistatic unsigned long long
23138c2ecf20Sopenharmony_cieval_type(unsigned long long val, struct tep_print_arg *arg, int pointer)
23148c2ecf20Sopenharmony_ci{
23158c2ecf20Sopenharmony_ci	if (arg->type != TEP_PRINT_TYPE) {
23168c2ecf20Sopenharmony_ci		do_warning("expected type argument");
23178c2ecf20Sopenharmony_ci		return 0;
23188c2ecf20Sopenharmony_ci	}
23198c2ecf20Sopenharmony_ci
23208c2ecf20Sopenharmony_ci	return eval_type_str(val, arg->typecast.type, pointer);
23218c2ecf20Sopenharmony_ci}
23228c2ecf20Sopenharmony_ci
23238c2ecf20Sopenharmony_cistatic int arg_num_eval(struct tep_print_arg *arg, long long *val)
23248c2ecf20Sopenharmony_ci{
23258c2ecf20Sopenharmony_ci	long long left, right;
23268c2ecf20Sopenharmony_ci	int ret = 1;
23278c2ecf20Sopenharmony_ci
23288c2ecf20Sopenharmony_ci	switch (arg->type) {
23298c2ecf20Sopenharmony_ci	case TEP_PRINT_ATOM:
23308c2ecf20Sopenharmony_ci		*val = strtoll(arg->atom.atom, NULL, 0);
23318c2ecf20Sopenharmony_ci		break;
23328c2ecf20Sopenharmony_ci	case TEP_PRINT_TYPE:
23338c2ecf20Sopenharmony_ci		ret = arg_num_eval(arg->typecast.item, val);
23348c2ecf20Sopenharmony_ci		if (!ret)
23358c2ecf20Sopenharmony_ci			break;
23368c2ecf20Sopenharmony_ci		*val = eval_type(*val, arg, 0);
23378c2ecf20Sopenharmony_ci		break;
23388c2ecf20Sopenharmony_ci	case TEP_PRINT_OP:
23398c2ecf20Sopenharmony_ci		switch (arg->op.op[0]) {
23408c2ecf20Sopenharmony_ci		case '|':
23418c2ecf20Sopenharmony_ci			ret = arg_num_eval(arg->op.left, &left);
23428c2ecf20Sopenharmony_ci			if (!ret)
23438c2ecf20Sopenharmony_ci				break;
23448c2ecf20Sopenharmony_ci			ret = arg_num_eval(arg->op.right, &right);
23458c2ecf20Sopenharmony_ci			if (!ret)
23468c2ecf20Sopenharmony_ci				break;
23478c2ecf20Sopenharmony_ci			if (arg->op.op[1])
23488c2ecf20Sopenharmony_ci				*val = left || right;
23498c2ecf20Sopenharmony_ci			else
23508c2ecf20Sopenharmony_ci				*val = left | right;
23518c2ecf20Sopenharmony_ci			break;
23528c2ecf20Sopenharmony_ci		case '&':
23538c2ecf20Sopenharmony_ci			ret = arg_num_eval(arg->op.left, &left);
23548c2ecf20Sopenharmony_ci			if (!ret)
23558c2ecf20Sopenharmony_ci				break;
23568c2ecf20Sopenharmony_ci			ret = arg_num_eval(arg->op.right, &right);
23578c2ecf20Sopenharmony_ci			if (!ret)
23588c2ecf20Sopenharmony_ci				break;
23598c2ecf20Sopenharmony_ci			if (arg->op.op[1])
23608c2ecf20Sopenharmony_ci				*val = left && right;
23618c2ecf20Sopenharmony_ci			else
23628c2ecf20Sopenharmony_ci				*val = left & right;
23638c2ecf20Sopenharmony_ci			break;
23648c2ecf20Sopenharmony_ci		case '<':
23658c2ecf20Sopenharmony_ci			ret = arg_num_eval(arg->op.left, &left);
23668c2ecf20Sopenharmony_ci			if (!ret)
23678c2ecf20Sopenharmony_ci				break;
23688c2ecf20Sopenharmony_ci			ret = arg_num_eval(arg->op.right, &right);
23698c2ecf20Sopenharmony_ci			if (!ret)
23708c2ecf20Sopenharmony_ci				break;
23718c2ecf20Sopenharmony_ci			switch (arg->op.op[1]) {
23728c2ecf20Sopenharmony_ci			case 0:
23738c2ecf20Sopenharmony_ci				*val = left < right;
23748c2ecf20Sopenharmony_ci				break;
23758c2ecf20Sopenharmony_ci			case '<':
23768c2ecf20Sopenharmony_ci				*val = left << right;
23778c2ecf20Sopenharmony_ci				break;
23788c2ecf20Sopenharmony_ci			case '=':
23798c2ecf20Sopenharmony_ci				*val = left <= right;
23808c2ecf20Sopenharmony_ci				break;
23818c2ecf20Sopenharmony_ci			default:
23828c2ecf20Sopenharmony_ci				do_warning("unknown op '%s'", arg->op.op);
23838c2ecf20Sopenharmony_ci				ret = 0;
23848c2ecf20Sopenharmony_ci			}
23858c2ecf20Sopenharmony_ci			break;
23868c2ecf20Sopenharmony_ci		case '>':
23878c2ecf20Sopenharmony_ci			ret = arg_num_eval(arg->op.left, &left);
23888c2ecf20Sopenharmony_ci			if (!ret)
23898c2ecf20Sopenharmony_ci				break;
23908c2ecf20Sopenharmony_ci			ret = arg_num_eval(arg->op.right, &right);
23918c2ecf20Sopenharmony_ci			if (!ret)
23928c2ecf20Sopenharmony_ci				break;
23938c2ecf20Sopenharmony_ci			switch (arg->op.op[1]) {
23948c2ecf20Sopenharmony_ci			case 0:
23958c2ecf20Sopenharmony_ci				*val = left > right;
23968c2ecf20Sopenharmony_ci				break;
23978c2ecf20Sopenharmony_ci			case '>':
23988c2ecf20Sopenharmony_ci				*val = left >> right;
23998c2ecf20Sopenharmony_ci				break;
24008c2ecf20Sopenharmony_ci			case '=':
24018c2ecf20Sopenharmony_ci				*val = left >= right;
24028c2ecf20Sopenharmony_ci				break;
24038c2ecf20Sopenharmony_ci			default:
24048c2ecf20Sopenharmony_ci				do_warning("unknown op '%s'", arg->op.op);
24058c2ecf20Sopenharmony_ci				ret = 0;
24068c2ecf20Sopenharmony_ci			}
24078c2ecf20Sopenharmony_ci			break;
24088c2ecf20Sopenharmony_ci		case '=':
24098c2ecf20Sopenharmony_ci			ret = arg_num_eval(arg->op.left, &left);
24108c2ecf20Sopenharmony_ci			if (!ret)
24118c2ecf20Sopenharmony_ci				break;
24128c2ecf20Sopenharmony_ci			ret = arg_num_eval(arg->op.right, &right);
24138c2ecf20Sopenharmony_ci			if (!ret)
24148c2ecf20Sopenharmony_ci				break;
24158c2ecf20Sopenharmony_ci
24168c2ecf20Sopenharmony_ci			if (arg->op.op[1] != '=') {
24178c2ecf20Sopenharmony_ci				do_warning("unknown op '%s'", arg->op.op);
24188c2ecf20Sopenharmony_ci				ret = 0;
24198c2ecf20Sopenharmony_ci			} else
24208c2ecf20Sopenharmony_ci				*val = left == right;
24218c2ecf20Sopenharmony_ci			break;
24228c2ecf20Sopenharmony_ci		case '!':
24238c2ecf20Sopenharmony_ci			ret = arg_num_eval(arg->op.left, &left);
24248c2ecf20Sopenharmony_ci			if (!ret)
24258c2ecf20Sopenharmony_ci				break;
24268c2ecf20Sopenharmony_ci			ret = arg_num_eval(arg->op.right, &right);
24278c2ecf20Sopenharmony_ci			if (!ret)
24288c2ecf20Sopenharmony_ci				break;
24298c2ecf20Sopenharmony_ci
24308c2ecf20Sopenharmony_ci			switch (arg->op.op[1]) {
24318c2ecf20Sopenharmony_ci			case '=':
24328c2ecf20Sopenharmony_ci				*val = left != right;
24338c2ecf20Sopenharmony_ci				break;
24348c2ecf20Sopenharmony_ci			default:
24358c2ecf20Sopenharmony_ci				do_warning("unknown op '%s'", arg->op.op);
24368c2ecf20Sopenharmony_ci				ret = 0;
24378c2ecf20Sopenharmony_ci			}
24388c2ecf20Sopenharmony_ci			break;
24398c2ecf20Sopenharmony_ci		case '-':
24408c2ecf20Sopenharmony_ci			/* check for negative */
24418c2ecf20Sopenharmony_ci			if (arg->op.left->type == TEP_PRINT_NULL)
24428c2ecf20Sopenharmony_ci				left = 0;
24438c2ecf20Sopenharmony_ci			else
24448c2ecf20Sopenharmony_ci				ret = arg_num_eval(arg->op.left, &left);
24458c2ecf20Sopenharmony_ci			if (!ret)
24468c2ecf20Sopenharmony_ci				break;
24478c2ecf20Sopenharmony_ci			ret = arg_num_eval(arg->op.right, &right);
24488c2ecf20Sopenharmony_ci			if (!ret)
24498c2ecf20Sopenharmony_ci				break;
24508c2ecf20Sopenharmony_ci			*val = left - right;
24518c2ecf20Sopenharmony_ci			break;
24528c2ecf20Sopenharmony_ci		case '+':
24538c2ecf20Sopenharmony_ci			if (arg->op.left->type == TEP_PRINT_NULL)
24548c2ecf20Sopenharmony_ci				left = 0;
24558c2ecf20Sopenharmony_ci			else
24568c2ecf20Sopenharmony_ci				ret = arg_num_eval(arg->op.left, &left);
24578c2ecf20Sopenharmony_ci			if (!ret)
24588c2ecf20Sopenharmony_ci				break;
24598c2ecf20Sopenharmony_ci			ret = arg_num_eval(arg->op.right, &right);
24608c2ecf20Sopenharmony_ci			if (!ret)
24618c2ecf20Sopenharmony_ci				break;
24628c2ecf20Sopenharmony_ci			*val = left + right;
24638c2ecf20Sopenharmony_ci			break;
24648c2ecf20Sopenharmony_ci		case '~':
24658c2ecf20Sopenharmony_ci			ret = arg_num_eval(arg->op.right, &right);
24668c2ecf20Sopenharmony_ci			if (!ret)
24678c2ecf20Sopenharmony_ci				break;
24688c2ecf20Sopenharmony_ci			*val = ~right;
24698c2ecf20Sopenharmony_ci			break;
24708c2ecf20Sopenharmony_ci		default:
24718c2ecf20Sopenharmony_ci			do_warning("unknown op '%s'", arg->op.op);
24728c2ecf20Sopenharmony_ci			ret = 0;
24738c2ecf20Sopenharmony_ci		}
24748c2ecf20Sopenharmony_ci		break;
24758c2ecf20Sopenharmony_ci
24768c2ecf20Sopenharmony_ci	case TEP_PRINT_NULL:
24778c2ecf20Sopenharmony_ci	case TEP_PRINT_FIELD ... TEP_PRINT_SYMBOL:
24788c2ecf20Sopenharmony_ci	case TEP_PRINT_STRING:
24798c2ecf20Sopenharmony_ci	case TEP_PRINT_BSTRING:
24808c2ecf20Sopenharmony_ci	case TEP_PRINT_BITMASK:
24818c2ecf20Sopenharmony_ci	default:
24828c2ecf20Sopenharmony_ci		do_warning("invalid eval type %d", arg->type);
24838c2ecf20Sopenharmony_ci		ret = 0;
24848c2ecf20Sopenharmony_ci
24858c2ecf20Sopenharmony_ci	}
24868c2ecf20Sopenharmony_ci	return ret;
24878c2ecf20Sopenharmony_ci}
24888c2ecf20Sopenharmony_ci
24898c2ecf20Sopenharmony_cistatic char *arg_eval (struct tep_print_arg *arg)
24908c2ecf20Sopenharmony_ci{
24918c2ecf20Sopenharmony_ci	long long val;
24928c2ecf20Sopenharmony_ci	static char buf[24];
24938c2ecf20Sopenharmony_ci
24948c2ecf20Sopenharmony_ci	switch (arg->type) {
24958c2ecf20Sopenharmony_ci	case TEP_PRINT_ATOM:
24968c2ecf20Sopenharmony_ci		return arg->atom.atom;
24978c2ecf20Sopenharmony_ci	case TEP_PRINT_TYPE:
24988c2ecf20Sopenharmony_ci		return arg_eval(arg->typecast.item);
24998c2ecf20Sopenharmony_ci	case TEP_PRINT_OP:
25008c2ecf20Sopenharmony_ci		if (!arg_num_eval(arg, &val))
25018c2ecf20Sopenharmony_ci			break;
25028c2ecf20Sopenharmony_ci		sprintf(buf, "%lld", val);
25038c2ecf20Sopenharmony_ci		return buf;
25048c2ecf20Sopenharmony_ci
25058c2ecf20Sopenharmony_ci	case TEP_PRINT_NULL:
25068c2ecf20Sopenharmony_ci	case TEP_PRINT_FIELD ... TEP_PRINT_SYMBOL:
25078c2ecf20Sopenharmony_ci	case TEP_PRINT_STRING:
25088c2ecf20Sopenharmony_ci	case TEP_PRINT_BSTRING:
25098c2ecf20Sopenharmony_ci	case TEP_PRINT_BITMASK:
25108c2ecf20Sopenharmony_ci	default:
25118c2ecf20Sopenharmony_ci		do_warning("invalid eval type %d", arg->type);
25128c2ecf20Sopenharmony_ci		break;
25138c2ecf20Sopenharmony_ci	}
25148c2ecf20Sopenharmony_ci
25158c2ecf20Sopenharmony_ci	return NULL;
25168c2ecf20Sopenharmony_ci}
25178c2ecf20Sopenharmony_ci
25188c2ecf20Sopenharmony_cistatic enum tep_event_type
25198c2ecf20Sopenharmony_ciprocess_fields(struct tep_event *event, struct tep_print_flag_sym **list, char **tok)
25208c2ecf20Sopenharmony_ci{
25218c2ecf20Sopenharmony_ci	enum tep_event_type type;
25228c2ecf20Sopenharmony_ci	struct tep_print_arg *arg = NULL;
25238c2ecf20Sopenharmony_ci	struct tep_print_flag_sym *field;
25248c2ecf20Sopenharmony_ci	char *token = *tok;
25258c2ecf20Sopenharmony_ci	char *value;
25268c2ecf20Sopenharmony_ci
25278c2ecf20Sopenharmony_ci	do {
25288c2ecf20Sopenharmony_ci		free_token(token);
25298c2ecf20Sopenharmony_ci		type = read_token_item(&token);
25308c2ecf20Sopenharmony_ci		if (test_type_token(type, token, TEP_EVENT_OP, "{"))
25318c2ecf20Sopenharmony_ci			break;
25328c2ecf20Sopenharmony_ci
25338c2ecf20Sopenharmony_ci		arg = alloc_arg();
25348c2ecf20Sopenharmony_ci		if (!arg)
25358c2ecf20Sopenharmony_ci			goto out_free;
25368c2ecf20Sopenharmony_ci
25378c2ecf20Sopenharmony_ci		free_token(token);
25388c2ecf20Sopenharmony_ci		type = process_arg(event, arg, &token);
25398c2ecf20Sopenharmony_ci
25408c2ecf20Sopenharmony_ci		if (type == TEP_EVENT_OP)
25418c2ecf20Sopenharmony_ci			type = process_op(event, arg, &token);
25428c2ecf20Sopenharmony_ci
25438c2ecf20Sopenharmony_ci		if (type == TEP_EVENT_ERROR)
25448c2ecf20Sopenharmony_ci			goto out_free;
25458c2ecf20Sopenharmony_ci
25468c2ecf20Sopenharmony_ci		if (test_type_token(type, token, TEP_EVENT_DELIM, ","))
25478c2ecf20Sopenharmony_ci			goto out_free;
25488c2ecf20Sopenharmony_ci
25498c2ecf20Sopenharmony_ci		field = calloc(1, sizeof(*field));
25508c2ecf20Sopenharmony_ci		if (!field)
25518c2ecf20Sopenharmony_ci			goto out_free;
25528c2ecf20Sopenharmony_ci
25538c2ecf20Sopenharmony_ci		value = arg_eval(arg);
25548c2ecf20Sopenharmony_ci		if (value == NULL)
25558c2ecf20Sopenharmony_ci			goto out_free_field;
25568c2ecf20Sopenharmony_ci		field->value = strdup(value);
25578c2ecf20Sopenharmony_ci		if (field->value == NULL)
25588c2ecf20Sopenharmony_ci			goto out_free_field;
25598c2ecf20Sopenharmony_ci
25608c2ecf20Sopenharmony_ci		free_arg(arg);
25618c2ecf20Sopenharmony_ci		arg = alloc_arg();
25628c2ecf20Sopenharmony_ci		if (!arg)
25638c2ecf20Sopenharmony_ci			goto out_free;
25648c2ecf20Sopenharmony_ci
25658c2ecf20Sopenharmony_ci		free_token(token);
25668c2ecf20Sopenharmony_ci		type = process_arg(event, arg, &token);
25678c2ecf20Sopenharmony_ci		if (test_type_token(type, token, TEP_EVENT_OP, "}"))
25688c2ecf20Sopenharmony_ci			goto out_free_field;
25698c2ecf20Sopenharmony_ci
25708c2ecf20Sopenharmony_ci		value = arg_eval(arg);
25718c2ecf20Sopenharmony_ci		if (value == NULL)
25728c2ecf20Sopenharmony_ci			goto out_free_field;
25738c2ecf20Sopenharmony_ci		field->str = strdup(value);
25748c2ecf20Sopenharmony_ci		if (field->str == NULL)
25758c2ecf20Sopenharmony_ci			goto out_free_field;
25768c2ecf20Sopenharmony_ci		free_arg(arg);
25778c2ecf20Sopenharmony_ci		arg = NULL;
25788c2ecf20Sopenharmony_ci
25798c2ecf20Sopenharmony_ci		*list = field;
25808c2ecf20Sopenharmony_ci		list = &field->next;
25818c2ecf20Sopenharmony_ci
25828c2ecf20Sopenharmony_ci		free_token(token);
25838c2ecf20Sopenharmony_ci		type = read_token_item(&token);
25848c2ecf20Sopenharmony_ci	} while (type == TEP_EVENT_DELIM && strcmp(token, ",") == 0);
25858c2ecf20Sopenharmony_ci
25868c2ecf20Sopenharmony_ci	*tok = token;
25878c2ecf20Sopenharmony_ci	return type;
25888c2ecf20Sopenharmony_ci
25898c2ecf20Sopenharmony_ciout_free_field:
25908c2ecf20Sopenharmony_ci	free_flag_sym(field);
25918c2ecf20Sopenharmony_ciout_free:
25928c2ecf20Sopenharmony_ci	free_arg(arg);
25938c2ecf20Sopenharmony_ci	free_token(token);
25948c2ecf20Sopenharmony_ci	*tok = NULL;
25958c2ecf20Sopenharmony_ci
25968c2ecf20Sopenharmony_ci	return TEP_EVENT_ERROR;
25978c2ecf20Sopenharmony_ci}
25988c2ecf20Sopenharmony_ci
25998c2ecf20Sopenharmony_cistatic enum tep_event_type
26008c2ecf20Sopenharmony_ciprocess_flags(struct tep_event *event, struct tep_print_arg *arg, char **tok)
26018c2ecf20Sopenharmony_ci{
26028c2ecf20Sopenharmony_ci	struct tep_print_arg *field;
26038c2ecf20Sopenharmony_ci	enum tep_event_type type;
26048c2ecf20Sopenharmony_ci	char *token = NULL;
26058c2ecf20Sopenharmony_ci
26068c2ecf20Sopenharmony_ci	memset(arg, 0, sizeof(*arg));
26078c2ecf20Sopenharmony_ci	arg->type = TEP_PRINT_FLAGS;
26088c2ecf20Sopenharmony_ci
26098c2ecf20Sopenharmony_ci	field = alloc_arg();
26108c2ecf20Sopenharmony_ci	if (!field) {
26118c2ecf20Sopenharmony_ci		do_warning_event(event, "%s: not enough memory!", __func__);
26128c2ecf20Sopenharmony_ci		goto out_free;
26138c2ecf20Sopenharmony_ci	}
26148c2ecf20Sopenharmony_ci
26158c2ecf20Sopenharmony_ci	type = process_field_arg(event, field, &token);
26168c2ecf20Sopenharmony_ci
26178c2ecf20Sopenharmony_ci	/* Handle operations in the first argument */
26188c2ecf20Sopenharmony_ci	while (type == TEP_EVENT_OP)
26198c2ecf20Sopenharmony_ci		type = process_op(event, field, &token);
26208c2ecf20Sopenharmony_ci
26218c2ecf20Sopenharmony_ci	if (test_type_token(type, token, TEP_EVENT_DELIM, ","))
26228c2ecf20Sopenharmony_ci		goto out_free_field;
26238c2ecf20Sopenharmony_ci	free_token(token);
26248c2ecf20Sopenharmony_ci
26258c2ecf20Sopenharmony_ci	arg->flags.field = field;
26268c2ecf20Sopenharmony_ci
26278c2ecf20Sopenharmony_ci	type = read_token_item(&token);
26288c2ecf20Sopenharmony_ci	if (event_item_type(type)) {
26298c2ecf20Sopenharmony_ci		arg->flags.delim = token;
26308c2ecf20Sopenharmony_ci		type = read_token_item(&token);
26318c2ecf20Sopenharmony_ci	}
26328c2ecf20Sopenharmony_ci
26338c2ecf20Sopenharmony_ci	if (test_type_token(type, token, TEP_EVENT_DELIM, ","))
26348c2ecf20Sopenharmony_ci		goto out_free;
26358c2ecf20Sopenharmony_ci
26368c2ecf20Sopenharmony_ci	type = process_fields(event, &arg->flags.flags, &token);
26378c2ecf20Sopenharmony_ci	if (test_type_token(type, token, TEP_EVENT_DELIM, ")"))
26388c2ecf20Sopenharmony_ci		goto out_free;
26398c2ecf20Sopenharmony_ci
26408c2ecf20Sopenharmony_ci	free_token(token);
26418c2ecf20Sopenharmony_ci	type = read_token_item(tok);
26428c2ecf20Sopenharmony_ci	return type;
26438c2ecf20Sopenharmony_ci
26448c2ecf20Sopenharmony_ciout_free_field:
26458c2ecf20Sopenharmony_ci	free_arg(field);
26468c2ecf20Sopenharmony_ciout_free:
26478c2ecf20Sopenharmony_ci	free_token(token);
26488c2ecf20Sopenharmony_ci	*tok = NULL;
26498c2ecf20Sopenharmony_ci	return TEP_EVENT_ERROR;
26508c2ecf20Sopenharmony_ci}
26518c2ecf20Sopenharmony_ci
26528c2ecf20Sopenharmony_cistatic enum tep_event_type
26538c2ecf20Sopenharmony_ciprocess_symbols(struct tep_event *event, struct tep_print_arg *arg, char **tok)
26548c2ecf20Sopenharmony_ci{
26558c2ecf20Sopenharmony_ci	struct tep_print_arg *field;
26568c2ecf20Sopenharmony_ci	enum tep_event_type type;
26578c2ecf20Sopenharmony_ci	char *token = NULL;
26588c2ecf20Sopenharmony_ci
26598c2ecf20Sopenharmony_ci	memset(arg, 0, sizeof(*arg));
26608c2ecf20Sopenharmony_ci	arg->type = TEP_PRINT_SYMBOL;
26618c2ecf20Sopenharmony_ci
26628c2ecf20Sopenharmony_ci	field = alloc_arg();
26638c2ecf20Sopenharmony_ci	if (!field) {
26648c2ecf20Sopenharmony_ci		do_warning_event(event, "%s: not enough memory!", __func__);
26658c2ecf20Sopenharmony_ci		goto out_free;
26668c2ecf20Sopenharmony_ci	}
26678c2ecf20Sopenharmony_ci
26688c2ecf20Sopenharmony_ci	type = process_field_arg(event, field, &token);
26698c2ecf20Sopenharmony_ci
26708c2ecf20Sopenharmony_ci	if (test_type_token(type, token, TEP_EVENT_DELIM, ","))
26718c2ecf20Sopenharmony_ci		goto out_free_field;
26728c2ecf20Sopenharmony_ci
26738c2ecf20Sopenharmony_ci	arg->symbol.field = field;
26748c2ecf20Sopenharmony_ci
26758c2ecf20Sopenharmony_ci	type = process_fields(event, &arg->symbol.symbols, &token);
26768c2ecf20Sopenharmony_ci	if (test_type_token(type, token, TEP_EVENT_DELIM, ")"))
26778c2ecf20Sopenharmony_ci		goto out_free;
26788c2ecf20Sopenharmony_ci
26798c2ecf20Sopenharmony_ci	free_token(token);
26808c2ecf20Sopenharmony_ci	type = read_token_item(tok);
26818c2ecf20Sopenharmony_ci	return type;
26828c2ecf20Sopenharmony_ci
26838c2ecf20Sopenharmony_ciout_free_field:
26848c2ecf20Sopenharmony_ci	free_arg(field);
26858c2ecf20Sopenharmony_ciout_free:
26868c2ecf20Sopenharmony_ci	free_token(token);
26878c2ecf20Sopenharmony_ci	*tok = NULL;
26888c2ecf20Sopenharmony_ci	return TEP_EVENT_ERROR;
26898c2ecf20Sopenharmony_ci}
26908c2ecf20Sopenharmony_ci
26918c2ecf20Sopenharmony_cistatic enum tep_event_type
26928c2ecf20Sopenharmony_ciprocess_hex_common(struct tep_event *event, struct tep_print_arg *arg,
26938c2ecf20Sopenharmony_ci		   char **tok, enum tep_print_arg_type type)
26948c2ecf20Sopenharmony_ci{
26958c2ecf20Sopenharmony_ci	memset(arg, 0, sizeof(*arg));
26968c2ecf20Sopenharmony_ci	arg->type = type;
26978c2ecf20Sopenharmony_ci
26988c2ecf20Sopenharmony_ci	if (alloc_and_process_delim(event, ",", &arg->hex.field))
26998c2ecf20Sopenharmony_ci		goto out;
27008c2ecf20Sopenharmony_ci
27018c2ecf20Sopenharmony_ci	if (alloc_and_process_delim(event, ")", &arg->hex.size))
27028c2ecf20Sopenharmony_ci		goto free_field;
27038c2ecf20Sopenharmony_ci
27048c2ecf20Sopenharmony_ci	return read_token_item(tok);
27058c2ecf20Sopenharmony_ci
27068c2ecf20Sopenharmony_cifree_field:
27078c2ecf20Sopenharmony_ci	free_arg(arg->hex.field);
27088c2ecf20Sopenharmony_ci	arg->hex.field = NULL;
27098c2ecf20Sopenharmony_ciout:
27108c2ecf20Sopenharmony_ci	*tok = NULL;
27118c2ecf20Sopenharmony_ci	return TEP_EVENT_ERROR;
27128c2ecf20Sopenharmony_ci}
27138c2ecf20Sopenharmony_ci
27148c2ecf20Sopenharmony_cistatic enum tep_event_type
27158c2ecf20Sopenharmony_ciprocess_hex(struct tep_event *event, struct tep_print_arg *arg, char **tok)
27168c2ecf20Sopenharmony_ci{
27178c2ecf20Sopenharmony_ci	return process_hex_common(event, arg, tok, TEP_PRINT_HEX);
27188c2ecf20Sopenharmony_ci}
27198c2ecf20Sopenharmony_ci
27208c2ecf20Sopenharmony_cistatic enum tep_event_type
27218c2ecf20Sopenharmony_ciprocess_hex_str(struct tep_event *event, struct tep_print_arg *arg,
27228c2ecf20Sopenharmony_ci		char **tok)
27238c2ecf20Sopenharmony_ci{
27248c2ecf20Sopenharmony_ci	return process_hex_common(event, arg, tok, TEP_PRINT_HEX_STR);
27258c2ecf20Sopenharmony_ci}
27268c2ecf20Sopenharmony_ci
27278c2ecf20Sopenharmony_cistatic enum tep_event_type
27288c2ecf20Sopenharmony_ciprocess_int_array(struct tep_event *event, struct tep_print_arg *arg, char **tok)
27298c2ecf20Sopenharmony_ci{
27308c2ecf20Sopenharmony_ci	memset(arg, 0, sizeof(*arg));
27318c2ecf20Sopenharmony_ci	arg->type = TEP_PRINT_INT_ARRAY;
27328c2ecf20Sopenharmony_ci
27338c2ecf20Sopenharmony_ci	if (alloc_and_process_delim(event, ",", &arg->int_array.field))
27348c2ecf20Sopenharmony_ci		goto out;
27358c2ecf20Sopenharmony_ci
27368c2ecf20Sopenharmony_ci	if (alloc_and_process_delim(event, ",", &arg->int_array.count))
27378c2ecf20Sopenharmony_ci		goto free_field;
27388c2ecf20Sopenharmony_ci
27398c2ecf20Sopenharmony_ci	if (alloc_and_process_delim(event, ")", &arg->int_array.el_size))
27408c2ecf20Sopenharmony_ci		goto free_size;
27418c2ecf20Sopenharmony_ci
27428c2ecf20Sopenharmony_ci	return read_token_item(tok);
27438c2ecf20Sopenharmony_ci
27448c2ecf20Sopenharmony_cifree_size:
27458c2ecf20Sopenharmony_ci	free_arg(arg->int_array.count);
27468c2ecf20Sopenharmony_ci	arg->int_array.count = NULL;
27478c2ecf20Sopenharmony_cifree_field:
27488c2ecf20Sopenharmony_ci	free_arg(arg->int_array.field);
27498c2ecf20Sopenharmony_ci	arg->int_array.field = NULL;
27508c2ecf20Sopenharmony_ciout:
27518c2ecf20Sopenharmony_ci	*tok = NULL;
27528c2ecf20Sopenharmony_ci	return TEP_EVENT_ERROR;
27538c2ecf20Sopenharmony_ci}
27548c2ecf20Sopenharmony_ci
27558c2ecf20Sopenharmony_cistatic enum tep_event_type
27568c2ecf20Sopenharmony_ciprocess_dynamic_array(struct tep_event *event, struct tep_print_arg *arg, char **tok)
27578c2ecf20Sopenharmony_ci{
27588c2ecf20Sopenharmony_ci	struct tep_format_field *field;
27598c2ecf20Sopenharmony_ci	enum tep_event_type type;
27608c2ecf20Sopenharmony_ci	char *token;
27618c2ecf20Sopenharmony_ci
27628c2ecf20Sopenharmony_ci	memset(arg, 0, sizeof(*arg));
27638c2ecf20Sopenharmony_ci	arg->type = TEP_PRINT_DYNAMIC_ARRAY;
27648c2ecf20Sopenharmony_ci
27658c2ecf20Sopenharmony_ci	/*
27668c2ecf20Sopenharmony_ci	 * The item within the parenthesis is another field that holds
27678c2ecf20Sopenharmony_ci	 * the index into where the array starts.
27688c2ecf20Sopenharmony_ci	 */
27698c2ecf20Sopenharmony_ci	type = read_token(&token);
27708c2ecf20Sopenharmony_ci	*tok = token;
27718c2ecf20Sopenharmony_ci	if (type != TEP_EVENT_ITEM)
27728c2ecf20Sopenharmony_ci		goto out_free;
27738c2ecf20Sopenharmony_ci
27748c2ecf20Sopenharmony_ci	/* Find the field */
27758c2ecf20Sopenharmony_ci
27768c2ecf20Sopenharmony_ci	field = tep_find_field(event, token);
27778c2ecf20Sopenharmony_ci	if (!field)
27788c2ecf20Sopenharmony_ci		goto out_free;
27798c2ecf20Sopenharmony_ci
27808c2ecf20Sopenharmony_ci	arg->dynarray.field = field;
27818c2ecf20Sopenharmony_ci	arg->dynarray.index = 0;
27828c2ecf20Sopenharmony_ci
27838c2ecf20Sopenharmony_ci	if (read_expected(TEP_EVENT_DELIM, ")") < 0)
27848c2ecf20Sopenharmony_ci		goto out_free;
27858c2ecf20Sopenharmony_ci
27868c2ecf20Sopenharmony_ci	free_token(token);
27878c2ecf20Sopenharmony_ci	type = read_token_item(&token);
27888c2ecf20Sopenharmony_ci	*tok = token;
27898c2ecf20Sopenharmony_ci	if (type != TEP_EVENT_OP || strcmp(token, "[") != 0)
27908c2ecf20Sopenharmony_ci		return type;
27918c2ecf20Sopenharmony_ci
27928c2ecf20Sopenharmony_ci	free_token(token);
27938c2ecf20Sopenharmony_ci	arg = alloc_arg();
27948c2ecf20Sopenharmony_ci	if (!arg) {
27958c2ecf20Sopenharmony_ci		do_warning_event(event, "%s: not enough memory!", __func__);
27968c2ecf20Sopenharmony_ci		*tok = NULL;
27978c2ecf20Sopenharmony_ci		return TEP_EVENT_ERROR;
27988c2ecf20Sopenharmony_ci	}
27998c2ecf20Sopenharmony_ci
28008c2ecf20Sopenharmony_ci	type = process_arg(event, arg, &token);
28018c2ecf20Sopenharmony_ci	if (type == TEP_EVENT_ERROR)
28028c2ecf20Sopenharmony_ci		goto out_free_arg;
28038c2ecf20Sopenharmony_ci
28048c2ecf20Sopenharmony_ci	if (!test_type_token(type, token, TEP_EVENT_OP, "]"))
28058c2ecf20Sopenharmony_ci		goto out_free_arg;
28068c2ecf20Sopenharmony_ci
28078c2ecf20Sopenharmony_ci	free_token(token);
28088c2ecf20Sopenharmony_ci	type = read_token_item(tok);
28098c2ecf20Sopenharmony_ci	return type;
28108c2ecf20Sopenharmony_ci
28118c2ecf20Sopenharmony_ci out_free_arg:
28128c2ecf20Sopenharmony_ci	free_arg(arg);
28138c2ecf20Sopenharmony_ci out_free:
28148c2ecf20Sopenharmony_ci	free_token(token);
28158c2ecf20Sopenharmony_ci	*tok = NULL;
28168c2ecf20Sopenharmony_ci	return TEP_EVENT_ERROR;
28178c2ecf20Sopenharmony_ci}
28188c2ecf20Sopenharmony_ci
28198c2ecf20Sopenharmony_cistatic enum tep_event_type
28208c2ecf20Sopenharmony_ciprocess_dynamic_array_len(struct tep_event *event, struct tep_print_arg *arg,
28218c2ecf20Sopenharmony_ci			  char **tok)
28228c2ecf20Sopenharmony_ci{
28238c2ecf20Sopenharmony_ci	struct tep_format_field *field;
28248c2ecf20Sopenharmony_ci	enum tep_event_type type;
28258c2ecf20Sopenharmony_ci	char *token;
28268c2ecf20Sopenharmony_ci
28278c2ecf20Sopenharmony_ci	if (read_expect_type(TEP_EVENT_ITEM, &token) < 0)
28288c2ecf20Sopenharmony_ci		goto out_free;
28298c2ecf20Sopenharmony_ci
28308c2ecf20Sopenharmony_ci	arg->type = TEP_PRINT_DYNAMIC_ARRAY_LEN;
28318c2ecf20Sopenharmony_ci
28328c2ecf20Sopenharmony_ci	/* Find the field */
28338c2ecf20Sopenharmony_ci	field = tep_find_field(event, token);
28348c2ecf20Sopenharmony_ci	if (!field)
28358c2ecf20Sopenharmony_ci		goto out_free;
28368c2ecf20Sopenharmony_ci
28378c2ecf20Sopenharmony_ci	arg->dynarray.field = field;
28388c2ecf20Sopenharmony_ci	arg->dynarray.index = 0;
28398c2ecf20Sopenharmony_ci
28408c2ecf20Sopenharmony_ci	if (read_expected(TEP_EVENT_DELIM, ")") < 0)
28418c2ecf20Sopenharmony_ci		goto out_err;
28428c2ecf20Sopenharmony_ci
28438c2ecf20Sopenharmony_ci	free_token(token);
28448c2ecf20Sopenharmony_ci	type = read_token(&token);
28458c2ecf20Sopenharmony_ci	*tok = token;
28468c2ecf20Sopenharmony_ci
28478c2ecf20Sopenharmony_ci	return type;
28488c2ecf20Sopenharmony_ci
28498c2ecf20Sopenharmony_ci out_free:
28508c2ecf20Sopenharmony_ci	free_token(token);
28518c2ecf20Sopenharmony_ci out_err:
28528c2ecf20Sopenharmony_ci	*tok = NULL;
28538c2ecf20Sopenharmony_ci	return TEP_EVENT_ERROR;
28548c2ecf20Sopenharmony_ci}
28558c2ecf20Sopenharmony_ci
28568c2ecf20Sopenharmony_cistatic enum tep_event_type
28578c2ecf20Sopenharmony_ciprocess_paren(struct tep_event *event, struct tep_print_arg *arg, char **tok)
28588c2ecf20Sopenharmony_ci{
28598c2ecf20Sopenharmony_ci	struct tep_print_arg *item_arg;
28608c2ecf20Sopenharmony_ci	enum tep_event_type type;
28618c2ecf20Sopenharmony_ci	char *token;
28628c2ecf20Sopenharmony_ci
28638c2ecf20Sopenharmony_ci	type = process_arg(event, arg, &token);
28648c2ecf20Sopenharmony_ci
28658c2ecf20Sopenharmony_ci	if (type == TEP_EVENT_ERROR)
28668c2ecf20Sopenharmony_ci		goto out_free;
28678c2ecf20Sopenharmony_ci
28688c2ecf20Sopenharmony_ci	if (type == TEP_EVENT_OP)
28698c2ecf20Sopenharmony_ci		type = process_op(event, arg, &token);
28708c2ecf20Sopenharmony_ci
28718c2ecf20Sopenharmony_ci	if (type == TEP_EVENT_ERROR)
28728c2ecf20Sopenharmony_ci		goto out_free;
28738c2ecf20Sopenharmony_ci
28748c2ecf20Sopenharmony_ci	if (test_type_token(type, token, TEP_EVENT_DELIM, ")"))
28758c2ecf20Sopenharmony_ci		goto out_free;
28768c2ecf20Sopenharmony_ci
28778c2ecf20Sopenharmony_ci	free_token(token);
28788c2ecf20Sopenharmony_ci	type = read_token_item(&token);
28798c2ecf20Sopenharmony_ci
28808c2ecf20Sopenharmony_ci	/*
28818c2ecf20Sopenharmony_ci	 * If the next token is an item or another open paren, then
28828c2ecf20Sopenharmony_ci	 * this was a typecast.
28838c2ecf20Sopenharmony_ci	 */
28848c2ecf20Sopenharmony_ci	if (event_item_type(type) ||
28858c2ecf20Sopenharmony_ci	    (type == TEP_EVENT_DELIM && strcmp(token, "(") == 0)) {
28868c2ecf20Sopenharmony_ci
28878c2ecf20Sopenharmony_ci		/* make this a typecast and contine */
28888c2ecf20Sopenharmony_ci
28898c2ecf20Sopenharmony_ci		/* prevous must be an atom */
28908c2ecf20Sopenharmony_ci		if (arg->type != TEP_PRINT_ATOM) {
28918c2ecf20Sopenharmony_ci			do_warning_event(event, "previous needed to be TEP_PRINT_ATOM");
28928c2ecf20Sopenharmony_ci			goto out_free;
28938c2ecf20Sopenharmony_ci		}
28948c2ecf20Sopenharmony_ci
28958c2ecf20Sopenharmony_ci		item_arg = alloc_arg();
28968c2ecf20Sopenharmony_ci		if (!item_arg) {
28978c2ecf20Sopenharmony_ci			do_warning_event(event, "%s: not enough memory!",
28988c2ecf20Sopenharmony_ci					 __func__);
28998c2ecf20Sopenharmony_ci			goto out_free;
29008c2ecf20Sopenharmony_ci		}
29018c2ecf20Sopenharmony_ci
29028c2ecf20Sopenharmony_ci		arg->type = TEP_PRINT_TYPE;
29038c2ecf20Sopenharmony_ci		arg->typecast.type = arg->atom.atom;
29048c2ecf20Sopenharmony_ci		arg->typecast.item = item_arg;
29058c2ecf20Sopenharmony_ci		type = process_arg_token(event, item_arg, &token, type);
29068c2ecf20Sopenharmony_ci
29078c2ecf20Sopenharmony_ci	}
29088c2ecf20Sopenharmony_ci
29098c2ecf20Sopenharmony_ci	*tok = token;
29108c2ecf20Sopenharmony_ci	return type;
29118c2ecf20Sopenharmony_ci
29128c2ecf20Sopenharmony_ci out_free:
29138c2ecf20Sopenharmony_ci	free_token(token);
29148c2ecf20Sopenharmony_ci	*tok = NULL;
29158c2ecf20Sopenharmony_ci	return TEP_EVENT_ERROR;
29168c2ecf20Sopenharmony_ci}
29178c2ecf20Sopenharmony_ci
29188c2ecf20Sopenharmony_ci
29198c2ecf20Sopenharmony_cistatic enum tep_event_type
29208c2ecf20Sopenharmony_ciprocess_str(struct tep_event *event __maybe_unused, struct tep_print_arg *arg,
29218c2ecf20Sopenharmony_ci	    char **tok)
29228c2ecf20Sopenharmony_ci{
29238c2ecf20Sopenharmony_ci	enum tep_event_type type;
29248c2ecf20Sopenharmony_ci	char *token;
29258c2ecf20Sopenharmony_ci
29268c2ecf20Sopenharmony_ci	if (read_expect_type(TEP_EVENT_ITEM, &token) < 0)
29278c2ecf20Sopenharmony_ci		goto out_free;
29288c2ecf20Sopenharmony_ci
29298c2ecf20Sopenharmony_ci	arg->type = TEP_PRINT_STRING;
29308c2ecf20Sopenharmony_ci	arg->string.string = token;
29318c2ecf20Sopenharmony_ci	arg->string.offset = -1;
29328c2ecf20Sopenharmony_ci
29338c2ecf20Sopenharmony_ci	if (read_expected(TEP_EVENT_DELIM, ")") < 0)
29348c2ecf20Sopenharmony_ci		goto out_err;
29358c2ecf20Sopenharmony_ci
29368c2ecf20Sopenharmony_ci	type = read_token(&token);
29378c2ecf20Sopenharmony_ci	*tok = token;
29388c2ecf20Sopenharmony_ci
29398c2ecf20Sopenharmony_ci	return type;
29408c2ecf20Sopenharmony_ci
29418c2ecf20Sopenharmony_ci out_free:
29428c2ecf20Sopenharmony_ci	free_token(token);
29438c2ecf20Sopenharmony_ci out_err:
29448c2ecf20Sopenharmony_ci	*tok = NULL;
29458c2ecf20Sopenharmony_ci	return TEP_EVENT_ERROR;
29468c2ecf20Sopenharmony_ci}
29478c2ecf20Sopenharmony_ci
29488c2ecf20Sopenharmony_cistatic enum tep_event_type
29498c2ecf20Sopenharmony_ciprocess_bitmask(struct tep_event *event __maybe_unused, struct tep_print_arg *arg,
29508c2ecf20Sopenharmony_ci		char **tok)
29518c2ecf20Sopenharmony_ci{
29528c2ecf20Sopenharmony_ci	enum tep_event_type type;
29538c2ecf20Sopenharmony_ci	char *token;
29548c2ecf20Sopenharmony_ci
29558c2ecf20Sopenharmony_ci	if (read_expect_type(TEP_EVENT_ITEM, &token) < 0)
29568c2ecf20Sopenharmony_ci		goto out_free;
29578c2ecf20Sopenharmony_ci
29588c2ecf20Sopenharmony_ci	arg->type = TEP_PRINT_BITMASK;
29598c2ecf20Sopenharmony_ci	arg->bitmask.bitmask = token;
29608c2ecf20Sopenharmony_ci	arg->bitmask.offset = -1;
29618c2ecf20Sopenharmony_ci
29628c2ecf20Sopenharmony_ci	if (read_expected(TEP_EVENT_DELIM, ")") < 0)
29638c2ecf20Sopenharmony_ci		goto out_err;
29648c2ecf20Sopenharmony_ci
29658c2ecf20Sopenharmony_ci	type = read_token(&token);
29668c2ecf20Sopenharmony_ci	*tok = token;
29678c2ecf20Sopenharmony_ci
29688c2ecf20Sopenharmony_ci	return type;
29698c2ecf20Sopenharmony_ci
29708c2ecf20Sopenharmony_ci out_free:
29718c2ecf20Sopenharmony_ci	free_token(token);
29728c2ecf20Sopenharmony_ci out_err:
29738c2ecf20Sopenharmony_ci	*tok = NULL;
29748c2ecf20Sopenharmony_ci	return TEP_EVENT_ERROR;
29758c2ecf20Sopenharmony_ci}
29768c2ecf20Sopenharmony_ci
29778c2ecf20Sopenharmony_cistatic struct tep_function_handler *
29788c2ecf20Sopenharmony_cifind_func_handler(struct tep_handle *tep, char *func_name)
29798c2ecf20Sopenharmony_ci{
29808c2ecf20Sopenharmony_ci	struct tep_function_handler *func;
29818c2ecf20Sopenharmony_ci
29828c2ecf20Sopenharmony_ci	if (!tep)
29838c2ecf20Sopenharmony_ci		return NULL;
29848c2ecf20Sopenharmony_ci
29858c2ecf20Sopenharmony_ci	for (func = tep->func_handlers; func; func = func->next) {
29868c2ecf20Sopenharmony_ci		if (strcmp(func->name, func_name) == 0)
29878c2ecf20Sopenharmony_ci			break;
29888c2ecf20Sopenharmony_ci	}
29898c2ecf20Sopenharmony_ci
29908c2ecf20Sopenharmony_ci	return func;
29918c2ecf20Sopenharmony_ci}
29928c2ecf20Sopenharmony_ci
29938c2ecf20Sopenharmony_cistatic void remove_func_handler(struct tep_handle *tep, char *func_name)
29948c2ecf20Sopenharmony_ci{
29958c2ecf20Sopenharmony_ci	struct tep_function_handler *func;
29968c2ecf20Sopenharmony_ci	struct tep_function_handler **next;
29978c2ecf20Sopenharmony_ci
29988c2ecf20Sopenharmony_ci	next = &tep->func_handlers;
29998c2ecf20Sopenharmony_ci	while ((func = *next)) {
30008c2ecf20Sopenharmony_ci		if (strcmp(func->name, func_name) == 0) {
30018c2ecf20Sopenharmony_ci			*next = func->next;
30028c2ecf20Sopenharmony_ci			free_func_handle(func);
30038c2ecf20Sopenharmony_ci			break;
30048c2ecf20Sopenharmony_ci		}
30058c2ecf20Sopenharmony_ci		next = &func->next;
30068c2ecf20Sopenharmony_ci	}
30078c2ecf20Sopenharmony_ci}
30088c2ecf20Sopenharmony_ci
30098c2ecf20Sopenharmony_cistatic enum tep_event_type
30108c2ecf20Sopenharmony_ciprocess_func_handler(struct tep_event *event, struct tep_function_handler *func,
30118c2ecf20Sopenharmony_ci		     struct tep_print_arg *arg, char **tok)
30128c2ecf20Sopenharmony_ci{
30138c2ecf20Sopenharmony_ci	struct tep_print_arg **next_arg;
30148c2ecf20Sopenharmony_ci	struct tep_print_arg *farg;
30158c2ecf20Sopenharmony_ci	enum tep_event_type type;
30168c2ecf20Sopenharmony_ci	char *token;
30178c2ecf20Sopenharmony_ci	int i;
30188c2ecf20Sopenharmony_ci
30198c2ecf20Sopenharmony_ci	arg->type = TEP_PRINT_FUNC;
30208c2ecf20Sopenharmony_ci	arg->func.func = func;
30218c2ecf20Sopenharmony_ci
30228c2ecf20Sopenharmony_ci	*tok = NULL;
30238c2ecf20Sopenharmony_ci
30248c2ecf20Sopenharmony_ci	next_arg = &(arg->func.args);
30258c2ecf20Sopenharmony_ci	for (i = 0; i < func->nr_args; i++) {
30268c2ecf20Sopenharmony_ci		farg = alloc_arg();
30278c2ecf20Sopenharmony_ci		if (!farg) {
30288c2ecf20Sopenharmony_ci			do_warning_event(event, "%s: not enough memory!",
30298c2ecf20Sopenharmony_ci					 __func__);
30308c2ecf20Sopenharmony_ci			return TEP_EVENT_ERROR;
30318c2ecf20Sopenharmony_ci		}
30328c2ecf20Sopenharmony_ci
30338c2ecf20Sopenharmony_ci		type = process_arg(event, farg, &token);
30348c2ecf20Sopenharmony_ci		if (i < (func->nr_args - 1)) {
30358c2ecf20Sopenharmony_ci			if (type != TEP_EVENT_DELIM || strcmp(token, ",") != 0) {
30368c2ecf20Sopenharmony_ci				do_warning_event(event,
30378c2ecf20Sopenharmony_ci					"Error: function '%s()' expects %d arguments but event %s only uses %d",
30388c2ecf20Sopenharmony_ci					func->name, func->nr_args,
30398c2ecf20Sopenharmony_ci					event->name, i + 1);
30408c2ecf20Sopenharmony_ci				goto err;
30418c2ecf20Sopenharmony_ci			}
30428c2ecf20Sopenharmony_ci		} else {
30438c2ecf20Sopenharmony_ci			if (type != TEP_EVENT_DELIM || strcmp(token, ")") != 0) {
30448c2ecf20Sopenharmony_ci				do_warning_event(event,
30458c2ecf20Sopenharmony_ci					"Error: function '%s()' only expects %d arguments but event %s has more",
30468c2ecf20Sopenharmony_ci					func->name, func->nr_args, event->name);
30478c2ecf20Sopenharmony_ci				goto err;
30488c2ecf20Sopenharmony_ci			}
30498c2ecf20Sopenharmony_ci		}
30508c2ecf20Sopenharmony_ci
30518c2ecf20Sopenharmony_ci		*next_arg = farg;
30528c2ecf20Sopenharmony_ci		next_arg = &(farg->next);
30538c2ecf20Sopenharmony_ci		free_token(token);
30548c2ecf20Sopenharmony_ci	}
30558c2ecf20Sopenharmony_ci
30568c2ecf20Sopenharmony_ci	type = read_token(&token);
30578c2ecf20Sopenharmony_ci	*tok = token;
30588c2ecf20Sopenharmony_ci
30598c2ecf20Sopenharmony_ci	return type;
30608c2ecf20Sopenharmony_ci
30618c2ecf20Sopenharmony_cierr:
30628c2ecf20Sopenharmony_ci	free_arg(farg);
30638c2ecf20Sopenharmony_ci	free_token(token);
30648c2ecf20Sopenharmony_ci	return TEP_EVENT_ERROR;
30658c2ecf20Sopenharmony_ci}
30668c2ecf20Sopenharmony_ci
30678c2ecf20Sopenharmony_cistatic enum tep_event_type
30688c2ecf20Sopenharmony_ciprocess_builtin_expect(struct tep_event *event, struct tep_print_arg *arg, char **tok)
30698c2ecf20Sopenharmony_ci{
30708c2ecf20Sopenharmony_ci	enum tep_event_type type;
30718c2ecf20Sopenharmony_ci	char *token = NULL;
30728c2ecf20Sopenharmony_ci
30738c2ecf20Sopenharmony_ci	/* Handle __builtin_expect( cond, #) */
30748c2ecf20Sopenharmony_ci	type = process_arg(event, arg, &token);
30758c2ecf20Sopenharmony_ci
30768c2ecf20Sopenharmony_ci	if (type != TEP_EVENT_DELIM || token[0] != ',')
30778c2ecf20Sopenharmony_ci		goto out_free;
30788c2ecf20Sopenharmony_ci
30798c2ecf20Sopenharmony_ci	free_token(token);
30808c2ecf20Sopenharmony_ci
30818c2ecf20Sopenharmony_ci	/* We don't care what the second parameter is of the __builtin_expect() */
30828c2ecf20Sopenharmony_ci	if (read_expect_type(TEP_EVENT_ITEM, &token) < 0)
30838c2ecf20Sopenharmony_ci		goto out_free;
30848c2ecf20Sopenharmony_ci
30858c2ecf20Sopenharmony_ci	if (read_expected(TEP_EVENT_DELIM, ")") < 0)
30868c2ecf20Sopenharmony_ci		goto out_free;
30878c2ecf20Sopenharmony_ci
30888c2ecf20Sopenharmony_ci	free_token(token);
30898c2ecf20Sopenharmony_ci	type = read_token_item(tok);
30908c2ecf20Sopenharmony_ci	return type;
30918c2ecf20Sopenharmony_ci
30928c2ecf20Sopenharmony_ciout_free:
30938c2ecf20Sopenharmony_ci	free_token(token);
30948c2ecf20Sopenharmony_ci	*tok = NULL;
30958c2ecf20Sopenharmony_ci	return TEP_EVENT_ERROR;
30968c2ecf20Sopenharmony_ci}
30978c2ecf20Sopenharmony_ci
30988c2ecf20Sopenharmony_cistatic enum tep_event_type
30998c2ecf20Sopenharmony_ciprocess_function(struct tep_event *event, struct tep_print_arg *arg,
31008c2ecf20Sopenharmony_ci		 char *token, char **tok)
31018c2ecf20Sopenharmony_ci{
31028c2ecf20Sopenharmony_ci	struct tep_function_handler *func;
31038c2ecf20Sopenharmony_ci
31048c2ecf20Sopenharmony_ci	if (strcmp(token, "__print_flags") == 0) {
31058c2ecf20Sopenharmony_ci		free_token(token);
31068c2ecf20Sopenharmony_ci		is_flag_field = 1;
31078c2ecf20Sopenharmony_ci		return process_flags(event, arg, tok);
31088c2ecf20Sopenharmony_ci	}
31098c2ecf20Sopenharmony_ci	if (strcmp(token, "__print_symbolic") == 0) {
31108c2ecf20Sopenharmony_ci		free_token(token);
31118c2ecf20Sopenharmony_ci		is_symbolic_field = 1;
31128c2ecf20Sopenharmony_ci		return process_symbols(event, arg, tok);
31138c2ecf20Sopenharmony_ci	}
31148c2ecf20Sopenharmony_ci	if (strcmp(token, "__print_hex") == 0) {
31158c2ecf20Sopenharmony_ci		free_token(token);
31168c2ecf20Sopenharmony_ci		return process_hex(event, arg, tok);
31178c2ecf20Sopenharmony_ci	}
31188c2ecf20Sopenharmony_ci	if (strcmp(token, "__print_hex_str") == 0) {
31198c2ecf20Sopenharmony_ci		free_token(token);
31208c2ecf20Sopenharmony_ci		return process_hex_str(event, arg, tok);
31218c2ecf20Sopenharmony_ci	}
31228c2ecf20Sopenharmony_ci	if (strcmp(token, "__print_array") == 0) {
31238c2ecf20Sopenharmony_ci		free_token(token);
31248c2ecf20Sopenharmony_ci		return process_int_array(event, arg, tok);
31258c2ecf20Sopenharmony_ci	}
31268c2ecf20Sopenharmony_ci	if (strcmp(token, "__get_str") == 0) {
31278c2ecf20Sopenharmony_ci		free_token(token);
31288c2ecf20Sopenharmony_ci		return process_str(event, arg, tok);
31298c2ecf20Sopenharmony_ci	}
31308c2ecf20Sopenharmony_ci	if (strcmp(token, "__get_bitmask") == 0) {
31318c2ecf20Sopenharmony_ci		free_token(token);
31328c2ecf20Sopenharmony_ci		return process_bitmask(event, arg, tok);
31338c2ecf20Sopenharmony_ci	}
31348c2ecf20Sopenharmony_ci	if (strcmp(token, "__get_dynamic_array") == 0) {
31358c2ecf20Sopenharmony_ci		free_token(token);
31368c2ecf20Sopenharmony_ci		return process_dynamic_array(event, arg, tok);
31378c2ecf20Sopenharmony_ci	}
31388c2ecf20Sopenharmony_ci	if (strcmp(token, "__get_dynamic_array_len") == 0) {
31398c2ecf20Sopenharmony_ci		free_token(token);
31408c2ecf20Sopenharmony_ci		return process_dynamic_array_len(event, arg, tok);
31418c2ecf20Sopenharmony_ci	}
31428c2ecf20Sopenharmony_ci	if (strcmp(token, "__builtin_expect") == 0) {
31438c2ecf20Sopenharmony_ci		free_token(token);
31448c2ecf20Sopenharmony_ci		return process_builtin_expect(event, arg, tok);
31458c2ecf20Sopenharmony_ci	}
31468c2ecf20Sopenharmony_ci
31478c2ecf20Sopenharmony_ci	func = find_func_handler(event->tep, token);
31488c2ecf20Sopenharmony_ci	if (func) {
31498c2ecf20Sopenharmony_ci		free_token(token);
31508c2ecf20Sopenharmony_ci		return process_func_handler(event, func, arg, tok);
31518c2ecf20Sopenharmony_ci	}
31528c2ecf20Sopenharmony_ci
31538c2ecf20Sopenharmony_ci	do_warning_event(event, "function %s not defined", token);
31548c2ecf20Sopenharmony_ci	free_token(token);
31558c2ecf20Sopenharmony_ci	return TEP_EVENT_ERROR;
31568c2ecf20Sopenharmony_ci}
31578c2ecf20Sopenharmony_ci
31588c2ecf20Sopenharmony_cistatic enum tep_event_type
31598c2ecf20Sopenharmony_ciprocess_arg_token(struct tep_event *event, struct tep_print_arg *arg,
31608c2ecf20Sopenharmony_ci		  char **tok, enum tep_event_type type)
31618c2ecf20Sopenharmony_ci{
31628c2ecf20Sopenharmony_ci	char *token;
31638c2ecf20Sopenharmony_ci	char *atom;
31648c2ecf20Sopenharmony_ci
31658c2ecf20Sopenharmony_ci	token = *tok;
31668c2ecf20Sopenharmony_ci
31678c2ecf20Sopenharmony_ci	switch (type) {
31688c2ecf20Sopenharmony_ci	case TEP_EVENT_ITEM:
31698c2ecf20Sopenharmony_ci		if (strcmp(token, "REC") == 0) {
31708c2ecf20Sopenharmony_ci			free_token(token);
31718c2ecf20Sopenharmony_ci			type = process_entry(event, arg, &token);
31728c2ecf20Sopenharmony_ci			break;
31738c2ecf20Sopenharmony_ci		}
31748c2ecf20Sopenharmony_ci		atom = token;
31758c2ecf20Sopenharmony_ci		/* test the next token */
31768c2ecf20Sopenharmony_ci		type = read_token_item(&token);
31778c2ecf20Sopenharmony_ci
31788c2ecf20Sopenharmony_ci		/*
31798c2ecf20Sopenharmony_ci		 * If the next token is a parenthesis, then this
31808c2ecf20Sopenharmony_ci		 * is a function.
31818c2ecf20Sopenharmony_ci		 */
31828c2ecf20Sopenharmony_ci		if (type == TEP_EVENT_DELIM && strcmp(token, "(") == 0) {
31838c2ecf20Sopenharmony_ci			free_token(token);
31848c2ecf20Sopenharmony_ci			token = NULL;
31858c2ecf20Sopenharmony_ci			/* this will free atom. */
31868c2ecf20Sopenharmony_ci			type = process_function(event, arg, atom, &token);
31878c2ecf20Sopenharmony_ci			break;
31888c2ecf20Sopenharmony_ci		}
31898c2ecf20Sopenharmony_ci		/* atoms can be more than one token long */
31908c2ecf20Sopenharmony_ci		while (type == TEP_EVENT_ITEM) {
31918c2ecf20Sopenharmony_ci			int ret;
31928c2ecf20Sopenharmony_ci
31938c2ecf20Sopenharmony_ci			ret = append(&atom, " ", token);
31948c2ecf20Sopenharmony_ci			if (ret < 0) {
31958c2ecf20Sopenharmony_ci				free(atom);
31968c2ecf20Sopenharmony_ci				*tok = NULL;
31978c2ecf20Sopenharmony_ci				free_token(token);
31988c2ecf20Sopenharmony_ci				return TEP_EVENT_ERROR;
31998c2ecf20Sopenharmony_ci			}
32008c2ecf20Sopenharmony_ci			free_token(token);
32018c2ecf20Sopenharmony_ci			type = read_token_item(&token);
32028c2ecf20Sopenharmony_ci		}
32038c2ecf20Sopenharmony_ci
32048c2ecf20Sopenharmony_ci		arg->type = TEP_PRINT_ATOM;
32058c2ecf20Sopenharmony_ci		arg->atom.atom = atom;
32068c2ecf20Sopenharmony_ci		break;
32078c2ecf20Sopenharmony_ci
32088c2ecf20Sopenharmony_ci	case TEP_EVENT_DQUOTE:
32098c2ecf20Sopenharmony_ci	case TEP_EVENT_SQUOTE:
32108c2ecf20Sopenharmony_ci		arg->type = TEP_PRINT_ATOM;
32118c2ecf20Sopenharmony_ci		arg->atom.atom = token;
32128c2ecf20Sopenharmony_ci		type = read_token_item(&token);
32138c2ecf20Sopenharmony_ci		break;
32148c2ecf20Sopenharmony_ci	case TEP_EVENT_DELIM:
32158c2ecf20Sopenharmony_ci		if (strcmp(token, "(") == 0) {
32168c2ecf20Sopenharmony_ci			free_token(token);
32178c2ecf20Sopenharmony_ci			type = process_paren(event, arg, &token);
32188c2ecf20Sopenharmony_ci			break;
32198c2ecf20Sopenharmony_ci		}
32208c2ecf20Sopenharmony_ci	case TEP_EVENT_OP:
32218c2ecf20Sopenharmony_ci		/* handle single ops */
32228c2ecf20Sopenharmony_ci		arg->type = TEP_PRINT_OP;
32238c2ecf20Sopenharmony_ci		arg->op.op = token;
32248c2ecf20Sopenharmony_ci		arg->op.left = NULL;
32258c2ecf20Sopenharmony_ci		type = process_op(event, arg, &token);
32268c2ecf20Sopenharmony_ci
32278c2ecf20Sopenharmony_ci		/* On error, the op is freed */
32288c2ecf20Sopenharmony_ci		if (type == TEP_EVENT_ERROR)
32298c2ecf20Sopenharmony_ci			arg->op.op = NULL;
32308c2ecf20Sopenharmony_ci
32318c2ecf20Sopenharmony_ci		/* return error type if errored */
32328c2ecf20Sopenharmony_ci		break;
32338c2ecf20Sopenharmony_ci
32348c2ecf20Sopenharmony_ci	case TEP_EVENT_ERROR ... TEP_EVENT_NEWLINE:
32358c2ecf20Sopenharmony_ci	default:
32368c2ecf20Sopenharmony_ci		do_warning_event(event, "unexpected type %d", type);
32378c2ecf20Sopenharmony_ci		return TEP_EVENT_ERROR;
32388c2ecf20Sopenharmony_ci	}
32398c2ecf20Sopenharmony_ci	*tok = token;
32408c2ecf20Sopenharmony_ci
32418c2ecf20Sopenharmony_ci	return type;
32428c2ecf20Sopenharmony_ci}
32438c2ecf20Sopenharmony_ci
32448c2ecf20Sopenharmony_cistatic int event_read_print_args(struct tep_event *event, struct tep_print_arg **list)
32458c2ecf20Sopenharmony_ci{
32468c2ecf20Sopenharmony_ci	enum tep_event_type type = TEP_EVENT_ERROR;
32478c2ecf20Sopenharmony_ci	struct tep_print_arg *arg;
32488c2ecf20Sopenharmony_ci	char *token;
32498c2ecf20Sopenharmony_ci	int args = 0;
32508c2ecf20Sopenharmony_ci
32518c2ecf20Sopenharmony_ci	do {
32528c2ecf20Sopenharmony_ci		if (type == TEP_EVENT_NEWLINE) {
32538c2ecf20Sopenharmony_ci			type = read_token_item(&token);
32548c2ecf20Sopenharmony_ci			continue;
32558c2ecf20Sopenharmony_ci		}
32568c2ecf20Sopenharmony_ci
32578c2ecf20Sopenharmony_ci		arg = alloc_arg();
32588c2ecf20Sopenharmony_ci		if (!arg) {
32598c2ecf20Sopenharmony_ci			do_warning_event(event, "%s: not enough memory!",
32608c2ecf20Sopenharmony_ci					 __func__);
32618c2ecf20Sopenharmony_ci			return -1;
32628c2ecf20Sopenharmony_ci		}
32638c2ecf20Sopenharmony_ci
32648c2ecf20Sopenharmony_ci		type = process_arg(event, arg, &token);
32658c2ecf20Sopenharmony_ci
32668c2ecf20Sopenharmony_ci		if (type == TEP_EVENT_ERROR) {
32678c2ecf20Sopenharmony_ci			free_token(token);
32688c2ecf20Sopenharmony_ci			free_arg(arg);
32698c2ecf20Sopenharmony_ci			return -1;
32708c2ecf20Sopenharmony_ci		}
32718c2ecf20Sopenharmony_ci
32728c2ecf20Sopenharmony_ci		*list = arg;
32738c2ecf20Sopenharmony_ci		args++;
32748c2ecf20Sopenharmony_ci
32758c2ecf20Sopenharmony_ci		if (type == TEP_EVENT_OP) {
32768c2ecf20Sopenharmony_ci			type = process_op(event, arg, &token);
32778c2ecf20Sopenharmony_ci			free_token(token);
32788c2ecf20Sopenharmony_ci			if (type == TEP_EVENT_ERROR) {
32798c2ecf20Sopenharmony_ci				*list = NULL;
32808c2ecf20Sopenharmony_ci				free_arg(arg);
32818c2ecf20Sopenharmony_ci				return -1;
32828c2ecf20Sopenharmony_ci			}
32838c2ecf20Sopenharmony_ci			list = &arg->next;
32848c2ecf20Sopenharmony_ci			continue;
32858c2ecf20Sopenharmony_ci		}
32868c2ecf20Sopenharmony_ci
32878c2ecf20Sopenharmony_ci		if (type == TEP_EVENT_DELIM && strcmp(token, ",") == 0) {
32888c2ecf20Sopenharmony_ci			free_token(token);
32898c2ecf20Sopenharmony_ci			*list = arg;
32908c2ecf20Sopenharmony_ci			list = &arg->next;
32918c2ecf20Sopenharmony_ci			continue;
32928c2ecf20Sopenharmony_ci		}
32938c2ecf20Sopenharmony_ci		break;
32948c2ecf20Sopenharmony_ci	} while (type != TEP_EVENT_NONE);
32958c2ecf20Sopenharmony_ci
32968c2ecf20Sopenharmony_ci	if (type != TEP_EVENT_NONE && type != TEP_EVENT_ERROR)
32978c2ecf20Sopenharmony_ci		free_token(token);
32988c2ecf20Sopenharmony_ci
32998c2ecf20Sopenharmony_ci	return args;
33008c2ecf20Sopenharmony_ci}
33018c2ecf20Sopenharmony_ci
33028c2ecf20Sopenharmony_cistatic int event_read_print(struct tep_event *event)
33038c2ecf20Sopenharmony_ci{
33048c2ecf20Sopenharmony_ci	enum tep_event_type type;
33058c2ecf20Sopenharmony_ci	char *token;
33068c2ecf20Sopenharmony_ci	int ret;
33078c2ecf20Sopenharmony_ci
33088c2ecf20Sopenharmony_ci	if (read_expected_item(TEP_EVENT_ITEM, "print") < 0)
33098c2ecf20Sopenharmony_ci		return -1;
33108c2ecf20Sopenharmony_ci
33118c2ecf20Sopenharmony_ci	if (read_expected(TEP_EVENT_ITEM, "fmt") < 0)
33128c2ecf20Sopenharmony_ci		return -1;
33138c2ecf20Sopenharmony_ci
33148c2ecf20Sopenharmony_ci	if (read_expected(TEP_EVENT_OP, ":") < 0)
33158c2ecf20Sopenharmony_ci		return -1;
33168c2ecf20Sopenharmony_ci
33178c2ecf20Sopenharmony_ci	if (read_expect_type(TEP_EVENT_DQUOTE, &token) < 0)
33188c2ecf20Sopenharmony_ci		goto fail;
33198c2ecf20Sopenharmony_ci
33208c2ecf20Sopenharmony_ci concat:
33218c2ecf20Sopenharmony_ci	event->print_fmt.format = token;
33228c2ecf20Sopenharmony_ci	event->print_fmt.args = NULL;
33238c2ecf20Sopenharmony_ci
33248c2ecf20Sopenharmony_ci	/* ok to have no arg */
33258c2ecf20Sopenharmony_ci	type = read_token_item(&token);
33268c2ecf20Sopenharmony_ci
33278c2ecf20Sopenharmony_ci	if (type == TEP_EVENT_NONE)
33288c2ecf20Sopenharmony_ci		return 0;
33298c2ecf20Sopenharmony_ci
33308c2ecf20Sopenharmony_ci	/* Handle concatenation of print lines */
33318c2ecf20Sopenharmony_ci	if (type == TEP_EVENT_DQUOTE) {
33328c2ecf20Sopenharmony_ci		char *cat;
33338c2ecf20Sopenharmony_ci
33348c2ecf20Sopenharmony_ci		if (asprintf(&cat, "%s%s", event->print_fmt.format, token) < 0)
33358c2ecf20Sopenharmony_ci			goto fail;
33368c2ecf20Sopenharmony_ci		free_token(token);
33378c2ecf20Sopenharmony_ci		free_token(event->print_fmt.format);
33388c2ecf20Sopenharmony_ci		event->print_fmt.format = NULL;
33398c2ecf20Sopenharmony_ci		token = cat;
33408c2ecf20Sopenharmony_ci		goto concat;
33418c2ecf20Sopenharmony_ci	}
33428c2ecf20Sopenharmony_ci
33438c2ecf20Sopenharmony_ci	if (test_type_token(type, token, TEP_EVENT_DELIM, ","))
33448c2ecf20Sopenharmony_ci		goto fail;
33458c2ecf20Sopenharmony_ci
33468c2ecf20Sopenharmony_ci	free_token(token);
33478c2ecf20Sopenharmony_ci
33488c2ecf20Sopenharmony_ci	ret = event_read_print_args(event, &event->print_fmt.args);
33498c2ecf20Sopenharmony_ci	if (ret < 0)
33508c2ecf20Sopenharmony_ci		return -1;
33518c2ecf20Sopenharmony_ci
33528c2ecf20Sopenharmony_ci	return ret;
33538c2ecf20Sopenharmony_ci
33548c2ecf20Sopenharmony_ci fail:
33558c2ecf20Sopenharmony_ci	free_token(token);
33568c2ecf20Sopenharmony_ci	return -1;
33578c2ecf20Sopenharmony_ci}
33588c2ecf20Sopenharmony_ci
33598c2ecf20Sopenharmony_ci/**
33608c2ecf20Sopenharmony_ci * tep_find_common_field - return a common field by event
33618c2ecf20Sopenharmony_ci * @event: handle for the event
33628c2ecf20Sopenharmony_ci * @name: the name of the common field to return
33638c2ecf20Sopenharmony_ci *
33648c2ecf20Sopenharmony_ci * Returns a common field from the event by the given @name.
33658c2ecf20Sopenharmony_ci * This only searches the common fields and not all field.
33668c2ecf20Sopenharmony_ci */
33678c2ecf20Sopenharmony_cistruct tep_format_field *
33688c2ecf20Sopenharmony_citep_find_common_field(struct tep_event *event, const char *name)
33698c2ecf20Sopenharmony_ci{
33708c2ecf20Sopenharmony_ci	struct tep_format_field *format;
33718c2ecf20Sopenharmony_ci
33728c2ecf20Sopenharmony_ci	for (format = event->format.common_fields;
33738c2ecf20Sopenharmony_ci	     format; format = format->next) {
33748c2ecf20Sopenharmony_ci		if (strcmp(format->name, name) == 0)
33758c2ecf20Sopenharmony_ci			break;
33768c2ecf20Sopenharmony_ci	}
33778c2ecf20Sopenharmony_ci
33788c2ecf20Sopenharmony_ci	return format;
33798c2ecf20Sopenharmony_ci}
33808c2ecf20Sopenharmony_ci
33818c2ecf20Sopenharmony_ci/**
33828c2ecf20Sopenharmony_ci * tep_find_field - find a non-common field
33838c2ecf20Sopenharmony_ci * @event: handle for the event
33848c2ecf20Sopenharmony_ci * @name: the name of the non-common field
33858c2ecf20Sopenharmony_ci *
33868c2ecf20Sopenharmony_ci * Returns a non-common field by the given @name.
33878c2ecf20Sopenharmony_ci * This does not search common fields.
33888c2ecf20Sopenharmony_ci */
33898c2ecf20Sopenharmony_cistruct tep_format_field *
33908c2ecf20Sopenharmony_citep_find_field(struct tep_event *event, const char *name)
33918c2ecf20Sopenharmony_ci{
33928c2ecf20Sopenharmony_ci	struct tep_format_field *format;
33938c2ecf20Sopenharmony_ci
33948c2ecf20Sopenharmony_ci	for (format = event->format.fields;
33958c2ecf20Sopenharmony_ci	     format; format = format->next) {
33968c2ecf20Sopenharmony_ci		if (strcmp(format->name, name) == 0)
33978c2ecf20Sopenharmony_ci			break;
33988c2ecf20Sopenharmony_ci	}
33998c2ecf20Sopenharmony_ci
34008c2ecf20Sopenharmony_ci	return format;
34018c2ecf20Sopenharmony_ci}
34028c2ecf20Sopenharmony_ci
34038c2ecf20Sopenharmony_ci/**
34048c2ecf20Sopenharmony_ci * tep_find_any_field - find any field by name
34058c2ecf20Sopenharmony_ci * @event: handle for the event
34068c2ecf20Sopenharmony_ci * @name: the name of the field
34078c2ecf20Sopenharmony_ci *
34088c2ecf20Sopenharmony_ci * Returns a field by the given @name.
34098c2ecf20Sopenharmony_ci * This searches the common field names first, then
34108c2ecf20Sopenharmony_ci * the non-common ones if a common one was not found.
34118c2ecf20Sopenharmony_ci */
34128c2ecf20Sopenharmony_cistruct tep_format_field *
34138c2ecf20Sopenharmony_citep_find_any_field(struct tep_event *event, const char *name)
34148c2ecf20Sopenharmony_ci{
34158c2ecf20Sopenharmony_ci	struct tep_format_field *format;
34168c2ecf20Sopenharmony_ci
34178c2ecf20Sopenharmony_ci	format = tep_find_common_field(event, name);
34188c2ecf20Sopenharmony_ci	if (format)
34198c2ecf20Sopenharmony_ci		return format;
34208c2ecf20Sopenharmony_ci	return tep_find_field(event, name);
34218c2ecf20Sopenharmony_ci}
34228c2ecf20Sopenharmony_ci
34238c2ecf20Sopenharmony_ci/**
34248c2ecf20Sopenharmony_ci * tep_read_number - read a number from data
34258c2ecf20Sopenharmony_ci * @tep: a handle to the trace event parser context
34268c2ecf20Sopenharmony_ci * @ptr: the raw data
34278c2ecf20Sopenharmony_ci * @size: the size of the data that holds the number
34288c2ecf20Sopenharmony_ci *
34298c2ecf20Sopenharmony_ci * Returns the number (converted to host) from the
34308c2ecf20Sopenharmony_ci * raw data.
34318c2ecf20Sopenharmony_ci */
34328c2ecf20Sopenharmony_ciunsigned long long tep_read_number(struct tep_handle *tep,
34338c2ecf20Sopenharmony_ci				   const void *ptr, int size)
34348c2ecf20Sopenharmony_ci{
34358c2ecf20Sopenharmony_ci	unsigned long long val;
34368c2ecf20Sopenharmony_ci
34378c2ecf20Sopenharmony_ci	switch (size) {
34388c2ecf20Sopenharmony_ci	case 1:
34398c2ecf20Sopenharmony_ci		return *(unsigned char *)ptr;
34408c2ecf20Sopenharmony_ci	case 2:
34418c2ecf20Sopenharmony_ci		return data2host2(tep, *(unsigned short *)ptr);
34428c2ecf20Sopenharmony_ci	case 4:
34438c2ecf20Sopenharmony_ci		return data2host4(tep, *(unsigned int *)ptr);
34448c2ecf20Sopenharmony_ci	case 8:
34458c2ecf20Sopenharmony_ci		memcpy(&val, (ptr), sizeof(unsigned long long));
34468c2ecf20Sopenharmony_ci		return data2host8(tep, val);
34478c2ecf20Sopenharmony_ci	default:
34488c2ecf20Sopenharmony_ci		/* BUG! */
34498c2ecf20Sopenharmony_ci		return 0;
34508c2ecf20Sopenharmony_ci	}
34518c2ecf20Sopenharmony_ci}
34528c2ecf20Sopenharmony_ci
34538c2ecf20Sopenharmony_ci/**
34548c2ecf20Sopenharmony_ci * tep_read_number_field - read a number from data
34558c2ecf20Sopenharmony_ci * @field: a handle to the field
34568c2ecf20Sopenharmony_ci * @data: the raw data to read
34578c2ecf20Sopenharmony_ci * @value: the value to place the number in
34588c2ecf20Sopenharmony_ci *
34598c2ecf20Sopenharmony_ci * Reads raw data according to a field offset and size,
34608c2ecf20Sopenharmony_ci * and translates it into @value.
34618c2ecf20Sopenharmony_ci *
34628c2ecf20Sopenharmony_ci * Returns 0 on success, -1 otherwise.
34638c2ecf20Sopenharmony_ci */
34648c2ecf20Sopenharmony_ciint tep_read_number_field(struct tep_format_field *field, const void *data,
34658c2ecf20Sopenharmony_ci			  unsigned long long *value)
34668c2ecf20Sopenharmony_ci{
34678c2ecf20Sopenharmony_ci	if (!field)
34688c2ecf20Sopenharmony_ci		return -1;
34698c2ecf20Sopenharmony_ci	switch (field->size) {
34708c2ecf20Sopenharmony_ci	case 1:
34718c2ecf20Sopenharmony_ci	case 2:
34728c2ecf20Sopenharmony_ci	case 4:
34738c2ecf20Sopenharmony_ci	case 8:
34748c2ecf20Sopenharmony_ci		*value = tep_read_number(field->event->tep,
34758c2ecf20Sopenharmony_ci					 data + field->offset, field->size);
34768c2ecf20Sopenharmony_ci		return 0;
34778c2ecf20Sopenharmony_ci	default:
34788c2ecf20Sopenharmony_ci		return -1;
34798c2ecf20Sopenharmony_ci	}
34808c2ecf20Sopenharmony_ci}
34818c2ecf20Sopenharmony_ci
34828c2ecf20Sopenharmony_cistatic int get_common_info(struct tep_handle *tep,
34838c2ecf20Sopenharmony_ci			   const char *type, int *offset, int *size)
34848c2ecf20Sopenharmony_ci{
34858c2ecf20Sopenharmony_ci	struct tep_event *event;
34868c2ecf20Sopenharmony_ci	struct tep_format_field *field;
34878c2ecf20Sopenharmony_ci
34888c2ecf20Sopenharmony_ci	/*
34898c2ecf20Sopenharmony_ci	 * All events should have the same common elements.
34908c2ecf20Sopenharmony_ci	 * Pick any event to find where the type is;
34918c2ecf20Sopenharmony_ci	 */
34928c2ecf20Sopenharmony_ci	if (!tep->events) {
34938c2ecf20Sopenharmony_ci		do_warning("no event_list!");
34948c2ecf20Sopenharmony_ci		return -1;
34958c2ecf20Sopenharmony_ci	}
34968c2ecf20Sopenharmony_ci
34978c2ecf20Sopenharmony_ci	event = tep->events[0];
34988c2ecf20Sopenharmony_ci	field = tep_find_common_field(event, type);
34998c2ecf20Sopenharmony_ci	if (!field)
35008c2ecf20Sopenharmony_ci		return -1;
35018c2ecf20Sopenharmony_ci
35028c2ecf20Sopenharmony_ci	*offset = field->offset;
35038c2ecf20Sopenharmony_ci	*size = field->size;
35048c2ecf20Sopenharmony_ci
35058c2ecf20Sopenharmony_ci	return 0;
35068c2ecf20Sopenharmony_ci}
35078c2ecf20Sopenharmony_ci
35088c2ecf20Sopenharmony_cistatic int __parse_common(struct tep_handle *tep, void *data,
35098c2ecf20Sopenharmony_ci			  int *size, int *offset, const char *name)
35108c2ecf20Sopenharmony_ci{
35118c2ecf20Sopenharmony_ci	int ret;
35128c2ecf20Sopenharmony_ci
35138c2ecf20Sopenharmony_ci	if (!*size) {
35148c2ecf20Sopenharmony_ci		ret = get_common_info(tep, name, offset, size);
35158c2ecf20Sopenharmony_ci		if (ret < 0)
35168c2ecf20Sopenharmony_ci			return ret;
35178c2ecf20Sopenharmony_ci	}
35188c2ecf20Sopenharmony_ci	return tep_read_number(tep, data + *offset, *size);
35198c2ecf20Sopenharmony_ci}
35208c2ecf20Sopenharmony_ci
35218c2ecf20Sopenharmony_cistatic int trace_parse_common_type(struct tep_handle *tep, void *data)
35228c2ecf20Sopenharmony_ci{
35238c2ecf20Sopenharmony_ci	return __parse_common(tep, data,
35248c2ecf20Sopenharmony_ci			      &tep->type_size, &tep->type_offset,
35258c2ecf20Sopenharmony_ci			      "common_type");
35268c2ecf20Sopenharmony_ci}
35278c2ecf20Sopenharmony_ci
35288c2ecf20Sopenharmony_cistatic int parse_common_pid(struct tep_handle *tep, void *data)
35298c2ecf20Sopenharmony_ci{
35308c2ecf20Sopenharmony_ci	return __parse_common(tep, data,
35318c2ecf20Sopenharmony_ci			      &tep->pid_size, &tep->pid_offset,
35328c2ecf20Sopenharmony_ci			      "common_pid");
35338c2ecf20Sopenharmony_ci}
35348c2ecf20Sopenharmony_ci
35358c2ecf20Sopenharmony_cistatic int parse_common_pc(struct tep_handle *tep, void *data)
35368c2ecf20Sopenharmony_ci{
35378c2ecf20Sopenharmony_ci	return __parse_common(tep, data,
35388c2ecf20Sopenharmony_ci			      &tep->pc_size, &tep->pc_offset,
35398c2ecf20Sopenharmony_ci			      "common_preempt_count");
35408c2ecf20Sopenharmony_ci}
35418c2ecf20Sopenharmony_ci
35428c2ecf20Sopenharmony_cistatic int parse_common_flags(struct tep_handle *tep, void *data)
35438c2ecf20Sopenharmony_ci{
35448c2ecf20Sopenharmony_ci	return __parse_common(tep, data,
35458c2ecf20Sopenharmony_ci			      &tep->flags_size, &tep->flags_offset,
35468c2ecf20Sopenharmony_ci			      "common_flags");
35478c2ecf20Sopenharmony_ci}
35488c2ecf20Sopenharmony_ci
35498c2ecf20Sopenharmony_cistatic int parse_common_lock_depth(struct tep_handle *tep, void *data)
35508c2ecf20Sopenharmony_ci{
35518c2ecf20Sopenharmony_ci	return __parse_common(tep, data,
35528c2ecf20Sopenharmony_ci			      &tep->ld_size, &tep->ld_offset,
35538c2ecf20Sopenharmony_ci			      "common_lock_depth");
35548c2ecf20Sopenharmony_ci}
35558c2ecf20Sopenharmony_ci
35568c2ecf20Sopenharmony_cistatic int parse_common_migrate_disable(struct tep_handle *tep, void *data)
35578c2ecf20Sopenharmony_ci{
35588c2ecf20Sopenharmony_ci	return __parse_common(tep, data,
35598c2ecf20Sopenharmony_ci			      &tep->ld_size, &tep->ld_offset,
35608c2ecf20Sopenharmony_ci			      "common_migrate_disable");
35618c2ecf20Sopenharmony_ci}
35628c2ecf20Sopenharmony_ci
35638c2ecf20Sopenharmony_cistatic int events_id_cmp(const void *a, const void *b);
35648c2ecf20Sopenharmony_ci
35658c2ecf20Sopenharmony_ci/**
35668c2ecf20Sopenharmony_ci * tep_find_event - find an event by given id
35678c2ecf20Sopenharmony_ci * @tep: a handle to the trace event parser context
35688c2ecf20Sopenharmony_ci * @id: the id of the event
35698c2ecf20Sopenharmony_ci *
35708c2ecf20Sopenharmony_ci * Returns an event that has a given @id.
35718c2ecf20Sopenharmony_ci */
35728c2ecf20Sopenharmony_cistruct tep_event *tep_find_event(struct tep_handle *tep, int id)
35738c2ecf20Sopenharmony_ci{
35748c2ecf20Sopenharmony_ci	struct tep_event **eventptr;
35758c2ecf20Sopenharmony_ci	struct tep_event key;
35768c2ecf20Sopenharmony_ci	struct tep_event *pkey = &key;
35778c2ecf20Sopenharmony_ci
35788c2ecf20Sopenharmony_ci	/* Check cache first */
35798c2ecf20Sopenharmony_ci	if (tep->last_event && tep->last_event->id == id)
35808c2ecf20Sopenharmony_ci		return tep->last_event;
35818c2ecf20Sopenharmony_ci
35828c2ecf20Sopenharmony_ci	key.id = id;
35838c2ecf20Sopenharmony_ci
35848c2ecf20Sopenharmony_ci	eventptr = bsearch(&pkey, tep->events, tep->nr_events,
35858c2ecf20Sopenharmony_ci			   sizeof(*tep->events), events_id_cmp);
35868c2ecf20Sopenharmony_ci
35878c2ecf20Sopenharmony_ci	if (eventptr) {
35888c2ecf20Sopenharmony_ci		tep->last_event = *eventptr;
35898c2ecf20Sopenharmony_ci		return *eventptr;
35908c2ecf20Sopenharmony_ci	}
35918c2ecf20Sopenharmony_ci
35928c2ecf20Sopenharmony_ci	return NULL;
35938c2ecf20Sopenharmony_ci}
35948c2ecf20Sopenharmony_ci
35958c2ecf20Sopenharmony_ci/**
35968c2ecf20Sopenharmony_ci * tep_find_event_by_name - find an event by given name
35978c2ecf20Sopenharmony_ci * @tep: a handle to the trace event parser context
35988c2ecf20Sopenharmony_ci * @sys: the system name to search for
35998c2ecf20Sopenharmony_ci * @name: the name of the event to search for
36008c2ecf20Sopenharmony_ci *
36018c2ecf20Sopenharmony_ci * This returns an event with a given @name and under the system
36028c2ecf20Sopenharmony_ci * @sys. If @sys is NULL the first event with @name is returned.
36038c2ecf20Sopenharmony_ci */
36048c2ecf20Sopenharmony_cistruct tep_event *
36058c2ecf20Sopenharmony_citep_find_event_by_name(struct tep_handle *tep,
36068c2ecf20Sopenharmony_ci		       const char *sys, const char *name)
36078c2ecf20Sopenharmony_ci{
36088c2ecf20Sopenharmony_ci	struct tep_event *event = NULL;
36098c2ecf20Sopenharmony_ci	int i;
36108c2ecf20Sopenharmony_ci
36118c2ecf20Sopenharmony_ci	if (tep->last_event &&
36128c2ecf20Sopenharmony_ci	    strcmp(tep->last_event->name, name) == 0 &&
36138c2ecf20Sopenharmony_ci	    (!sys || strcmp(tep->last_event->system, sys) == 0))
36148c2ecf20Sopenharmony_ci		return tep->last_event;
36158c2ecf20Sopenharmony_ci
36168c2ecf20Sopenharmony_ci	for (i = 0; i < tep->nr_events; i++) {
36178c2ecf20Sopenharmony_ci		event = tep->events[i];
36188c2ecf20Sopenharmony_ci		if (strcmp(event->name, name) == 0) {
36198c2ecf20Sopenharmony_ci			if (!sys)
36208c2ecf20Sopenharmony_ci				break;
36218c2ecf20Sopenharmony_ci			if (strcmp(event->system, sys) == 0)
36228c2ecf20Sopenharmony_ci				break;
36238c2ecf20Sopenharmony_ci		}
36248c2ecf20Sopenharmony_ci	}
36258c2ecf20Sopenharmony_ci	if (i == tep->nr_events)
36268c2ecf20Sopenharmony_ci		event = NULL;
36278c2ecf20Sopenharmony_ci
36288c2ecf20Sopenharmony_ci	tep->last_event = event;
36298c2ecf20Sopenharmony_ci	return event;
36308c2ecf20Sopenharmony_ci}
36318c2ecf20Sopenharmony_ci
36328c2ecf20Sopenharmony_cistatic unsigned long long
36338c2ecf20Sopenharmony_cieval_num_arg(void *data, int size, struct tep_event *event, struct tep_print_arg *arg)
36348c2ecf20Sopenharmony_ci{
36358c2ecf20Sopenharmony_ci	struct tep_handle *tep = event->tep;
36368c2ecf20Sopenharmony_ci	unsigned long long val = 0;
36378c2ecf20Sopenharmony_ci	unsigned long long left, right;
36388c2ecf20Sopenharmony_ci	struct tep_print_arg *typearg = NULL;
36398c2ecf20Sopenharmony_ci	struct tep_print_arg *larg;
36408c2ecf20Sopenharmony_ci	unsigned long offset;
36418c2ecf20Sopenharmony_ci	unsigned int field_size;
36428c2ecf20Sopenharmony_ci
36438c2ecf20Sopenharmony_ci	switch (arg->type) {
36448c2ecf20Sopenharmony_ci	case TEP_PRINT_NULL:
36458c2ecf20Sopenharmony_ci		/* ?? */
36468c2ecf20Sopenharmony_ci		return 0;
36478c2ecf20Sopenharmony_ci	case TEP_PRINT_ATOM:
36488c2ecf20Sopenharmony_ci		return strtoull(arg->atom.atom, NULL, 0);
36498c2ecf20Sopenharmony_ci	case TEP_PRINT_FIELD:
36508c2ecf20Sopenharmony_ci		if (!arg->field.field) {
36518c2ecf20Sopenharmony_ci			arg->field.field = tep_find_any_field(event, arg->field.name);
36528c2ecf20Sopenharmony_ci			if (!arg->field.field)
36538c2ecf20Sopenharmony_ci				goto out_warning_field;
36548c2ecf20Sopenharmony_ci
36558c2ecf20Sopenharmony_ci		}
36568c2ecf20Sopenharmony_ci		/* must be a number */
36578c2ecf20Sopenharmony_ci		val = tep_read_number(tep, data + arg->field.field->offset,
36588c2ecf20Sopenharmony_ci				      arg->field.field->size);
36598c2ecf20Sopenharmony_ci		break;
36608c2ecf20Sopenharmony_ci	case TEP_PRINT_FLAGS:
36618c2ecf20Sopenharmony_ci	case TEP_PRINT_SYMBOL:
36628c2ecf20Sopenharmony_ci	case TEP_PRINT_INT_ARRAY:
36638c2ecf20Sopenharmony_ci	case TEP_PRINT_HEX:
36648c2ecf20Sopenharmony_ci	case TEP_PRINT_HEX_STR:
36658c2ecf20Sopenharmony_ci		break;
36668c2ecf20Sopenharmony_ci	case TEP_PRINT_TYPE:
36678c2ecf20Sopenharmony_ci		val = eval_num_arg(data, size, event, arg->typecast.item);
36688c2ecf20Sopenharmony_ci		return eval_type(val, arg, 0);
36698c2ecf20Sopenharmony_ci	case TEP_PRINT_STRING:
36708c2ecf20Sopenharmony_ci	case TEP_PRINT_BSTRING:
36718c2ecf20Sopenharmony_ci	case TEP_PRINT_BITMASK:
36728c2ecf20Sopenharmony_ci		return 0;
36738c2ecf20Sopenharmony_ci	case TEP_PRINT_FUNC: {
36748c2ecf20Sopenharmony_ci		struct trace_seq s;
36758c2ecf20Sopenharmony_ci		trace_seq_init(&s);
36768c2ecf20Sopenharmony_ci		val = process_defined_func(&s, data, size, event, arg);
36778c2ecf20Sopenharmony_ci		trace_seq_destroy(&s);
36788c2ecf20Sopenharmony_ci		return val;
36798c2ecf20Sopenharmony_ci	}
36808c2ecf20Sopenharmony_ci	case TEP_PRINT_OP:
36818c2ecf20Sopenharmony_ci		if (strcmp(arg->op.op, "[") == 0) {
36828c2ecf20Sopenharmony_ci			/*
36838c2ecf20Sopenharmony_ci			 * Arrays are special, since we don't want
36848c2ecf20Sopenharmony_ci			 * to read the arg as is.
36858c2ecf20Sopenharmony_ci			 */
36868c2ecf20Sopenharmony_ci			right = eval_num_arg(data, size, event, arg->op.right);
36878c2ecf20Sopenharmony_ci
36888c2ecf20Sopenharmony_ci			/* handle typecasts */
36898c2ecf20Sopenharmony_ci			larg = arg->op.left;
36908c2ecf20Sopenharmony_ci			while (larg->type == TEP_PRINT_TYPE) {
36918c2ecf20Sopenharmony_ci				if (!typearg)
36928c2ecf20Sopenharmony_ci					typearg = larg;
36938c2ecf20Sopenharmony_ci				larg = larg->typecast.item;
36948c2ecf20Sopenharmony_ci			}
36958c2ecf20Sopenharmony_ci
36968c2ecf20Sopenharmony_ci			/* Default to long size */
36978c2ecf20Sopenharmony_ci			field_size = tep->long_size;
36988c2ecf20Sopenharmony_ci
36998c2ecf20Sopenharmony_ci			switch (larg->type) {
37008c2ecf20Sopenharmony_ci			case TEP_PRINT_DYNAMIC_ARRAY:
37018c2ecf20Sopenharmony_ci				offset = tep_read_number(tep,
37028c2ecf20Sopenharmony_ci						   data + larg->dynarray.field->offset,
37038c2ecf20Sopenharmony_ci						   larg->dynarray.field->size);
37048c2ecf20Sopenharmony_ci				if (larg->dynarray.field->elementsize)
37058c2ecf20Sopenharmony_ci					field_size = larg->dynarray.field->elementsize;
37068c2ecf20Sopenharmony_ci				/*
37078c2ecf20Sopenharmony_ci				 * The actual length of the dynamic array is stored
37088c2ecf20Sopenharmony_ci				 * in the top half of the field, and the offset
37098c2ecf20Sopenharmony_ci				 * is in the bottom half of the 32 bit field.
37108c2ecf20Sopenharmony_ci				 */
37118c2ecf20Sopenharmony_ci				offset &= 0xffff;
37128c2ecf20Sopenharmony_ci				offset += right;
37138c2ecf20Sopenharmony_ci				break;
37148c2ecf20Sopenharmony_ci			case TEP_PRINT_FIELD:
37158c2ecf20Sopenharmony_ci				if (!larg->field.field) {
37168c2ecf20Sopenharmony_ci					larg->field.field =
37178c2ecf20Sopenharmony_ci						tep_find_any_field(event, larg->field.name);
37188c2ecf20Sopenharmony_ci					if (!larg->field.field) {
37198c2ecf20Sopenharmony_ci						arg = larg;
37208c2ecf20Sopenharmony_ci						goto out_warning_field;
37218c2ecf20Sopenharmony_ci					}
37228c2ecf20Sopenharmony_ci				}
37238c2ecf20Sopenharmony_ci				field_size = larg->field.field->elementsize;
37248c2ecf20Sopenharmony_ci				offset = larg->field.field->offset +
37258c2ecf20Sopenharmony_ci					right * larg->field.field->elementsize;
37268c2ecf20Sopenharmony_ci				break;
37278c2ecf20Sopenharmony_ci			default:
37288c2ecf20Sopenharmony_ci				goto default_op; /* oops, all bets off */
37298c2ecf20Sopenharmony_ci			}
37308c2ecf20Sopenharmony_ci			val = tep_read_number(tep,
37318c2ecf20Sopenharmony_ci					      data + offset, field_size);
37328c2ecf20Sopenharmony_ci			if (typearg)
37338c2ecf20Sopenharmony_ci				val = eval_type(val, typearg, 1);
37348c2ecf20Sopenharmony_ci			break;
37358c2ecf20Sopenharmony_ci		} else if (strcmp(arg->op.op, "?") == 0) {
37368c2ecf20Sopenharmony_ci			left = eval_num_arg(data, size, event, arg->op.left);
37378c2ecf20Sopenharmony_ci			arg = arg->op.right;
37388c2ecf20Sopenharmony_ci			if (left)
37398c2ecf20Sopenharmony_ci				val = eval_num_arg(data, size, event, arg->op.left);
37408c2ecf20Sopenharmony_ci			else
37418c2ecf20Sopenharmony_ci				val = eval_num_arg(data, size, event, arg->op.right);
37428c2ecf20Sopenharmony_ci			break;
37438c2ecf20Sopenharmony_ci		}
37448c2ecf20Sopenharmony_ci default_op:
37458c2ecf20Sopenharmony_ci		left = eval_num_arg(data, size, event, arg->op.left);
37468c2ecf20Sopenharmony_ci		right = eval_num_arg(data, size, event, arg->op.right);
37478c2ecf20Sopenharmony_ci		switch (arg->op.op[0]) {
37488c2ecf20Sopenharmony_ci		case '!':
37498c2ecf20Sopenharmony_ci			switch (arg->op.op[1]) {
37508c2ecf20Sopenharmony_ci			case 0:
37518c2ecf20Sopenharmony_ci				val = !right;
37528c2ecf20Sopenharmony_ci				break;
37538c2ecf20Sopenharmony_ci			case '=':
37548c2ecf20Sopenharmony_ci				val = left != right;
37558c2ecf20Sopenharmony_ci				break;
37568c2ecf20Sopenharmony_ci			default:
37578c2ecf20Sopenharmony_ci				goto out_warning_op;
37588c2ecf20Sopenharmony_ci			}
37598c2ecf20Sopenharmony_ci			break;
37608c2ecf20Sopenharmony_ci		case '~':
37618c2ecf20Sopenharmony_ci			val = ~right;
37628c2ecf20Sopenharmony_ci			break;
37638c2ecf20Sopenharmony_ci		case '|':
37648c2ecf20Sopenharmony_ci			if (arg->op.op[1])
37658c2ecf20Sopenharmony_ci				val = left || right;
37668c2ecf20Sopenharmony_ci			else
37678c2ecf20Sopenharmony_ci				val = left | right;
37688c2ecf20Sopenharmony_ci			break;
37698c2ecf20Sopenharmony_ci		case '&':
37708c2ecf20Sopenharmony_ci			if (arg->op.op[1])
37718c2ecf20Sopenharmony_ci				val = left && right;
37728c2ecf20Sopenharmony_ci			else
37738c2ecf20Sopenharmony_ci				val = left & right;
37748c2ecf20Sopenharmony_ci			break;
37758c2ecf20Sopenharmony_ci		case '<':
37768c2ecf20Sopenharmony_ci			switch (arg->op.op[1]) {
37778c2ecf20Sopenharmony_ci			case 0:
37788c2ecf20Sopenharmony_ci				val = left < right;
37798c2ecf20Sopenharmony_ci				break;
37808c2ecf20Sopenharmony_ci			case '<':
37818c2ecf20Sopenharmony_ci				val = left << right;
37828c2ecf20Sopenharmony_ci				break;
37838c2ecf20Sopenharmony_ci			case '=':
37848c2ecf20Sopenharmony_ci				val = left <= right;
37858c2ecf20Sopenharmony_ci				break;
37868c2ecf20Sopenharmony_ci			default:
37878c2ecf20Sopenharmony_ci				goto out_warning_op;
37888c2ecf20Sopenharmony_ci			}
37898c2ecf20Sopenharmony_ci			break;
37908c2ecf20Sopenharmony_ci		case '>':
37918c2ecf20Sopenharmony_ci			switch (arg->op.op[1]) {
37928c2ecf20Sopenharmony_ci			case 0:
37938c2ecf20Sopenharmony_ci				val = left > right;
37948c2ecf20Sopenharmony_ci				break;
37958c2ecf20Sopenharmony_ci			case '>':
37968c2ecf20Sopenharmony_ci				val = left >> right;
37978c2ecf20Sopenharmony_ci				break;
37988c2ecf20Sopenharmony_ci			case '=':
37998c2ecf20Sopenharmony_ci				val = left >= right;
38008c2ecf20Sopenharmony_ci				break;
38018c2ecf20Sopenharmony_ci			default:
38028c2ecf20Sopenharmony_ci				goto out_warning_op;
38038c2ecf20Sopenharmony_ci			}
38048c2ecf20Sopenharmony_ci			break;
38058c2ecf20Sopenharmony_ci		case '=':
38068c2ecf20Sopenharmony_ci			if (arg->op.op[1] != '=')
38078c2ecf20Sopenharmony_ci				goto out_warning_op;
38088c2ecf20Sopenharmony_ci
38098c2ecf20Sopenharmony_ci			val = left == right;
38108c2ecf20Sopenharmony_ci			break;
38118c2ecf20Sopenharmony_ci		case '-':
38128c2ecf20Sopenharmony_ci			val = left - right;
38138c2ecf20Sopenharmony_ci			break;
38148c2ecf20Sopenharmony_ci		case '+':
38158c2ecf20Sopenharmony_ci			val = left + right;
38168c2ecf20Sopenharmony_ci			break;
38178c2ecf20Sopenharmony_ci		case '/':
38188c2ecf20Sopenharmony_ci			val = left / right;
38198c2ecf20Sopenharmony_ci			break;
38208c2ecf20Sopenharmony_ci		case '%':
38218c2ecf20Sopenharmony_ci			val = left % right;
38228c2ecf20Sopenharmony_ci			break;
38238c2ecf20Sopenharmony_ci		case '*':
38248c2ecf20Sopenharmony_ci			val = left * right;
38258c2ecf20Sopenharmony_ci			break;
38268c2ecf20Sopenharmony_ci		default:
38278c2ecf20Sopenharmony_ci			goto out_warning_op;
38288c2ecf20Sopenharmony_ci		}
38298c2ecf20Sopenharmony_ci		break;
38308c2ecf20Sopenharmony_ci	case TEP_PRINT_DYNAMIC_ARRAY_LEN:
38318c2ecf20Sopenharmony_ci		offset = tep_read_number(tep,
38328c2ecf20Sopenharmony_ci					 data + arg->dynarray.field->offset,
38338c2ecf20Sopenharmony_ci					 arg->dynarray.field->size);
38348c2ecf20Sopenharmony_ci		/*
38358c2ecf20Sopenharmony_ci		 * The total allocated length of the dynamic array is
38368c2ecf20Sopenharmony_ci		 * stored in the top half of the field, and the offset
38378c2ecf20Sopenharmony_ci		 * is in the bottom half of the 32 bit field.
38388c2ecf20Sopenharmony_ci		 */
38398c2ecf20Sopenharmony_ci		val = (unsigned long long)(offset >> 16);
38408c2ecf20Sopenharmony_ci		break;
38418c2ecf20Sopenharmony_ci	case TEP_PRINT_DYNAMIC_ARRAY:
38428c2ecf20Sopenharmony_ci		/* Without [], we pass the address to the dynamic data */
38438c2ecf20Sopenharmony_ci		offset = tep_read_number(tep,
38448c2ecf20Sopenharmony_ci					 data + arg->dynarray.field->offset,
38458c2ecf20Sopenharmony_ci					 arg->dynarray.field->size);
38468c2ecf20Sopenharmony_ci		/*
38478c2ecf20Sopenharmony_ci		 * The total allocated length of the dynamic array is
38488c2ecf20Sopenharmony_ci		 * stored in the top half of the field, and the offset
38498c2ecf20Sopenharmony_ci		 * is in the bottom half of the 32 bit field.
38508c2ecf20Sopenharmony_ci		 */
38518c2ecf20Sopenharmony_ci		offset &= 0xffff;
38528c2ecf20Sopenharmony_ci		val = (unsigned long long)((unsigned long)data + offset);
38538c2ecf20Sopenharmony_ci		break;
38548c2ecf20Sopenharmony_ci	default: /* not sure what to do there */
38558c2ecf20Sopenharmony_ci		return 0;
38568c2ecf20Sopenharmony_ci	}
38578c2ecf20Sopenharmony_ci	return val;
38588c2ecf20Sopenharmony_ci
38598c2ecf20Sopenharmony_ciout_warning_op:
38608c2ecf20Sopenharmony_ci	do_warning_event(event, "%s: unknown op '%s'", __func__, arg->op.op);
38618c2ecf20Sopenharmony_ci	return 0;
38628c2ecf20Sopenharmony_ci
38638c2ecf20Sopenharmony_ciout_warning_field:
38648c2ecf20Sopenharmony_ci	do_warning_event(event, "%s: field %s not found",
38658c2ecf20Sopenharmony_ci			 __func__, arg->field.name);
38668c2ecf20Sopenharmony_ci	return 0;
38678c2ecf20Sopenharmony_ci}
38688c2ecf20Sopenharmony_ci
38698c2ecf20Sopenharmony_cistruct flag {
38708c2ecf20Sopenharmony_ci	const char *name;
38718c2ecf20Sopenharmony_ci	unsigned long long value;
38728c2ecf20Sopenharmony_ci};
38738c2ecf20Sopenharmony_ci
38748c2ecf20Sopenharmony_cistatic const struct flag flags[] = {
38758c2ecf20Sopenharmony_ci	{ "HI_SOFTIRQ", 0 },
38768c2ecf20Sopenharmony_ci	{ "TIMER_SOFTIRQ", 1 },
38778c2ecf20Sopenharmony_ci	{ "NET_TX_SOFTIRQ", 2 },
38788c2ecf20Sopenharmony_ci	{ "NET_RX_SOFTIRQ", 3 },
38798c2ecf20Sopenharmony_ci	{ "BLOCK_SOFTIRQ", 4 },
38808c2ecf20Sopenharmony_ci	{ "IRQ_POLL_SOFTIRQ", 5 },
38818c2ecf20Sopenharmony_ci	{ "TASKLET_SOFTIRQ", 6 },
38828c2ecf20Sopenharmony_ci	{ "SCHED_SOFTIRQ", 7 },
38838c2ecf20Sopenharmony_ci	{ "HRTIMER_SOFTIRQ", 8 },
38848c2ecf20Sopenharmony_ci	{ "RCU_SOFTIRQ", 9 },
38858c2ecf20Sopenharmony_ci
38868c2ecf20Sopenharmony_ci	{ "HRTIMER_NORESTART", 0 },
38878c2ecf20Sopenharmony_ci	{ "HRTIMER_RESTART", 1 },
38888c2ecf20Sopenharmony_ci};
38898c2ecf20Sopenharmony_ci
38908c2ecf20Sopenharmony_cistatic long long eval_flag(const char *flag)
38918c2ecf20Sopenharmony_ci{
38928c2ecf20Sopenharmony_ci	int i;
38938c2ecf20Sopenharmony_ci
38948c2ecf20Sopenharmony_ci	/*
38958c2ecf20Sopenharmony_ci	 * Some flags in the format files do not get converted.
38968c2ecf20Sopenharmony_ci	 * If the flag is not numeric, see if it is something that
38978c2ecf20Sopenharmony_ci	 * we already know about.
38988c2ecf20Sopenharmony_ci	 */
38998c2ecf20Sopenharmony_ci	if (isdigit(flag[0]))
39008c2ecf20Sopenharmony_ci		return strtoull(flag, NULL, 0);
39018c2ecf20Sopenharmony_ci
39028c2ecf20Sopenharmony_ci	for (i = 0; i < (int)(sizeof(flags)/sizeof(flags[0])); i++)
39038c2ecf20Sopenharmony_ci		if (strcmp(flags[i].name, flag) == 0)
39048c2ecf20Sopenharmony_ci			return flags[i].value;
39058c2ecf20Sopenharmony_ci
39068c2ecf20Sopenharmony_ci	return -1LL;
39078c2ecf20Sopenharmony_ci}
39088c2ecf20Sopenharmony_ci
39098c2ecf20Sopenharmony_cistatic void print_str_to_seq(struct trace_seq *s, const char *format,
39108c2ecf20Sopenharmony_ci			     int len_arg, const char *str)
39118c2ecf20Sopenharmony_ci{
39128c2ecf20Sopenharmony_ci	if (len_arg >= 0)
39138c2ecf20Sopenharmony_ci		trace_seq_printf(s, format, len_arg, str);
39148c2ecf20Sopenharmony_ci	else
39158c2ecf20Sopenharmony_ci		trace_seq_printf(s, format, str);
39168c2ecf20Sopenharmony_ci}
39178c2ecf20Sopenharmony_ci
39188c2ecf20Sopenharmony_cistatic void print_bitmask_to_seq(struct tep_handle *tep,
39198c2ecf20Sopenharmony_ci				 struct trace_seq *s, const char *format,
39208c2ecf20Sopenharmony_ci				 int len_arg, const void *data, int size)
39218c2ecf20Sopenharmony_ci{
39228c2ecf20Sopenharmony_ci	int nr_bits = size * 8;
39238c2ecf20Sopenharmony_ci	int str_size = (nr_bits + 3) / 4;
39248c2ecf20Sopenharmony_ci	int len = 0;
39258c2ecf20Sopenharmony_ci	char buf[3];
39268c2ecf20Sopenharmony_ci	char *str;
39278c2ecf20Sopenharmony_ci	int index;
39288c2ecf20Sopenharmony_ci	int i;
39298c2ecf20Sopenharmony_ci
39308c2ecf20Sopenharmony_ci	/*
39318c2ecf20Sopenharmony_ci	 * The kernel likes to put in commas every 32 bits, we
39328c2ecf20Sopenharmony_ci	 * can do the same.
39338c2ecf20Sopenharmony_ci	 */
39348c2ecf20Sopenharmony_ci	str_size += (nr_bits - 1) / 32;
39358c2ecf20Sopenharmony_ci
39368c2ecf20Sopenharmony_ci	str = malloc(str_size + 1);
39378c2ecf20Sopenharmony_ci	if (!str) {
39388c2ecf20Sopenharmony_ci		do_warning("%s: not enough memory!", __func__);
39398c2ecf20Sopenharmony_ci		return;
39408c2ecf20Sopenharmony_ci	}
39418c2ecf20Sopenharmony_ci	str[str_size] = 0;
39428c2ecf20Sopenharmony_ci
39438c2ecf20Sopenharmony_ci	/* Start out with -2 for the two chars per byte */
39448c2ecf20Sopenharmony_ci	for (i = str_size - 2; i >= 0; i -= 2) {
39458c2ecf20Sopenharmony_ci		/*
39468c2ecf20Sopenharmony_ci		 * data points to a bit mask of size bytes.
39478c2ecf20Sopenharmony_ci		 * In the kernel, this is an array of long words, thus
39488c2ecf20Sopenharmony_ci		 * endianness is very important.
39498c2ecf20Sopenharmony_ci		 */
39508c2ecf20Sopenharmony_ci		if (tep->file_bigendian)
39518c2ecf20Sopenharmony_ci			index = size - (len + 1);
39528c2ecf20Sopenharmony_ci		else
39538c2ecf20Sopenharmony_ci			index = len;
39548c2ecf20Sopenharmony_ci
39558c2ecf20Sopenharmony_ci		snprintf(buf, 3, "%02x", *((unsigned char *)data + index));
39568c2ecf20Sopenharmony_ci		memcpy(str + i, buf, 2);
39578c2ecf20Sopenharmony_ci		len++;
39588c2ecf20Sopenharmony_ci		if (!(len & 3) && i > 0) {
39598c2ecf20Sopenharmony_ci			i--;
39608c2ecf20Sopenharmony_ci			str[i] = ',';
39618c2ecf20Sopenharmony_ci		}
39628c2ecf20Sopenharmony_ci	}
39638c2ecf20Sopenharmony_ci
39648c2ecf20Sopenharmony_ci	if (len_arg >= 0)
39658c2ecf20Sopenharmony_ci		trace_seq_printf(s, format, len_arg, str);
39668c2ecf20Sopenharmony_ci	else
39678c2ecf20Sopenharmony_ci		trace_seq_printf(s, format, str);
39688c2ecf20Sopenharmony_ci
39698c2ecf20Sopenharmony_ci	free(str);
39708c2ecf20Sopenharmony_ci}
39718c2ecf20Sopenharmony_ci
39728c2ecf20Sopenharmony_cistatic void print_str_arg(struct trace_seq *s, void *data, int size,
39738c2ecf20Sopenharmony_ci			  struct tep_event *event, const char *format,
39748c2ecf20Sopenharmony_ci			  int len_arg, struct tep_print_arg *arg)
39758c2ecf20Sopenharmony_ci{
39768c2ecf20Sopenharmony_ci	struct tep_handle *tep = event->tep;
39778c2ecf20Sopenharmony_ci	struct tep_print_flag_sym *flag;
39788c2ecf20Sopenharmony_ci	struct tep_format_field *field;
39798c2ecf20Sopenharmony_ci	struct printk_map *printk;
39808c2ecf20Sopenharmony_ci	long long val, fval;
39818c2ecf20Sopenharmony_ci	unsigned long long addr;
39828c2ecf20Sopenharmony_ci	char *str;
39838c2ecf20Sopenharmony_ci	unsigned char *hex;
39848c2ecf20Sopenharmony_ci	int print;
39858c2ecf20Sopenharmony_ci	int i, len;
39868c2ecf20Sopenharmony_ci
39878c2ecf20Sopenharmony_ci	switch (arg->type) {
39888c2ecf20Sopenharmony_ci	case TEP_PRINT_NULL:
39898c2ecf20Sopenharmony_ci		/* ?? */
39908c2ecf20Sopenharmony_ci		return;
39918c2ecf20Sopenharmony_ci	case TEP_PRINT_ATOM:
39928c2ecf20Sopenharmony_ci		print_str_to_seq(s, format, len_arg, arg->atom.atom);
39938c2ecf20Sopenharmony_ci		return;
39948c2ecf20Sopenharmony_ci	case TEP_PRINT_FIELD:
39958c2ecf20Sopenharmony_ci		field = arg->field.field;
39968c2ecf20Sopenharmony_ci		if (!field) {
39978c2ecf20Sopenharmony_ci			field = tep_find_any_field(event, arg->field.name);
39988c2ecf20Sopenharmony_ci			if (!field) {
39998c2ecf20Sopenharmony_ci				str = arg->field.name;
40008c2ecf20Sopenharmony_ci				goto out_warning_field;
40018c2ecf20Sopenharmony_ci			}
40028c2ecf20Sopenharmony_ci			arg->field.field = field;
40038c2ecf20Sopenharmony_ci		}
40048c2ecf20Sopenharmony_ci		/* Zero sized fields, mean the rest of the data */
40058c2ecf20Sopenharmony_ci		len = field->size ? : size - field->offset;
40068c2ecf20Sopenharmony_ci
40078c2ecf20Sopenharmony_ci		/*
40088c2ecf20Sopenharmony_ci		 * Some events pass in pointers. If this is not an array
40098c2ecf20Sopenharmony_ci		 * and the size is the same as long_size, assume that it
40108c2ecf20Sopenharmony_ci		 * is a pointer.
40118c2ecf20Sopenharmony_ci		 */
40128c2ecf20Sopenharmony_ci		if (!(field->flags & TEP_FIELD_IS_ARRAY) &&
40138c2ecf20Sopenharmony_ci		    field->size == tep->long_size) {
40148c2ecf20Sopenharmony_ci
40158c2ecf20Sopenharmony_ci			/* Handle heterogeneous recording and processing
40168c2ecf20Sopenharmony_ci			 * architectures
40178c2ecf20Sopenharmony_ci			 *
40188c2ecf20Sopenharmony_ci			 * CASE I:
40198c2ecf20Sopenharmony_ci			 * Traces recorded on 32-bit devices (32-bit
40208c2ecf20Sopenharmony_ci			 * addressing) and processed on 64-bit devices:
40218c2ecf20Sopenharmony_ci			 * In this case, only 32 bits should be read.
40228c2ecf20Sopenharmony_ci			 *
40238c2ecf20Sopenharmony_ci			 * CASE II:
40248c2ecf20Sopenharmony_ci			 * Traces recorded on 64 bit devices and processed
40258c2ecf20Sopenharmony_ci			 * on 32-bit devices:
40268c2ecf20Sopenharmony_ci			 * In this case, 64 bits must be read.
40278c2ecf20Sopenharmony_ci			 */
40288c2ecf20Sopenharmony_ci			addr = (tep->long_size == 8) ?
40298c2ecf20Sopenharmony_ci				*(unsigned long long *)(data + field->offset) :
40308c2ecf20Sopenharmony_ci				(unsigned long long)*(unsigned int *)(data + field->offset);
40318c2ecf20Sopenharmony_ci
40328c2ecf20Sopenharmony_ci			/* Check if it matches a print format */
40338c2ecf20Sopenharmony_ci			printk = find_printk(tep, addr);
40348c2ecf20Sopenharmony_ci			if (printk)
40358c2ecf20Sopenharmony_ci				trace_seq_puts(s, printk->printk);
40368c2ecf20Sopenharmony_ci			else
40378c2ecf20Sopenharmony_ci				trace_seq_printf(s, "%llx", addr);
40388c2ecf20Sopenharmony_ci			break;
40398c2ecf20Sopenharmony_ci		}
40408c2ecf20Sopenharmony_ci		str = malloc(len + 1);
40418c2ecf20Sopenharmony_ci		if (!str) {
40428c2ecf20Sopenharmony_ci			do_warning_event(event, "%s: not enough memory!",
40438c2ecf20Sopenharmony_ci					 __func__);
40448c2ecf20Sopenharmony_ci			return;
40458c2ecf20Sopenharmony_ci		}
40468c2ecf20Sopenharmony_ci		memcpy(str, data + field->offset, len);
40478c2ecf20Sopenharmony_ci		str[len] = 0;
40488c2ecf20Sopenharmony_ci		print_str_to_seq(s, format, len_arg, str);
40498c2ecf20Sopenharmony_ci		free(str);
40508c2ecf20Sopenharmony_ci		break;
40518c2ecf20Sopenharmony_ci	case TEP_PRINT_FLAGS:
40528c2ecf20Sopenharmony_ci		val = eval_num_arg(data, size, event, arg->flags.field);
40538c2ecf20Sopenharmony_ci		print = 0;
40548c2ecf20Sopenharmony_ci		for (flag = arg->flags.flags; flag; flag = flag->next) {
40558c2ecf20Sopenharmony_ci			fval = eval_flag(flag->value);
40568c2ecf20Sopenharmony_ci			if (!val && fval < 0) {
40578c2ecf20Sopenharmony_ci				print_str_to_seq(s, format, len_arg, flag->str);
40588c2ecf20Sopenharmony_ci				break;
40598c2ecf20Sopenharmony_ci			}
40608c2ecf20Sopenharmony_ci			if (fval > 0 && (val & fval) == fval) {
40618c2ecf20Sopenharmony_ci				if (print && arg->flags.delim)
40628c2ecf20Sopenharmony_ci					trace_seq_puts(s, arg->flags.delim);
40638c2ecf20Sopenharmony_ci				print_str_to_seq(s, format, len_arg, flag->str);
40648c2ecf20Sopenharmony_ci				print = 1;
40658c2ecf20Sopenharmony_ci				val &= ~fval;
40668c2ecf20Sopenharmony_ci			}
40678c2ecf20Sopenharmony_ci		}
40688c2ecf20Sopenharmony_ci		if (val) {
40698c2ecf20Sopenharmony_ci			if (print && arg->flags.delim)
40708c2ecf20Sopenharmony_ci				trace_seq_puts(s, arg->flags.delim);
40718c2ecf20Sopenharmony_ci			trace_seq_printf(s, "0x%llx", val);
40728c2ecf20Sopenharmony_ci		}
40738c2ecf20Sopenharmony_ci		break;
40748c2ecf20Sopenharmony_ci	case TEP_PRINT_SYMBOL:
40758c2ecf20Sopenharmony_ci		val = eval_num_arg(data, size, event, arg->symbol.field);
40768c2ecf20Sopenharmony_ci		for (flag = arg->symbol.symbols; flag; flag = flag->next) {
40778c2ecf20Sopenharmony_ci			fval = eval_flag(flag->value);
40788c2ecf20Sopenharmony_ci			if (val == fval) {
40798c2ecf20Sopenharmony_ci				print_str_to_seq(s, format, len_arg, flag->str);
40808c2ecf20Sopenharmony_ci				break;
40818c2ecf20Sopenharmony_ci			}
40828c2ecf20Sopenharmony_ci		}
40838c2ecf20Sopenharmony_ci		if (!flag)
40848c2ecf20Sopenharmony_ci			trace_seq_printf(s, "0x%llx", val);
40858c2ecf20Sopenharmony_ci		break;
40868c2ecf20Sopenharmony_ci	case TEP_PRINT_HEX:
40878c2ecf20Sopenharmony_ci	case TEP_PRINT_HEX_STR:
40888c2ecf20Sopenharmony_ci		if (arg->hex.field->type == TEP_PRINT_DYNAMIC_ARRAY) {
40898c2ecf20Sopenharmony_ci			unsigned long offset;
40908c2ecf20Sopenharmony_ci			offset = tep_read_number(tep,
40918c2ecf20Sopenharmony_ci				data + arg->hex.field->dynarray.field->offset,
40928c2ecf20Sopenharmony_ci				arg->hex.field->dynarray.field->size);
40938c2ecf20Sopenharmony_ci			hex = data + (offset & 0xffff);
40948c2ecf20Sopenharmony_ci		} else {
40958c2ecf20Sopenharmony_ci			field = arg->hex.field->field.field;
40968c2ecf20Sopenharmony_ci			if (!field) {
40978c2ecf20Sopenharmony_ci				str = arg->hex.field->field.name;
40988c2ecf20Sopenharmony_ci				field = tep_find_any_field(event, str);
40998c2ecf20Sopenharmony_ci				if (!field)
41008c2ecf20Sopenharmony_ci					goto out_warning_field;
41018c2ecf20Sopenharmony_ci				arg->hex.field->field.field = field;
41028c2ecf20Sopenharmony_ci			}
41038c2ecf20Sopenharmony_ci			hex = data + field->offset;
41048c2ecf20Sopenharmony_ci		}
41058c2ecf20Sopenharmony_ci		len = eval_num_arg(data, size, event, arg->hex.size);
41068c2ecf20Sopenharmony_ci		for (i = 0; i < len; i++) {
41078c2ecf20Sopenharmony_ci			if (i && arg->type == TEP_PRINT_HEX)
41088c2ecf20Sopenharmony_ci				trace_seq_putc(s, ' ');
41098c2ecf20Sopenharmony_ci			trace_seq_printf(s, "%02x", hex[i]);
41108c2ecf20Sopenharmony_ci		}
41118c2ecf20Sopenharmony_ci		break;
41128c2ecf20Sopenharmony_ci
41138c2ecf20Sopenharmony_ci	case TEP_PRINT_INT_ARRAY: {
41148c2ecf20Sopenharmony_ci		void *num;
41158c2ecf20Sopenharmony_ci		int el_size;
41168c2ecf20Sopenharmony_ci
41178c2ecf20Sopenharmony_ci		if (arg->int_array.field->type == TEP_PRINT_DYNAMIC_ARRAY) {
41188c2ecf20Sopenharmony_ci			unsigned long offset;
41198c2ecf20Sopenharmony_ci			struct tep_format_field *field =
41208c2ecf20Sopenharmony_ci				arg->int_array.field->dynarray.field;
41218c2ecf20Sopenharmony_ci			offset = tep_read_number(tep,
41228c2ecf20Sopenharmony_ci						 data + field->offset,
41238c2ecf20Sopenharmony_ci						 field->size);
41248c2ecf20Sopenharmony_ci			num = data + (offset & 0xffff);
41258c2ecf20Sopenharmony_ci		} else {
41268c2ecf20Sopenharmony_ci			field = arg->int_array.field->field.field;
41278c2ecf20Sopenharmony_ci			if (!field) {
41288c2ecf20Sopenharmony_ci				str = arg->int_array.field->field.name;
41298c2ecf20Sopenharmony_ci				field = tep_find_any_field(event, str);
41308c2ecf20Sopenharmony_ci				if (!field)
41318c2ecf20Sopenharmony_ci					goto out_warning_field;
41328c2ecf20Sopenharmony_ci				arg->int_array.field->field.field = field;
41338c2ecf20Sopenharmony_ci			}
41348c2ecf20Sopenharmony_ci			num = data + field->offset;
41358c2ecf20Sopenharmony_ci		}
41368c2ecf20Sopenharmony_ci		len = eval_num_arg(data, size, event, arg->int_array.count);
41378c2ecf20Sopenharmony_ci		el_size = eval_num_arg(data, size, event,
41388c2ecf20Sopenharmony_ci				       arg->int_array.el_size);
41398c2ecf20Sopenharmony_ci		for (i = 0; i < len; i++) {
41408c2ecf20Sopenharmony_ci			if (i)
41418c2ecf20Sopenharmony_ci				trace_seq_putc(s, ' ');
41428c2ecf20Sopenharmony_ci
41438c2ecf20Sopenharmony_ci			if (el_size == 1) {
41448c2ecf20Sopenharmony_ci				trace_seq_printf(s, "%u", *(uint8_t *)num);
41458c2ecf20Sopenharmony_ci			} else if (el_size == 2) {
41468c2ecf20Sopenharmony_ci				trace_seq_printf(s, "%u", *(uint16_t *)num);
41478c2ecf20Sopenharmony_ci			} else if (el_size == 4) {
41488c2ecf20Sopenharmony_ci				trace_seq_printf(s, "%u", *(uint32_t *)num);
41498c2ecf20Sopenharmony_ci			} else if (el_size == 8) {
41508c2ecf20Sopenharmony_ci				trace_seq_printf(s, "%"PRIu64, *(uint64_t *)num);
41518c2ecf20Sopenharmony_ci			} else {
41528c2ecf20Sopenharmony_ci				trace_seq_printf(s, "BAD SIZE:%d 0x%x",
41538c2ecf20Sopenharmony_ci						 el_size, *(uint8_t *)num);
41548c2ecf20Sopenharmony_ci				el_size = 1;
41558c2ecf20Sopenharmony_ci			}
41568c2ecf20Sopenharmony_ci
41578c2ecf20Sopenharmony_ci			num += el_size;
41588c2ecf20Sopenharmony_ci		}
41598c2ecf20Sopenharmony_ci		break;
41608c2ecf20Sopenharmony_ci	}
41618c2ecf20Sopenharmony_ci	case TEP_PRINT_TYPE:
41628c2ecf20Sopenharmony_ci		break;
41638c2ecf20Sopenharmony_ci	case TEP_PRINT_STRING: {
41648c2ecf20Sopenharmony_ci		int str_offset;
41658c2ecf20Sopenharmony_ci
41668c2ecf20Sopenharmony_ci		if (arg->string.offset == -1) {
41678c2ecf20Sopenharmony_ci			struct tep_format_field *f;
41688c2ecf20Sopenharmony_ci
41698c2ecf20Sopenharmony_ci			f = tep_find_any_field(event, arg->string.string);
41708c2ecf20Sopenharmony_ci			arg->string.offset = f->offset;
41718c2ecf20Sopenharmony_ci		}
41728c2ecf20Sopenharmony_ci		str_offset = data2host4(tep, *(unsigned int *)(data + arg->string.offset));
41738c2ecf20Sopenharmony_ci		str_offset &= 0xffff;
41748c2ecf20Sopenharmony_ci		print_str_to_seq(s, format, len_arg, ((char *)data) + str_offset);
41758c2ecf20Sopenharmony_ci		break;
41768c2ecf20Sopenharmony_ci	}
41778c2ecf20Sopenharmony_ci	case TEP_PRINT_BSTRING:
41788c2ecf20Sopenharmony_ci		print_str_to_seq(s, format, len_arg, arg->string.string);
41798c2ecf20Sopenharmony_ci		break;
41808c2ecf20Sopenharmony_ci	case TEP_PRINT_BITMASK: {
41818c2ecf20Sopenharmony_ci		int bitmask_offset;
41828c2ecf20Sopenharmony_ci		int bitmask_size;
41838c2ecf20Sopenharmony_ci
41848c2ecf20Sopenharmony_ci		if (arg->bitmask.offset == -1) {
41858c2ecf20Sopenharmony_ci			struct tep_format_field *f;
41868c2ecf20Sopenharmony_ci
41878c2ecf20Sopenharmony_ci			f = tep_find_any_field(event, arg->bitmask.bitmask);
41888c2ecf20Sopenharmony_ci			arg->bitmask.offset = f->offset;
41898c2ecf20Sopenharmony_ci		}
41908c2ecf20Sopenharmony_ci		bitmask_offset = data2host4(tep, *(unsigned int *)(data + arg->bitmask.offset));
41918c2ecf20Sopenharmony_ci		bitmask_size = bitmask_offset >> 16;
41928c2ecf20Sopenharmony_ci		bitmask_offset &= 0xffff;
41938c2ecf20Sopenharmony_ci		print_bitmask_to_seq(tep, s, format, len_arg,
41948c2ecf20Sopenharmony_ci				     data + bitmask_offset, bitmask_size);
41958c2ecf20Sopenharmony_ci		break;
41968c2ecf20Sopenharmony_ci	}
41978c2ecf20Sopenharmony_ci	case TEP_PRINT_OP:
41988c2ecf20Sopenharmony_ci		/*
41998c2ecf20Sopenharmony_ci		 * The only op for string should be ? :
42008c2ecf20Sopenharmony_ci		 */
42018c2ecf20Sopenharmony_ci		if (arg->op.op[0] != '?')
42028c2ecf20Sopenharmony_ci			return;
42038c2ecf20Sopenharmony_ci		val = eval_num_arg(data, size, event, arg->op.left);
42048c2ecf20Sopenharmony_ci		if (val)
42058c2ecf20Sopenharmony_ci			print_str_arg(s, data, size, event,
42068c2ecf20Sopenharmony_ci				      format, len_arg, arg->op.right->op.left);
42078c2ecf20Sopenharmony_ci		else
42088c2ecf20Sopenharmony_ci			print_str_arg(s, data, size, event,
42098c2ecf20Sopenharmony_ci				      format, len_arg, arg->op.right->op.right);
42108c2ecf20Sopenharmony_ci		break;
42118c2ecf20Sopenharmony_ci	case TEP_PRINT_FUNC:
42128c2ecf20Sopenharmony_ci		process_defined_func(s, data, size, event, arg);
42138c2ecf20Sopenharmony_ci		break;
42148c2ecf20Sopenharmony_ci	default:
42158c2ecf20Sopenharmony_ci		/* well... */
42168c2ecf20Sopenharmony_ci		break;
42178c2ecf20Sopenharmony_ci	}
42188c2ecf20Sopenharmony_ci
42198c2ecf20Sopenharmony_ci	return;
42208c2ecf20Sopenharmony_ci
42218c2ecf20Sopenharmony_ciout_warning_field:
42228c2ecf20Sopenharmony_ci	do_warning_event(event, "%s: field %s not found",
42238c2ecf20Sopenharmony_ci			 __func__, arg->field.name);
42248c2ecf20Sopenharmony_ci}
42258c2ecf20Sopenharmony_ci
42268c2ecf20Sopenharmony_cistatic unsigned long long
42278c2ecf20Sopenharmony_ciprocess_defined_func(struct trace_seq *s, void *data, int size,
42288c2ecf20Sopenharmony_ci		     struct tep_event *event, struct tep_print_arg *arg)
42298c2ecf20Sopenharmony_ci{
42308c2ecf20Sopenharmony_ci	struct tep_function_handler *func_handle = arg->func.func;
42318c2ecf20Sopenharmony_ci	struct func_params *param;
42328c2ecf20Sopenharmony_ci	unsigned long long *args;
42338c2ecf20Sopenharmony_ci	unsigned long long ret;
42348c2ecf20Sopenharmony_ci	struct tep_print_arg *farg;
42358c2ecf20Sopenharmony_ci	struct trace_seq str;
42368c2ecf20Sopenharmony_ci	struct save_str {
42378c2ecf20Sopenharmony_ci		struct save_str *next;
42388c2ecf20Sopenharmony_ci		char *str;
42398c2ecf20Sopenharmony_ci	} *strings = NULL, *string;
42408c2ecf20Sopenharmony_ci	int i;
42418c2ecf20Sopenharmony_ci
42428c2ecf20Sopenharmony_ci	if (!func_handle->nr_args) {
42438c2ecf20Sopenharmony_ci		ret = (*func_handle->func)(s, NULL);
42448c2ecf20Sopenharmony_ci		goto out;
42458c2ecf20Sopenharmony_ci	}
42468c2ecf20Sopenharmony_ci
42478c2ecf20Sopenharmony_ci	farg = arg->func.args;
42488c2ecf20Sopenharmony_ci	param = func_handle->params;
42498c2ecf20Sopenharmony_ci
42508c2ecf20Sopenharmony_ci	ret = ULLONG_MAX;
42518c2ecf20Sopenharmony_ci	args = malloc(sizeof(*args) * func_handle->nr_args);
42528c2ecf20Sopenharmony_ci	if (!args)
42538c2ecf20Sopenharmony_ci		goto out;
42548c2ecf20Sopenharmony_ci
42558c2ecf20Sopenharmony_ci	for (i = 0; i < func_handle->nr_args; i++) {
42568c2ecf20Sopenharmony_ci		switch (param->type) {
42578c2ecf20Sopenharmony_ci		case TEP_FUNC_ARG_INT:
42588c2ecf20Sopenharmony_ci		case TEP_FUNC_ARG_LONG:
42598c2ecf20Sopenharmony_ci		case TEP_FUNC_ARG_PTR:
42608c2ecf20Sopenharmony_ci			args[i] = eval_num_arg(data, size, event, farg);
42618c2ecf20Sopenharmony_ci			break;
42628c2ecf20Sopenharmony_ci		case TEP_FUNC_ARG_STRING:
42638c2ecf20Sopenharmony_ci			trace_seq_init(&str);
42648c2ecf20Sopenharmony_ci			print_str_arg(&str, data, size, event, "%s", -1, farg);
42658c2ecf20Sopenharmony_ci			trace_seq_terminate(&str);
42668c2ecf20Sopenharmony_ci			string = malloc(sizeof(*string));
42678c2ecf20Sopenharmony_ci			if (!string) {
42688c2ecf20Sopenharmony_ci				do_warning_event(event, "%s(%d): malloc str",
42698c2ecf20Sopenharmony_ci						 __func__, __LINE__);
42708c2ecf20Sopenharmony_ci				goto out_free;
42718c2ecf20Sopenharmony_ci			}
42728c2ecf20Sopenharmony_ci			string->next = strings;
42738c2ecf20Sopenharmony_ci			string->str = strdup(str.buffer);
42748c2ecf20Sopenharmony_ci			if (!string->str) {
42758c2ecf20Sopenharmony_ci				free(string);
42768c2ecf20Sopenharmony_ci				do_warning_event(event, "%s(%d): malloc str",
42778c2ecf20Sopenharmony_ci						 __func__, __LINE__);
42788c2ecf20Sopenharmony_ci				goto out_free;
42798c2ecf20Sopenharmony_ci			}
42808c2ecf20Sopenharmony_ci			args[i] = (uintptr_t)string->str;
42818c2ecf20Sopenharmony_ci			strings = string;
42828c2ecf20Sopenharmony_ci			trace_seq_destroy(&str);
42838c2ecf20Sopenharmony_ci			break;
42848c2ecf20Sopenharmony_ci		default:
42858c2ecf20Sopenharmony_ci			/*
42868c2ecf20Sopenharmony_ci			 * Something went totally wrong, this is not
42878c2ecf20Sopenharmony_ci			 * an input error, something in this code broke.
42888c2ecf20Sopenharmony_ci			 */
42898c2ecf20Sopenharmony_ci			do_warning_event(event, "Unexpected end of arguments\n");
42908c2ecf20Sopenharmony_ci			goto out_free;
42918c2ecf20Sopenharmony_ci		}
42928c2ecf20Sopenharmony_ci		farg = farg->next;
42938c2ecf20Sopenharmony_ci		param = param->next;
42948c2ecf20Sopenharmony_ci	}
42958c2ecf20Sopenharmony_ci
42968c2ecf20Sopenharmony_ci	ret = (*func_handle->func)(s, args);
42978c2ecf20Sopenharmony_ciout_free:
42988c2ecf20Sopenharmony_ci	free(args);
42998c2ecf20Sopenharmony_ci	while (strings) {
43008c2ecf20Sopenharmony_ci		string = strings;
43018c2ecf20Sopenharmony_ci		strings = string->next;
43028c2ecf20Sopenharmony_ci		free(string->str);
43038c2ecf20Sopenharmony_ci		free(string);
43048c2ecf20Sopenharmony_ci	}
43058c2ecf20Sopenharmony_ci
43068c2ecf20Sopenharmony_ci out:
43078c2ecf20Sopenharmony_ci	/* TBD : handle return type here */
43088c2ecf20Sopenharmony_ci	return ret;
43098c2ecf20Sopenharmony_ci}
43108c2ecf20Sopenharmony_ci
43118c2ecf20Sopenharmony_cistatic void free_args(struct tep_print_arg *args)
43128c2ecf20Sopenharmony_ci{
43138c2ecf20Sopenharmony_ci	struct tep_print_arg *next;
43148c2ecf20Sopenharmony_ci
43158c2ecf20Sopenharmony_ci	while (args) {
43168c2ecf20Sopenharmony_ci		next = args->next;
43178c2ecf20Sopenharmony_ci
43188c2ecf20Sopenharmony_ci		free_arg(args);
43198c2ecf20Sopenharmony_ci		args = next;
43208c2ecf20Sopenharmony_ci	}
43218c2ecf20Sopenharmony_ci}
43228c2ecf20Sopenharmony_ci
43238c2ecf20Sopenharmony_cistatic struct tep_print_arg *make_bprint_args(char *fmt, void *data, int size, struct tep_event *event)
43248c2ecf20Sopenharmony_ci{
43258c2ecf20Sopenharmony_ci	struct tep_handle *tep = event->tep;
43268c2ecf20Sopenharmony_ci	struct tep_format_field *field, *ip_field;
43278c2ecf20Sopenharmony_ci	struct tep_print_arg *args, *arg, **next;
43288c2ecf20Sopenharmony_ci	unsigned long long ip, val;
43298c2ecf20Sopenharmony_ci	char *ptr;
43308c2ecf20Sopenharmony_ci	void *bptr;
43318c2ecf20Sopenharmony_ci	int vsize = 0;
43328c2ecf20Sopenharmony_ci
43338c2ecf20Sopenharmony_ci	field = tep->bprint_buf_field;
43348c2ecf20Sopenharmony_ci	ip_field = tep->bprint_ip_field;
43358c2ecf20Sopenharmony_ci
43368c2ecf20Sopenharmony_ci	if (!field) {
43378c2ecf20Sopenharmony_ci		field = tep_find_field(event, "buf");
43388c2ecf20Sopenharmony_ci		if (!field) {
43398c2ecf20Sopenharmony_ci			do_warning_event(event, "can't find buffer field for binary printk");
43408c2ecf20Sopenharmony_ci			return NULL;
43418c2ecf20Sopenharmony_ci		}
43428c2ecf20Sopenharmony_ci		ip_field = tep_find_field(event, "ip");
43438c2ecf20Sopenharmony_ci		if (!ip_field) {
43448c2ecf20Sopenharmony_ci			do_warning_event(event, "can't find ip field for binary printk");
43458c2ecf20Sopenharmony_ci			return NULL;
43468c2ecf20Sopenharmony_ci		}
43478c2ecf20Sopenharmony_ci		tep->bprint_buf_field = field;
43488c2ecf20Sopenharmony_ci		tep->bprint_ip_field = ip_field;
43498c2ecf20Sopenharmony_ci	}
43508c2ecf20Sopenharmony_ci
43518c2ecf20Sopenharmony_ci	ip = tep_read_number(tep, data + ip_field->offset, ip_field->size);
43528c2ecf20Sopenharmony_ci
43538c2ecf20Sopenharmony_ci	/*
43548c2ecf20Sopenharmony_ci	 * The first arg is the IP pointer.
43558c2ecf20Sopenharmony_ci	 */
43568c2ecf20Sopenharmony_ci	args = alloc_arg();
43578c2ecf20Sopenharmony_ci	if (!args) {
43588c2ecf20Sopenharmony_ci		do_warning_event(event, "%s(%d): not enough memory!",
43598c2ecf20Sopenharmony_ci				 __func__, __LINE__);
43608c2ecf20Sopenharmony_ci		return NULL;
43618c2ecf20Sopenharmony_ci	}
43628c2ecf20Sopenharmony_ci	arg = args;
43638c2ecf20Sopenharmony_ci	arg->next = NULL;
43648c2ecf20Sopenharmony_ci	next = &arg->next;
43658c2ecf20Sopenharmony_ci
43668c2ecf20Sopenharmony_ci	arg->type = TEP_PRINT_ATOM;
43678c2ecf20Sopenharmony_ci
43688c2ecf20Sopenharmony_ci	if (asprintf(&arg->atom.atom, "%lld", ip) < 0)
43698c2ecf20Sopenharmony_ci		goto out_free;
43708c2ecf20Sopenharmony_ci
43718c2ecf20Sopenharmony_ci	/* skip the first "%ps: " */
43728c2ecf20Sopenharmony_ci	for (ptr = fmt + 5, bptr = data + field->offset;
43738c2ecf20Sopenharmony_ci	     bptr < data + size && *ptr; ptr++) {
43748c2ecf20Sopenharmony_ci		int ls = 0;
43758c2ecf20Sopenharmony_ci
43768c2ecf20Sopenharmony_ci		if (*ptr == '%') {
43778c2ecf20Sopenharmony_ci process_again:
43788c2ecf20Sopenharmony_ci			ptr++;
43798c2ecf20Sopenharmony_ci			switch (*ptr) {
43808c2ecf20Sopenharmony_ci			case '%':
43818c2ecf20Sopenharmony_ci				break;
43828c2ecf20Sopenharmony_ci			case 'l':
43838c2ecf20Sopenharmony_ci				ls++;
43848c2ecf20Sopenharmony_ci				goto process_again;
43858c2ecf20Sopenharmony_ci			case 'L':
43868c2ecf20Sopenharmony_ci				ls = 2;
43878c2ecf20Sopenharmony_ci				goto process_again;
43888c2ecf20Sopenharmony_ci			case '0' ... '9':
43898c2ecf20Sopenharmony_ci				goto process_again;
43908c2ecf20Sopenharmony_ci			case '.':
43918c2ecf20Sopenharmony_ci				goto process_again;
43928c2ecf20Sopenharmony_ci			case 'z':
43938c2ecf20Sopenharmony_ci			case 'Z':
43948c2ecf20Sopenharmony_ci				ls = 1;
43958c2ecf20Sopenharmony_ci				goto process_again;
43968c2ecf20Sopenharmony_ci			case 'p':
43978c2ecf20Sopenharmony_ci				ls = 1;
43988c2ecf20Sopenharmony_ci				if (isalnum(ptr[1])) {
43998c2ecf20Sopenharmony_ci					ptr++;
44008c2ecf20Sopenharmony_ci					/* Check for special pointers */
44018c2ecf20Sopenharmony_ci					switch (*ptr) {
44028c2ecf20Sopenharmony_ci					case 's':
44038c2ecf20Sopenharmony_ci					case 'S':
44048c2ecf20Sopenharmony_ci					case 'x':
44058c2ecf20Sopenharmony_ci						break;
44068c2ecf20Sopenharmony_ci					case 'f':
44078c2ecf20Sopenharmony_ci					case 'F':
44088c2ecf20Sopenharmony_ci						/*
44098c2ecf20Sopenharmony_ci						 * Pre-5.5 kernels use %pf and
44108c2ecf20Sopenharmony_ci						 * %pF for printing symbols
44118c2ecf20Sopenharmony_ci						 * while kernels since 5.5 use
44128c2ecf20Sopenharmony_ci						 * %pfw for fwnodes. So check
44138c2ecf20Sopenharmony_ci						 * %p[fF] isn't followed by 'w'.
44148c2ecf20Sopenharmony_ci						 */
44158c2ecf20Sopenharmony_ci						if (ptr[1] != 'w')
44168c2ecf20Sopenharmony_ci							break;
44178c2ecf20Sopenharmony_ci						/* fall through */
44188c2ecf20Sopenharmony_ci					default:
44198c2ecf20Sopenharmony_ci						/*
44208c2ecf20Sopenharmony_ci						 * Older kernels do not process
44218c2ecf20Sopenharmony_ci						 * dereferenced pointers.
44228c2ecf20Sopenharmony_ci						 * Only process if the pointer
44238c2ecf20Sopenharmony_ci						 * value is a printable.
44248c2ecf20Sopenharmony_ci						 */
44258c2ecf20Sopenharmony_ci						if (isprint(*(char *)bptr))
44268c2ecf20Sopenharmony_ci							goto process_string;
44278c2ecf20Sopenharmony_ci					}
44288c2ecf20Sopenharmony_ci				}
44298c2ecf20Sopenharmony_ci				/* fall through */
44308c2ecf20Sopenharmony_ci			case 'd':
44318c2ecf20Sopenharmony_ci			case 'u':
44328c2ecf20Sopenharmony_ci			case 'i':
44338c2ecf20Sopenharmony_ci			case 'x':
44348c2ecf20Sopenharmony_ci			case 'X':
44358c2ecf20Sopenharmony_ci			case 'o':
44368c2ecf20Sopenharmony_ci				switch (ls) {
44378c2ecf20Sopenharmony_ci				case 0:
44388c2ecf20Sopenharmony_ci					vsize = 4;
44398c2ecf20Sopenharmony_ci					break;
44408c2ecf20Sopenharmony_ci				case 1:
44418c2ecf20Sopenharmony_ci					vsize = tep->long_size;
44428c2ecf20Sopenharmony_ci					break;
44438c2ecf20Sopenharmony_ci				case 2:
44448c2ecf20Sopenharmony_ci					vsize = 8;
44458c2ecf20Sopenharmony_ci					break;
44468c2ecf20Sopenharmony_ci				default:
44478c2ecf20Sopenharmony_ci					vsize = ls; /* ? */
44488c2ecf20Sopenharmony_ci					break;
44498c2ecf20Sopenharmony_ci				}
44508c2ecf20Sopenharmony_ci			/* fall through */
44518c2ecf20Sopenharmony_ci			case '*':
44528c2ecf20Sopenharmony_ci				if (*ptr == '*')
44538c2ecf20Sopenharmony_ci					vsize = 4;
44548c2ecf20Sopenharmony_ci
44558c2ecf20Sopenharmony_ci				/* the pointers are always 4 bytes aligned */
44568c2ecf20Sopenharmony_ci				bptr = (void *)(((unsigned long)bptr + 3) &
44578c2ecf20Sopenharmony_ci						~3);
44588c2ecf20Sopenharmony_ci				val = tep_read_number(tep, bptr, vsize);
44598c2ecf20Sopenharmony_ci				bptr += vsize;
44608c2ecf20Sopenharmony_ci				arg = alloc_arg();
44618c2ecf20Sopenharmony_ci				if (!arg) {
44628c2ecf20Sopenharmony_ci					do_warning_event(event, "%s(%d): not enough memory!",
44638c2ecf20Sopenharmony_ci						   __func__, __LINE__);
44648c2ecf20Sopenharmony_ci					goto out_free;
44658c2ecf20Sopenharmony_ci				}
44668c2ecf20Sopenharmony_ci				arg->next = NULL;
44678c2ecf20Sopenharmony_ci				arg->type = TEP_PRINT_ATOM;
44688c2ecf20Sopenharmony_ci				if (asprintf(&arg->atom.atom, "%lld", val) < 0) {
44698c2ecf20Sopenharmony_ci					free(arg);
44708c2ecf20Sopenharmony_ci					goto out_free;
44718c2ecf20Sopenharmony_ci				}
44728c2ecf20Sopenharmony_ci				*next = arg;
44738c2ecf20Sopenharmony_ci				next = &arg->next;
44748c2ecf20Sopenharmony_ci				/*
44758c2ecf20Sopenharmony_ci				 * The '*' case means that an arg is used as the length.
44768c2ecf20Sopenharmony_ci				 * We need to continue to figure out for what.
44778c2ecf20Sopenharmony_ci				 */
44788c2ecf20Sopenharmony_ci				if (*ptr == '*')
44798c2ecf20Sopenharmony_ci					goto process_again;
44808c2ecf20Sopenharmony_ci
44818c2ecf20Sopenharmony_ci				break;
44828c2ecf20Sopenharmony_ci			case 's':
44838c2ecf20Sopenharmony_ci process_string:
44848c2ecf20Sopenharmony_ci				arg = alloc_arg();
44858c2ecf20Sopenharmony_ci				if (!arg) {
44868c2ecf20Sopenharmony_ci					do_warning_event(event, "%s(%d): not enough memory!",
44878c2ecf20Sopenharmony_ci						   __func__, __LINE__);
44888c2ecf20Sopenharmony_ci					goto out_free;
44898c2ecf20Sopenharmony_ci				}
44908c2ecf20Sopenharmony_ci				arg->next = NULL;
44918c2ecf20Sopenharmony_ci				arg->type = TEP_PRINT_BSTRING;
44928c2ecf20Sopenharmony_ci				arg->string.string = strdup(bptr);
44938c2ecf20Sopenharmony_ci				if (!arg->string.string)
44948c2ecf20Sopenharmony_ci					goto out_free;
44958c2ecf20Sopenharmony_ci				bptr += strlen(bptr) + 1;
44968c2ecf20Sopenharmony_ci				*next = arg;
44978c2ecf20Sopenharmony_ci				next = &arg->next;
44988c2ecf20Sopenharmony_ci			default:
44998c2ecf20Sopenharmony_ci				break;
45008c2ecf20Sopenharmony_ci			}
45018c2ecf20Sopenharmony_ci		}
45028c2ecf20Sopenharmony_ci	}
45038c2ecf20Sopenharmony_ci
45048c2ecf20Sopenharmony_ci	return args;
45058c2ecf20Sopenharmony_ci
45068c2ecf20Sopenharmony_ciout_free:
45078c2ecf20Sopenharmony_ci	free_args(args);
45088c2ecf20Sopenharmony_ci	return NULL;
45098c2ecf20Sopenharmony_ci}
45108c2ecf20Sopenharmony_ci
45118c2ecf20Sopenharmony_cistatic char *
45128c2ecf20Sopenharmony_ciget_bprint_format(void *data, int size __maybe_unused,
45138c2ecf20Sopenharmony_ci		  struct tep_event *event)
45148c2ecf20Sopenharmony_ci{
45158c2ecf20Sopenharmony_ci	struct tep_handle *tep = event->tep;
45168c2ecf20Sopenharmony_ci	unsigned long long addr;
45178c2ecf20Sopenharmony_ci	struct tep_format_field *field;
45188c2ecf20Sopenharmony_ci	struct printk_map *printk;
45198c2ecf20Sopenharmony_ci	char *format;
45208c2ecf20Sopenharmony_ci
45218c2ecf20Sopenharmony_ci	field = tep->bprint_fmt_field;
45228c2ecf20Sopenharmony_ci
45238c2ecf20Sopenharmony_ci	if (!field) {
45248c2ecf20Sopenharmony_ci		field = tep_find_field(event, "fmt");
45258c2ecf20Sopenharmony_ci		if (!field) {
45268c2ecf20Sopenharmony_ci			do_warning_event(event, "can't find format field for binary printk");
45278c2ecf20Sopenharmony_ci			return NULL;
45288c2ecf20Sopenharmony_ci		}
45298c2ecf20Sopenharmony_ci		tep->bprint_fmt_field = field;
45308c2ecf20Sopenharmony_ci	}
45318c2ecf20Sopenharmony_ci
45328c2ecf20Sopenharmony_ci	addr = tep_read_number(tep, data + field->offset, field->size);
45338c2ecf20Sopenharmony_ci
45348c2ecf20Sopenharmony_ci	printk = find_printk(tep, addr);
45358c2ecf20Sopenharmony_ci	if (!printk) {
45368c2ecf20Sopenharmony_ci		if (asprintf(&format, "%%ps: (NO FORMAT FOUND at %llx)\n", addr) < 0)
45378c2ecf20Sopenharmony_ci			return NULL;
45388c2ecf20Sopenharmony_ci		return format;
45398c2ecf20Sopenharmony_ci	}
45408c2ecf20Sopenharmony_ci
45418c2ecf20Sopenharmony_ci	if (asprintf(&format, "%s: %s", "%ps", printk->printk) < 0)
45428c2ecf20Sopenharmony_ci		return NULL;
45438c2ecf20Sopenharmony_ci
45448c2ecf20Sopenharmony_ci	return format;
45458c2ecf20Sopenharmony_ci}
45468c2ecf20Sopenharmony_ci
45478c2ecf20Sopenharmony_cistatic int print_mac_arg(struct trace_seq *s, const char *format,
45488c2ecf20Sopenharmony_ci			 void *data, int size, struct tep_event *event,
45498c2ecf20Sopenharmony_ci			 struct tep_print_arg *arg)
45508c2ecf20Sopenharmony_ci{
45518c2ecf20Sopenharmony_ci	const char *fmt = "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x";
45528c2ecf20Sopenharmony_ci	bool reverse = false;
45538c2ecf20Sopenharmony_ci	unsigned char *buf;
45548c2ecf20Sopenharmony_ci	int ret = 0;
45558c2ecf20Sopenharmony_ci
45568c2ecf20Sopenharmony_ci	if (arg->type == TEP_PRINT_FUNC) {
45578c2ecf20Sopenharmony_ci		process_defined_func(s, data, size, event, arg);
45588c2ecf20Sopenharmony_ci		return 0;
45598c2ecf20Sopenharmony_ci	}
45608c2ecf20Sopenharmony_ci
45618c2ecf20Sopenharmony_ci	if (arg->type != TEP_PRINT_FIELD) {
45628c2ecf20Sopenharmony_ci		trace_seq_printf(s, "ARG TYPE NOT FIELD BUT %d",
45638c2ecf20Sopenharmony_ci				 arg->type);
45648c2ecf20Sopenharmony_ci		return 0;
45658c2ecf20Sopenharmony_ci	}
45668c2ecf20Sopenharmony_ci
45678c2ecf20Sopenharmony_ci	if (format[0] == 'm') {
45688c2ecf20Sopenharmony_ci		fmt = "%.2x%.2x%.2x%.2x%.2x%.2x";
45698c2ecf20Sopenharmony_ci	} else if (format[0] == 'M' && format[1] == 'F') {
45708c2ecf20Sopenharmony_ci		fmt = "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x";
45718c2ecf20Sopenharmony_ci		ret++;
45728c2ecf20Sopenharmony_ci	}
45738c2ecf20Sopenharmony_ci	if (format[1] == 'R') {
45748c2ecf20Sopenharmony_ci		reverse = true;
45758c2ecf20Sopenharmony_ci		ret++;
45768c2ecf20Sopenharmony_ci	}
45778c2ecf20Sopenharmony_ci
45788c2ecf20Sopenharmony_ci	if (!arg->field.field) {
45798c2ecf20Sopenharmony_ci		arg->field.field =
45808c2ecf20Sopenharmony_ci			tep_find_any_field(event, arg->field.name);
45818c2ecf20Sopenharmony_ci		if (!arg->field.field) {
45828c2ecf20Sopenharmony_ci			do_warning_event(event, "%s: field %s not found",
45838c2ecf20Sopenharmony_ci					 __func__, arg->field.name);
45848c2ecf20Sopenharmony_ci			return ret;
45858c2ecf20Sopenharmony_ci		}
45868c2ecf20Sopenharmony_ci	}
45878c2ecf20Sopenharmony_ci	if (arg->field.field->size != 6) {
45888c2ecf20Sopenharmony_ci		trace_seq_printf(s, "INVALIDMAC");
45898c2ecf20Sopenharmony_ci		return ret;
45908c2ecf20Sopenharmony_ci	}
45918c2ecf20Sopenharmony_ci
45928c2ecf20Sopenharmony_ci	buf = data + arg->field.field->offset;
45938c2ecf20Sopenharmony_ci	if (reverse)
45948c2ecf20Sopenharmony_ci		trace_seq_printf(s, fmt, buf[5], buf[4], buf[3], buf[2], buf[1], buf[0]);
45958c2ecf20Sopenharmony_ci	else
45968c2ecf20Sopenharmony_ci		trace_seq_printf(s, fmt, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
45978c2ecf20Sopenharmony_ci
45988c2ecf20Sopenharmony_ci	return ret;
45998c2ecf20Sopenharmony_ci}
46008c2ecf20Sopenharmony_ci
46018c2ecf20Sopenharmony_cistatic int parse_ip4_print_args(struct tep_handle *tep,
46028c2ecf20Sopenharmony_ci				const char *ptr, bool *reverse)
46038c2ecf20Sopenharmony_ci{
46048c2ecf20Sopenharmony_ci	int ret = 0;
46058c2ecf20Sopenharmony_ci
46068c2ecf20Sopenharmony_ci	*reverse = false;
46078c2ecf20Sopenharmony_ci
46088c2ecf20Sopenharmony_ci	/* hnbl */
46098c2ecf20Sopenharmony_ci	switch (*ptr) {
46108c2ecf20Sopenharmony_ci	case 'h':
46118c2ecf20Sopenharmony_ci		if (tep->file_bigendian)
46128c2ecf20Sopenharmony_ci			*reverse = false;
46138c2ecf20Sopenharmony_ci		else
46148c2ecf20Sopenharmony_ci			*reverse = true;
46158c2ecf20Sopenharmony_ci		ret++;
46168c2ecf20Sopenharmony_ci		break;
46178c2ecf20Sopenharmony_ci	case 'l':
46188c2ecf20Sopenharmony_ci		*reverse = true;
46198c2ecf20Sopenharmony_ci		ret++;
46208c2ecf20Sopenharmony_ci		break;
46218c2ecf20Sopenharmony_ci	case 'n':
46228c2ecf20Sopenharmony_ci	case 'b':
46238c2ecf20Sopenharmony_ci		ret++;
46248c2ecf20Sopenharmony_ci		/* fall through */
46258c2ecf20Sopenharmony_ci	default:
46268c2ecf20Sopenharmony_ci		*reverse = false;
46278c2ecf20Sopenharmony_ci		break;
46288c2ecf20Sopenharmony_ci	}
46298c2ecf20Sopenharmony_ci
46308c2ecf20Sopenharmony_ci	return ret;
46318c2ecf20Sopenharmony_ci}
46328c2ecf20Sopenharmony_ci
46338c2ecf20Sopenharmony_cistatic void print_ip4_addr(struct trace_seq *s, char i, bool reverse, unsigned char *buf)
46348c2ecf20Sopenharmony_ci{
46358c2ecf20Sopenharmony_ci	const char *fmt;
46368c2ecf20Sopenharmony_ci
46378c2ecf20Sopenharmony_ci	if (i == 'i')
46388c2ecf20Sopenharmony_ci		fmt = "%03d.%03d.%03d.%03d";
46398c2ecf20Sopenharmony_ci	else
46408c2ecf20Sopenharmony_ci		fmt = "%d.%d.%d.%d";
46418c2ecf20Sopenharmony_ci
46428c2ecf20Sopenharmony_ci	if (reverse)
46438c2ecf20Sopenharmony_ci		trace_seq_printf(s, fmt, buf[3], buf[2], buf[1], buf[0]);
46448c2ecf20Sopenharmony_ci	else
46458c2ecf20Sopenharmony_ci		trace_seq_printf(s, fmt, buf[0], buf[1], buf[2], buf[3]);
46468c2ecf20Sopenharmony_ci
46478c2ecf20Sopenharmony_ci}
46488c2ecf20Sopenharmony_ci
46498c2ecf20Sopenharmony_cistatic inline bool ipv6_addr_v4mapped(const struct in6_addr *a)
46508c2ecf20Sopenharmony_ci{
46518c2ecf20Sopenharmony_ci	return ((unsigned long)(a->s6_addr32[0] | a->s6_addr32[1]) |
46528c2ecf20Sopenharmony_ci		(unsigned long)(a->s6_addr32[2] ^ htonl(0x0000ffff))) == 0UL;
46538c2ecf20Sopenharmony_ci}
46548c2ecf20Sopenharmony_ci
46558c2ecf20Sopenharmony_cistatic inline bool ipv6_addr_is_isatap(const struct in6_addr *addr)
46568c2ecf20Sopenharmony_ci{
46578c2ecf20Sopenharmony_ci	return (addr->s6_addr32[2] | htonl(0x02000000)) == htonl(0x02005EFE);
46588c2ecf20Sopenharmony_ci}
46598c2ecf20Sopenharmony_ci
46608c2ecf20Sopenharmony_cistatic void print_ip6c_addr(struct trace_seq *s, unsigned char *addr)
46618c2ecf20Sopenharmony_ci{
46628c2ecf20Sopenharmony_ci	int i, j, range;
46638c2ecf20Sopenharmony_ci	unsigned char zerolength[8];
46648c2ecf20Sopenharmony_ci	int longest = 1;
46658c2ecf20Sopenharmony_ci	int colonpos = -1;
46668c2ecf20Sopenharmony_ci	uint16_t word;
46678c2ecf20Sopenharmony_ci	uint8_t hi, lo;
46688c2ecf20Sopenharmony_ci	bool needcolon = false;
46698c2ecf20Sopenharmony_ci	bool useIPv4;
46708c2ecf20Sopenharmony_ci	struct in6_addr in6;
46718c2ecf20Sopenharmony_ci
46728c2ecf20Sopenharmony_ci	memcpy(&in6, addr, sizeof(struct in6_addr));
46738c2ecf20Sopenharmony_ci
46748c2ecf20Sopenharmony_ci	useIPv4 = ipv6_addr_v4mapped(&in6) || ipv6_addr_is_isatap(&in6);
46758c2ecf20Sopenharmony_ci
46768c2ecf20Sopenharmony_ci	memset(zerolength, 0, sizeof(zerolength));
46778c2ecf20Sopenharmony_ci
46788c2ecf20Sopenharmony_ci	if (useIPv4)
46798c2ecf20Sopenharmony_ci		range = 6;
46808c2ecf20Sopenharmony_ci	else
46818c2ecf20Sopenharmony_ci		range = 8;
46828c2ecf20Sopenharmony_ci
46838c2ecf20Sopenharmony_ci	/* find position of longest 0 run */
46848c2ecf20Sopenharmony_ci	for (i = 0; i < range; i++) {
46858c2ecf20Sopenharmony_ci		for (j = i; j < range; j++) {
46868c2ecf20Sopenharmony_ci			if (in6.s6_addr16[j] != 0)
46878c2ecf20Sopenharmony_ci				break;
46888c2ecf20Sopenharmony_ci			zerolength[i]++;
46898c2ecf20Sopenharmony_ci		}
46908c2ecf20Sopenharmony_ci	}
46918c2ecf20Sopenharmony_ci	for (i = 0; i < range; i++) {
46928c2ecf20Sopenharmony_ci		if (zerolength[i] > longest) {
46938c2ecf20Sopenharmony_ci			longest = zerolength[i];
46948c2ecf20Sopenharmony_ci			colonpos = i;
46958c2ecf20Sopenharmony_ci		}
46968c2ecf20Sopenharmony_ci	}
46978c2ecf20Sopenharmony_ci	if (longest == 1)		/* don't compress a single 0 */
46988c2ecf20Sopenharmony_ci		colonpos = -1;
46998c2ecf20Sopenharmony_ci
47008c2ecf20Sopenharmony_ci	/* emit address */
47018c2ecf20Sopenharmony_ci	for (i = 0; i < range; i++) {
47028c2ecf20Sopenharmony_ci		if (i == colonpos) {
47038c2ecf20Sopenharmony_ci			if (needcolon || i == 0)
47048c2ecf20Sopenharmony_ci				trace_seq_printf(s, ":");
47058c2ecf20Sopenharmony_ci			trace_seq_printf(s, ":");
47068c2ecf20Sopenharmony_ci			needcolon = false;
47078c2ecf20Sopenharmony_ci			i += longest - 1;
47088c2ecf20Sopenharmony_ci			continue;
47098c2ecf20Sopenharmony_ci		}
47108c2ecf20Sopenharmony_ci		if (needcolon) {
47118c2ecf20Sopenharmony_ci			trace_seq_printf(s, ":");
47128c2ecf20Sopenharmony_ci			needcolon = false;
47138c2ecf20Sopenharmony_ci		}
47148c2ecf20Sopenharmony_ci		/* hex u16 without leading 0s */
47158c2ecf20Sopenharmony_ci		word = ntohs(in6.s6_addr16[i]);
47168c2ecf20Sopenharmony_ci		hi = word >> 8;
47178c2ecf20Sopenharmony_ci		lo = word & 0xff;
47188c2ecf20Sopenharmony_ci		if (hi)
47198c2ecf20Sopenharmony_ci			trace_seq_printf(s, "%x%02x", hi, lo);
47208c2ecf20Sopenharmony_ci		else
47218c2ecf20Sopenharmony_ci			trace_seq_printf(s, "%x", lo);
47228c2ecf20Sopenharmony_ci
47238c2ecf20Sopenharmony_ci		needcolon = true;
47248c2ecf20Sopenharmony_ci	}
47258c2ecf20Sopenharmony_ci
47268c2ecf20Sopenharmony_ci	if (useIPv4) {
47278c2ecf20Sopenharmony_ci		if (needcolon)
47288c2ecf20Sopenharmony_ci			trace_seq_printf(s, ":");
47298c2ecf20Sopenharmony_ci		print_ip4_addr(s, 'I', false, &in6.s6_addr[12]);
47308c2ecf20Sopenharmony_ci	}
47318c2ecf20Sopenharmony_ci
47328c2ecf20Sopenharmony_ci	return;
47338c2ecf20Sopenharmony_ci}
47348c2ecf20Sopenharmony_ci
47358c2ecf20Sopenharmony_cistatic void print_ip6_addr(struct trace_seq *s, char i, unsigned char *buf)
47368c2ecf20Sopenharmony_ci{
47378c2ecf20Sopenharmony_ci	int j;
47388c2ecf20Sopenharmony_ci
47398c2ecf20Sopenharmony_ci	for (j = 0; j < 16; j += 2) {
47408c2ecf20Sopenharmony_ci		trace_seq_printf(s, "%02x%02x", buf[j], buf[j+1]);
47418c2ecf20Sopenharmony_ci		if (i == 'I' && j < 14)
47428c2ecf20Sopenharmony_ci			trace_seq_printf(s, ":");
47438c2ecf20Sopenharmony_ci	}
47448c2ecf20Sopenharmony_ci}
47458c2ecf20Sopenharmony_ci
47468c2ecf20Sopenharmony_ci/*
47478c2ecf20Sopenharmony_ci * %pi4   print an IPv4 address with leading zeros
47488c2ecf20Sopenharmony_ci * %pI4   print an IPv4 address without leading zeros
47498c2ecf20Sopenharmony_ci * %pi6   print an IPv6 address without colons
47508c2ecf20Sopenharmony_ci * %pI6   print an IPv6 address with colons
47518c2ecf20Sopenharmony_ci * %pI6c  print an IPv6 address in compressed form with colons
47528c2ecf20Sopenharmony_ci * %pISpc print an IP address based on sockaddr; p adds port.
47538c2ecf20Sopenharmony_ci */
47548c2ecf20Sopenharmony_cistatic int print_ipv4_arg(struct trace_seq *s, const char *ptr, char i,
47558c2ecf20Sopenharmony_ci			  void *data, int size, struct tep_event *event,
47568c2ecf20Sopenharmony_ci			  struct tep_print_arg *arg)
47578c2ecf20Sopenharmony_ci{
47588c2ecf20Sopenharmony_ci	bool reverse = false;
47598c2ecf20Sopenharmony_ci	unsigned char *buf;
47608c2ecf20Sopenharmony_ci	int ret;
47618c2ecf20Sopenharmony_ci
47628c2ecf20Sopenharmony_ci	ret = parse_ip4_print_args(event->tep, ptr, &reverse);
47638c2ecf20Sopenharmony_ci
47648c2ecf20Sopenharmony_ci	if (arg->type == TEP_PRINT_FUNC) {
47658c2ecf20Sopenharmony_ci		process_defined_func(s, data, size, event, arg);
47668c2ecf20Sopenharmony_ci		return ret;
47678c2ecf20Sopenharmony_ci	}
47688c2ecf20Sopenharmony_ci
47698c2ecf20Sopenharmony_ci	if (arg->type != TEP_PRINT_FIELD) {
47708c2ecf20Sopenharmony_ci		trace_seq_printf(s, "ARG TYPE NOT FIELD BUT %d", arg->type);
47718c2ecf20Sopenharmony_ci		return ret;
47728c2ecf20Sopenharmony_ci	}
47738c2ecf20Sopenharmony_ci
47748c2ecf20Sopenharmony_ci	if (!arg->field.field) {
47758c2ecf20Sopenharmony_ci		arg->field.field =
47768c2ecf20Sopenharmony_ci			tep_find_any_field(event, arg->field.name);
47778c2ecf20Sopenharmony_ci		if (!arg->field.field) {
47788c2ecf20Sopenharmony_ci			do_warning("%s: field %s not found",
47798c2ecf20Sopenharmony_ci				   __func__, arg->field.name);
47808c2ecf20Sopenharmony_ci			return ret;
47818c2ecf20Sopenharmony_ci		}
47828c2ecf20Sopenharmony_ci	}
47838c2ecf20Sopenharmony_ci
47848c2ecf20Sopenharmony_ci	buf = data + arg->field.field->offset;
47858c2ecf20Sopenharmony_ci
47868c2ecf20Sopenharmony_ci	if (arg->field.field->size != 4) {
47878c2ecf20Sopenharmony_ci		trace_seq_printf(s, "INVALIDIPv4");
47888c2ecf20Sopenharmony_ci		return ret;
47898c2ecf20Sopenharmony_ci	}
47908c2ecf20Sopenharmony_ci
47918c2ecf20Sopenharmony_ci	print_ip4_addr(s, i, reverse, buf);
47928c2ecf20Sopenharmony_ci	return ret;
47938c2ecf20Sopenharmony_ci
47948c2ecf20Sopenharmony_ci}
47958c2ecf20Sopenharmony_ci
47968c2ecf20Sopenharmony_cistatic int print_ipv6_arg(struct trace_seq *s, const char *ptr, char i,
47978c2ecf20Sopenharmony_ci			  void *data, int size, struct tep_event *event,
47988c2ecf20Sopenharmony_ci			  struct tep_print_arg *arg)
47998c2ecf20Sopenharmony_ci{
48008c2ecf20Sopenharmony_ci	char have_c = 0;
48018c2ecf20Sopenharmony_ci	unsigned char *buf;
48028c2ecf20Sopenharmony_ci	int rc = 0;
48038c2ecf20Sopenharmony_ci
48048c2ecf20Sopenharmony_ci	/* pI6c */
48058c2ecf20Sopenharmony_ci	if (i == 'I' && *ptr == 'c') {
48068c2ecf20Sopenharmony_ci		have_c = 1;
48078c2ecf20Sopenharmony_ci		ptr++;
48088c2ecf20Sopenharmony_ci		rc++;
48098c2ecf20Sopenharmony_ci	}
48108c2ecf20Sopenharmony_ci
48118c2ecf20Sopenharmony_ci	if (arg->type == TEP_PRINT_FUNC) {
48128c2ecf20Sopenharmony_ci		process_defined_func(s, data, size, event, arg);
48138c2ecf20Sopenharmony_ci		return rc;
48148c2ecf20Sopenharmony_ci	}
48158c2ecf20Sopenharmony_ci
48168c2ecf20Sopenharmony_ci	if (arg->type != TEP_PRINT_FIELD) {
48178c2ecf20Sopenharmony_ci		trace_seq_printf(s, "ARG TYPE NOT FIELD BUT %d", arg->type);
48188c2ecf20Sopenharmony_ci		return rc;
48198c2ecf20Sopenharmony_ci	}
48208c2ecf20Sopenharmony_ci
48218c2ecf20Sopenharmony_ci	if (!arg->field.field) {
48228c2ecf20Sopenharmony_ci		arg->field.field =
48238c2ecf20Sopenharmony_ci			tep_find_any_field(event, arg->field.name);
48248c2ecf20Sopenharmony_ci		if (!arg->field.field) {
48258c2ecf20Sopenharmony_ci			do_warning("%s: field %s not found",
48268c2ecf20Sopenharmony_ci				   __func__, arg->field.name);
48278c2ecf20Sopenharmony_ci			return rc;
48288c2ecf20Sopenharmony_ci		}
48298c2ecf20Sopenharmony_ci	}
48308c2ecf20Sopenharmony_ci
48318c2ecf20Sopenharmony_ci	buf = data + arg->field.field->offset;
48328c2ecf20Sopenharmony_ci
48338c2ecf20Sopenharmony_ci	if (arg->field.field->size != 16) {
48348c2ecf20Sopenharmony_ci		trace_seq_printf(s, "INVALIDIPv6");
48358c2ecf20Sopenharmony_ci		return rc;
48368c2ecf20Sopenharmony_ci	}
48378c2ecf20Sopenharmony_ci
48388c2ecf20Sopenharmony_ci	if (have_c)
48398c2ecf20Sopenharmony_ci		print_ip6c_addr(s, buf);
48408c2ecf20Sopenharmony_ci	else
48418c2ecf20Sopenharmony_ci		print_ip6_addr(s, i, buf);
48428c2ecf20Sopenharmony_ci
48438c2ecf20Sopenharmony_ci	return rc;
48448c2ecf20Sopenharmony_ci}
48458c2ecf20Sopenharmony_ci
48468c2ecf20Sopenharmony_cistatic int print_ipsa_arg(struct trace_seq *s, const char *ptr, char i,
48478c2ecf20Sopenharmony_ci			  void *data, int size, struct tep_event *event,
48488c2ecf20Sopenharmony_ci			  struct tep_print_arg *arg)
48498c2ecf20Sopenharmony_ci{
48508c2ecf20Sopenharmony_ci	char have_c = 0, have_p = 0;
48518c2ecf20Sopenharmony_ci	unsigned char *buf;
48528c2ecf20Sopenharmony_ci	struct sockaddr_storage *sa;
48538c2ecf20Sopenharmony_ci	bool reverse = false;
48548c2ecf20Sopenharmony_ci	int rc = 0;
48558c2ecf20Sopenharmony_ci	int ret;
48568c2ecf20Sopenharmony_ci
48578c2ecf20Sopenharmony_ci	/* pISpc */
48588c2ecf20Sopenharmony_ci	if (i == 'I') {
48598c2ecf20Sopenharmony_ci		if (*ptr == 'p') {
48608c2ecf20Sopenharmony_ci			have_p = 1;
48618c2ecf20Sopenharmony_ci			ptr++;
48628c2ecf20Sopenharmony_ci			rc++;
48638c2ecf20Sopenharmony_ci		}
48648c2ecf20Sopenharmony_ci		if (*ptr == 'c') {
48658c2ecf20Sopenharmony_ci			have_c = 1;
48668c2ecf20Sopenharmony_ci			ptr++;
48678c2ecf20Sopenharmony_ci			rc++;
48688c2ecf20Sopenharmony_ci		}
48698c2ecf20Sopenharmony_ci	}
48708c2ecf20Sopenharmony_ci	ret = parse_ip4_print_args(event->tep, ptr, &reverse);
48718c2ecf20Sopenharmony_ci	ptr += ret;
48728c2ecf20Sopenharmony_ci	rc += ret;
48738c2ecf20Sopenharmony_ci
48748c2ecf20Sopenharmony_ci	if (arg->type == TEP_PRINT_FUNC) {
48758c2ecf20Sopenharmony_ci		process_defined_func(s, data, size, event, arg);
48768c2ecf20Sopenharmony_ci		return rc;
48778c2ecf20Sopenharmony_ci	}
48788c2ecf20Sopenharmony_ci
48798c2ecf20Sopenharmony_ci	if (arg->type != TEP_PRINT_FIELD) {
48808c2ecf20Sopenharmony_ci		trace_seq_printf(s, "ARG TYPE NOT FIELD BUT %d", arg->type);
48818c2ecf20Sopenharmony_ci		return rc;
48828c2ecf20Sopenharmony_ci	}
48838c2ecf20Sopenharmony_ci
48848c2ecf20Sopenharmony_ci	if (!arg->field.field) {
48858c2ecf20Sopenharmony_ci		arg->field.field =
48868c2ecf20Sopenharmony_ci			tep_find_any_field(event, arg->field.name);
48878c2ecf20Sopenharmony_ci		if (!arg->field.field) {
48888c2ecf20Sopenharmony_ci			do_warning("%s: field %s not found",
48898c2ecf20Sopenharmony_ci				   __func__, arg->field.name);
48908c2ecf20Sopenharmony_ci			return rc;
48918c2ecf20Sopenharmony_ci		}
48928c2ecf20Sopenharmony_ci	}
48938c2ecf20Sopenharmony_ci
48948c2ecf20Sopenharmony_ci	sa = (struct sockaddr_storage *) (data + arg->field.field->offset);
48958c2ecf20Sopenharmony_ci
48968c2ecf20Sopenharmony_ci	if (sa->ss_family == AF_INET) {
48978c2ecf20Sopenharmony_ci		struct sockaddr_in *sa4 = (struct sockaddr_in *) sa;
48988c2ecf20Sopenharmony_ci
48998c2ecf20Sopenharmony_ci		if (arg->field.field->size < sizeof(struct sockaddr_in)) {
49008c2ecf20Sopenharmony_ci			trace_seq_printf(s, "INVALIDIPv4");
49018c2ecf20Sopenharmony_ci			return rc;
49028c2ecf20Sopenharmony_ci		}
49038c2ecf20Sopenharmony_ci
49048c2ecf20Sopenharmony_ci		print_ip4_addr(s, i, reverse, (unsigned char *) &sa4->sin_addr);
49058c2ecf20Sopenharmony_ci		if (have_p)
49068c2ecf20Sopenharmony_ci			trace_seq_printf(s, ":%d", ntohs(sa4->sin_port));
49078c2ecf20Sopenharmony_ci
49088c2ecf20Sopenharmony_ci
49098c2ecf20Sopenharmony_ci	} else if (sa->ss_family == AF_INET6) {
49108c2ecf20Sopenharmony_ci		struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) sa;
49118c2ecf20Sopenharmony_ci
49128c2ecf20Sopenharmony_ci		if (arg->field.field->size < sizeof(struct sockaddr_in6)) {
49138c2ecf20Sopenharmony_ci			trace_seq_printf(s, "INVALIDIPv6");
49148c2ecf20Sopenharmony_ci			return rc;
49158c2ecf20Sopenharmony_ci		}
49168c2ecf20Sopenharmony_ci
49178c2ecf20Sopenharmony_ci		if (have_p)
49188c2ecf20Sopenharmony_ci			trace_seq_printf(s, "[");
49198c2ecf20Sopenharmony_ci
49208c2ecf20Sopenharmony_ci		buf = (unsigned char *) &sa6->sin6_addr;
49218c2ecf20Sopenharmony_ci		if (have_c)
49228c2ecf20Sopenharmony_ci			print_ip6c_addr(s, buf);
49238c2ecf20Sopenharmony_ci		else
49248c2ecf20Sopenharmony_ci			print_ip6_addr(s, i, buf);
49258c2ecf20Sopenharmony_ci
49268c2ecf20Sopenharmony_ci		if (have_p)
49278c2ecf20Sopenharmony_ci			trace_seq_printf(s, "]:%d", ntohs(sa6->sin6_port));
49288c2ecf20Sopenharmony_ci	}
49298c2ecf20Sopenharmony_ci
49308c2ecf20Sopenharmony_ci	return rc;
49318c2ecf20Sopenharmony_ci}
49328c2ecf20Sopenharmony_ci
49338c2ecf20Sopenharmony_cistatic int print_ip_arg(struct trace_seq *s, const char *ptr,
49348c2ecf20Sopenharmony_ci			void *data, int size, struct tep_event *event,
49358c2ecf20Sopenharmony_ci			struct tep_print_arg *arg)
49368c2ecf20Sopenharmony_ci{
49378c2ecf20Sopenharmony_ci	char i = *ptr;  /* 'i' or 'I' */
49388c2ecf20Sopenharmony_ci	int rc = 1;
49398c2ecf20Sopenharmony_ci
49408c2ecf20Sopenharmony_ci	/* IP version */
49418c2ecf20Sopenharmony_ci	ptr++;
49428c2ecf20Sopenharmony_ci
49438c2ecf20Sopenharmony_ci	switch (*ptr) {
49448c2ecf20Sopenharmony_ci	case '4':
49458c2ecf20Sopenharmony_ci		rc += print_ipv4_arg(s, ptr + 1, i, data, size, event, arg);
49468c2ecf20Sopenharmony_ci		break;
49478c2ecf20Sopenharmony_ci	case '6':
49488c2ecf20Sopenharmony_ci		rc += print_ipv6_arg(s, ptr + 1, i, data, size, event, arg);
49498c2ecf20Sopenharmony_ci		break;
49508c2ecf20Sopenharmony_ci	case 'S':
49518c2ecf20Sopenharmony_ci		rc += print_ipsa_arg(s, ptr + 1, i, data, size, event, arg);
49528c2ecf20Sopenharmony_ci		break;
49538c2ecf20Sopenharmony_ci	default:
49548c2ecf20Sopenharmony_ci		return 0;
49558c2ecf20Sopenharmony_ci	}
49568c2ecf20Sopenharmony_ci
49578c2ecf20Sopenharmony_ci	return rc;
49588c2ecf20Sopenharmony_ci}
49598c2ecf20Sopenharmony_ci
49608c2ecf20Sopenharmony_cistatic const int guid_index[16] = {3, 2, 1, 0, 5, 4, 7, 6, 8, 9, 10, 11, 12, 13, 14, 15};
49618c2ecf20Sopenharmony_cistatic const int uuid_index[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
49628c2ecf20Sopenharmony_ci
49638c2ecf20Sopenharmony_cistatic int print_uuid_arg(struct trace_seq *s, const char *ptr,
49648c2ecf20Sopenharmony_ci			void *data, int size, struct tep_event *event,
49658c2ecf20Sopenharmony_ci			struct tep_print_arg *arg)
49668c2ecf20Sopenharmony_ci{
49678c2ecf20Sopenharmony_ci	const int *index = uuid_index;
49688c2ecf20Sopenharmony_ci	char *format = "%02x";
49698c2ecf20Sopenharmony_ci	int ret = 0;
49708c2ecf20Sopenharmony_ci	char *buf;
49718c2ecf20Sopenharmony_ci	int i;
49728c2ecf20Sopenharmony_ci
49738c2ecf20Sopenharmony_ci	switch (*(ptr + 1)) {
49748c2ecf20Sopenharmony_ci	case 'L':
49758c2ecf20Sopenharmony_ci		format = "%02X";
49768c2ecf20Sopenharmony_ci		/* fall through */
49778c2ecf20Sopenharmony_ci	case 'l':
49788c2ecf20Sopenharmony_ci		index = guid_index;
49798c2ecf20Sopenharmony_ci		ret++;
49808c2ecf20Sopenharmony_ci		break;
49818c2ecf20Sopenharmony_ci	case 'B':
49828c2ecf20Sopenharmony_ci		format = "%02X";
49838c2ecf20Sopenharmony_ci		/* fall through */
49848c2ecf20Sopenharmony_ci	case 'b':
49858c2ecf20Sopenharmony_ci		ret++;
49868c2ecf20Sopenharmony_ci		break;
49878c2ecf20Sopenharmony_ci	}
49888c2ecf20Sopenharmony_ci
49898c2ecf20Sopenharmony_ci	if (arg->type == TEP_PRINT_FUNC) {
49908c2ecf20Sopenharmony_ci		process_defined_func(s, data, size, event, arg);
49918c2ecf20Sopenharmony_ci		return ret;
49928c2ecf20Sopenharmony_ci	}
49938c2ecf20Sopenharmony_ci
49948c2ecf20Sopenharmony_ci	if (arg->type != TEP_PRINT_FIELD) {
49958c2ecf20Sopenharmony_ci		trace_seq_printf(s, "ARG TYPE NOT FIELD BUT %d", arg->type);
49968c2ecf20Sopenharmony_ci		return ret;
49978c2ecf20Sopenharmony_ci	}
49988c2ecf20Sopenharmony_ci
49998c2ecf20Sopenharmony_ci	if (!arg->field.field) {
50008c2ecf20Sopenharmony_ci		arg->field.field =
50018c2ecf20Sopenharmony_ci			tep_find_any_field(event, arg->field.name);
50028c2ecf20Sopenharmony_ci		if (!arg->field.field) {
50038c2ecf20Sopenharmony_ci			do_warning("%s: field %s not found",
50048c2ecf20Sopenharmony_ci				   __func__, arg->field.name);
50058c2ecf20Sopenharmony_ci			return ret;
50068c2ecf20Sopenharmony_ci		}
50078c2ecf20Sopenharmony_ci	}
50088c2ecf20Sopenharmony_ci
50098c2ecf20Sopenharmony_ci	if (arg->field.field->size != 16) {
50108c2ecf20Sopenharmony_ci		trace_seq_printf(s, "INVALIDUUID");
50118c2ecf20Sopenharmony_ci		return ret;
50128c2ecf20Sopenharmony_ci	}
50138c2ecf20Sopenharmony_ci
50148c2ecf20Sopenharmony_ci	buf = data + arg->field.field->offset;
50158c2ecf20Sopenharmony_ci
50168c2ecf20Sopenharmony_ci	for (i = 0; i < 16; i++) {
50178c2ecf20Sopenharmony_ci		trace_seq_printf(s, format, buf[index[i]] & 0xff);
50188c2ecf20Sopenharmony_ci		switch (i) {
50198c2ecf20Sopenharmony_ci		case 3:
50208c2ecf20Sopenharmony_ci		case 5:
50218c2ecf20Sopenharmony_ci		case 7:
50228c2ecf20Sopenharmony_ci		case 9:
50238c2ecf20Sopenharmony_ci			trace_seq_printf(s, "-");
50248c2ecf20Sopenharmony_ci			break;
50258c2ecf20Sopenharmony_ci		}
50268c2ecf20Sopenharmony_ci	}
50278c2ecf20Sopenharmony_ci
50288c2ecf20Sopenharmony_ci	return ret;
50298c2ecf20Sopenharmony_ci}
50308c2ecf20Sopenharmony_ci
50318c2ecf20Sopenharmony_cistatic int print_raw_buff_arg(struct trace_seq *s, const char *ptr,
50328c2ecf20Sopenharmony_ci			      void *data, int size, struct tep_event *event,
50338c2ecf20Sopenharmony_ci			      struct tep_print_arg *arg, int print_len)
50348c2ecf20Sopenharmony_ci{
50358c2ecf20Sopenharmony_ci	int plen = print_len;
50368c2ecf20Sopenharmony_ci	char *delim = " ";
50378c2ecf20Sopenharmony_ci	int ret = 0;
50388c2ecf20Sopenharmony_ci	char *buf;
50398c2ecf20Sopenharmony_ci	int i;
50408c2ecf20Sopenharmony_ci	unsigned long offset;
50418c2ecf20Sopenharmony_ci	int arr_len;
50428c2ecf20Sopenharmony_ci
50438c2ecf20Sopenharmony_ci	switch (*(ptr + 1)) {
50448c2ecf20Sopenharmony_ci	case 'C':
50458c2ecf20Sopenharmony_ci		delim = ":";
50468c2ecf20Sopenharmony_ci		ret++;
50478c2ecf20Sopenharmony_ci		break;
50488c2ecf20Sopenharmony_ci	case 'D':
50498c2ecf20Sopenharmony_ci		delim = "-";
50508c2ecf20Sopenharmony_ci		ret++;
50518c2ecf20Sopenharmony_ci		break;
50528c2ecf20Sopenharmony_ci	case 'N':
50538c2ecf20Sopenharmony_ci		delim = "";
50548c2ecf20Sopenharmony_ci		ret++;
50558c2ecf20Sopenharmony_ci		break;
50568c2ecf20Sopenharmony_ci	}
50578c2ecf20Sopenharmony_ci
50588c2ecf20Sopenharmony_ci	if (arg->type == TEP_PRINT_FUNC) {
50598c2ecf20Sopenharmony_ci		process_defined_func(s, data, size, event, arg);
50608c2ecf20Sopenharmony_ci		return ret;
50618c2ecf20Sopenharmony_ci	}
50628c2ecf20Sopenharmony_ci
50638c2ecf20Sopenharmony_ci	if (arg->type != TEP_PRINT_DYNAMIC_ARRAY) {
50648c2ecf20Sopenharmony_ci		trace_seq_printf(s, "ARG TYPE NOT FIELD BUT %d", arg->type);
50658c2ecf20Sopenharmony_ci		return ret;
50668c2ecf20Sopenharmony_ci	}
50678c2ecf20Sopenharmony_ci
50688c2ecf20Sopenharmony_ci	offset = tep_read_number(event->tep,
50698c2ecf20Sopenharmony_ci				 data + arg->dynarray.field->offset,
50708c2ecf20Sopenharmony_ci				 arg->dynarray.field->size);
50718c2ecf20Sopenharmony_ci	arr_len = (unsigned long long)(offset >> 16);
50728c2ecf20Sopenharmony_ci	buf = data + (offset & 0xffff);
50738c2ecf20Sopenharmony_ci
50748c2ecf20Sopenharmony_ci	if (arr_len < plen)
50758c2ecf20Sopenharmony_ci		plen = arr_len;
50768c2ecf20Sopenharmony_ci
50778c2ecf20Sopenharmony_ci	if (plen < 1)
50788c2ecf20Sopenharmony_ci		return ret;
50798c2ecf20Sopenharmony_ci
50808c2ecf20Sopenharmony_ci	trace_seq_printf(s, "%02x", buf[0] & 0xff);
50818c2ecf20Sopenharmony_ci	for (i = 1; i < plen; i++)
50828c2ecf20Sopenharmony_ci		trace_seq_printf(s, "%s%02x", delim, buf[i] & 0xff);
50838c2ecf20Sopenharmony_ci
50848c2ecf20Sopenharmony_ci	return ret;
50858c2ecf20Sopenharmony_ci}
50868c2ecf20Sopenharmony_ci
50878c2ecf20Sopenharmony_cistatic int is_printable_array(char *p, unsigned int len)
50888c2ecf20Sopenharmony_ci{
50898c2ecf20Sopenharmony_ci	unsigned int i;
50908c2ecf20Sopenharmony_ci
50918c2ecf20Sopenharmony_ci	for (i = 0; i < len && p[i]; i++)
50928c2ecf20Sopenharmony_ci		if (!isprint(p[i]) && !isspace(p[i]))
50938c2ecf20Sopenharmony_ci		    return 0;
50948c2ecf20Sopenharmony_ci	return 1;
50958c2ecf20Sopenharmony_ci}
50968c2ecf20Sopenharmony_ci
50978c2ecf20Sopenharmony_civoid tep_print_field(struct trace_seq *s, void *data,
50988c2ecf20Sopenharmony_ci		     struct tep_format_field *field)
50998c2ecf20Sopenharmony_ci{
51008c2ecf20Sopenharmony_ci	unsigned long long val;
51018c2ecf20Sopenharmony_ci	unsigned int offset, len, i;
51028c2ecf20Sopenharmony_ci	struct tep_handle *tep = field->event->tep;
51038c2ecf20Sopenharmony_ci
51048c2ecf20Sopenharmony_ci	if (field->flags & TEP_FIELD_IS_ARRAY) {
51058c2ecf20Sopenharmony_ci		offset = field->offset;
51068c2ecf20Sopenharmony_ci		len = field->size;
51078c2ecf20Sopenharmony_ci		if (field->flags & TEP_FIELD_IS_DYNAMIC) {
51088c2ecf20Sopenharmony_ci			val = tep_read_number(tep, data + offset, len);
51098c2ecf20Sopenharmony_ci			offset = val;
51108c2ecf20Sopenharmony_ci			len = offset >> 16;
51118c2ecf20Sopenharmony_ci			offset &= 0xffff;
51128c2ecf20Sopenharmony_ci		}
51138c2ecf20Sopenharmony_ci		if (field->flags & TEP_FIELD_IS_STRING &&
51148c2ecf20Sopenharmony_ci		    is_printable_array(data + offset, len)) {
51158c2ecf20Sopenharmony_ci			trace_seq_printf(s, "%s", (char *)data + offset);
51168c2ecf20Sopenharmony_ci		} else {
51178c2ecf20Sopenharmony_ci			trace_seq_puts(s, "ARRAY[");
51188c2ecf20Sopenharmony_ci			for (i = 0; i < len; i++) {
51198c2ecf20Sopenharmony_ci				if (i)
51208c2ecf20Sopenharmony_ci					trace_seq_puts(s, ", ");
51218c2ecf20Sopenharmony_ci				trace_seq_printf(s, "%02x",
51228c2ecf20Sopenharmony_ci						 *((unsigned char *)data + offset + i));
51238c2ecf20Sopenharmony_ci			}
51248c2ecf20Sopenharmony_ci			trace_seq_putc(s, ']');
51258c2ecf20Sopenharmony_ci			field->flags &= ~TEP_FIELD_IS_STRING;
51268c2ecf20Sopenharmony_ci		}
51278c2ecf20Sopenharmony_ci	} else {
51288c2ecf20Sopenharmony_ci		val = tep_read_number(tep, data + field->offset,
51298c2ecf20Sopenharmony_ci				      field->size);
51308c2ecf20Sopenharmony_ci		if (field->flags & TEP_FIELD_IS_POINTER) {
51318c2ecf20Sopenharmony_ci			trace_seq_printf(s, "0x%llx", val);
51328c2ecf20Sopenharmony_ci		} else if (field->flags & TEP_FIELD_IS_SIGNED) {
51338c2ecf20Sopenharmony_ci			switch (field->size) {
51348c2ecf20Sopenharmony_ci			case 4:
51358c2ecf20Sopenharmony_ci				/*
51368c2ecf20Sopenharmony_ci				 * If field is long then print it in hex.
51378c2ecf20Sopenharmony_ci				 * A long usually stores pointers.
51388c2ecf20Sopenharmony_ci				 */
51398c2ecf20Sopenharmony_ci				if (field->flags & TEP_FIELD_IS_LONG)
51408c2ecf20Sopenharmony_ci					trace_seq_printf(s, "0x%x", (int)val);
51418c2ecf20Sopenharmony_ci				else
51428c2ecf20Sopenharmony_ci					trace_seq_printf(s, "%d", (int)val);
51438c2ecf20Sopenharmony_ci				break;
51448c2ecf20Sopenharmony_ci			case 2:
51458c2ecf20Sopenharmony_ci				trace_seq_printf(s, "%2d", (short)val);
51468c2ecf20Sopenharmony_ci				break;
51478c2ecf20Sopenharmony_ci			case 1:
51488c2ecf20Sopenharmony_ci				trace_seq_printf(s, "%1d", (char)val);
51498c2ecf20Sopenharmony_ci				break;
51508c2ecf20Sopenharmony_ci			default:
51518c2ecf20Sopenharmony_ci				trace_seq_printf(s, "%lld", val);
51528c2ecf20Sopenharmony_ci			}
51538c2ecf20Sopenharmony_ci		} else {
51548c2ecf20Sopenharmony_ci			if (field->flags & TEP_FIELD_IS_LONG)
51558c2ecf20Sopenharmony_ci				trace_seq_printf(s, "0x%llx", val);
51568c2ecf20Sopenharmony_ci			else
51578c2ecf20Sopenharmony_ci				trace_seq_printf(s, "%llu", val);
51588c2ecf20Sopenharmony_ci		}
51598c2ecf20Sopenharmony_ci	}
51608c2ecf20Sopenharmony_ci}
51618c2ecf20Sopenharmony_ci
51628c2ecf20Sopenharmony_civoid tep_print_fields(struct trace_seq *s, void *data,
51638c2ecf20Sopenharmony_ci		      int size __maybe_unused, struct tep_event *event)
51648c2ecf20Sopenharmony_ci{
51658c2ecf20Sopenharmony_ci	struct tep_format_field *field;
51668c2ecf20Sopenharmony_ci
51678c2ecf20Sopenharmony_ci	field = event->format.fields;
51688c2ecf20Sopenharmony_ci	while (field) {
51698c2ecf20Sopenharmony_ci		trace_seq_printf(s, " %s=", field->name);
51708c2ecf20Sopenharmony_ci		tep_print_field(s, data, field);
51718c2ecf20Sopenharmony_ci		field = field->next;
51728c2ecf20Sopenharmony_ci	}
51738c2ecf20Sopenharmony_ci}
51748c2ecf20Sopenharmony_ci
51758c2ecf20Sopenharmony_cistatic int print_function(struct trace_seq *s, const char *format,
51768c2ecf20Sopenharmony_ci			  void *data, int size, struct tep_event *event,
51778c2ecf20Sopenharmony_ci			  struct tep_print_arg *arg)
51788c2ecf20Sopenharmony_ci{
51798c2ecf20Sopenharmony_ci	struct func_map *func;
51808c2ecf20Sopenharmony_ci	unsigned long long val;
51818c2ecf20Sopenharmony_ci
51828c2ecf20Sopenharmony_ci	val = eval_num_arg(data, size, event, arg);
51838c2ecf20Sopenharmony_ci	func = find_func(event->tep, val);
51848c2ecf20Sopenharmony_ci	if (func) {
51858c2ecf20Sopenharmony_ci		trace_seq_puts(s, func->func);
51868c2ecf20Sopenharmony_ci		if (*format == 'F' || *format == 'S')
51878c2ecf20Sopenharmony_ci			trace_seq_printf(s, "+0x%llx", val - func->addr);
51888c2ecf20Sopenharmony_ci	} else {
51898c2ecf20Sopenharmony_ci		if (event->tep->long_size == 4)
51908c2ecf20Sopenharmony_ci			trace_seq_printf(s, "0x%lx", (long)val);
51918c2ecf20Sopenharmony_ci		else
51928c2ecf20Sopenharmony_ci			trace_seq_printf(s, "0x%llx", (long long)val);
51938c2ecf20Sopenharmony_ci	}
51948c2ecf20Sopenharmony_ci
51958c2ecf20Sopenharmony_ci	return 0;
51968c2ecf20Sopenharmony_ci}
51978c2ecf20Sopenharmony_ci
51988c2ecf20Sopenharmony_cistatic int print_arg_pointer(struct trace_seq *s, const char *format, int plen,
51998c2ecf20Sopenharmony_ci			     void *data, int size,
52008c2ecf20Sopenharmony_ci			     struct tep_event *event, struct tep_print_arg *arg)
52018c2ecf20Sopenharmony_ci{
52028c2ecf20Sopenharmony_ci	unsigned long long val;
52038c2ecf20Sopenharmony_ci	int ret = 1;
52048c2ecf20Sopenharmony_ci
52058c2ecf20Sopenharmony_ci	if (arg->type == TEP_PRINT_BSTRING) {
52068c2ecf20Sopenharmony_ci		trace_seq_puts(s, arg->string.string);
52078c2ecf20Sopenharmony_ci		return 0;
52088c2ecf20Sopenharmony_ci	}
52098c2ecf20Sopenharmony_ci	while (*format) {
52108c2ecf20Sopenharmony_ci		if (*format == 'p') {
52118c2ecf20Sopenharmony_ci			format++;
52128c2ecf20Sopenharmony_ci			break;
52138c2ecf20Sopenharmony_ci		}
52148c2ecf20Sopenharmony_ci		format++;
52158c2ecf20Sopenharmony_ci	}
52168c2ecf20Sopenharmony_ci
52178c2ecf20Sopenharmony_ci	switch (*format) {
52188c2ecf20Sopenharmony_ci	case 'F':
52198c2ecf20Sopenharmony_ci	case 'f':
52208c2ecf20Sopenharmony_ci	case 'S':
52218c2ecf20Sopenharmony_ci	case 's':
52228c2ecf20Sopenharmony_ci		ret += print_function(s, format, data, size, event, arg);
52238c2ecf20Sopenharmony_ci		break;
52248c2ecf20Sopenharmony_ci	case 'M':
52258c2ecf20Sopenharmony_ci	case 'm':
52268c2ecf20Sopenharmony_ci		ret += print_mac_arg(s, format, data, size, event, arg);
52278c2ecf20Sopenharmony_ci		break;
52288c2ecf20Sopenharmony_ci	case 'I':
52298c2ecf20Sopenharmony_ci	case 'i':
52308c2ecf20Sopenharmony_ci		ret += print_ip_arg(s, format, data, size, event, arg);
52318c2ecf20Sopenharmony_ci		break;
52328c2ecf20Sopenharmony_ci	case 'U':
52338c2ecf20Sopenharmony_ci		ret += print_uuid_arg(s, format, data, size, event, arg);
52348c2ecf20Sopenharmony_ci		break;
52358c2ecf20Sopenharmony_ci	case 'h':
52368c2ecf20Sopenharmony_ci		ret += print_raw_buff_arg(s, format, data, size, event, arg, plen);
52378c2ecf20Sopenharmony_ci		break;
52388c2ecf20Sopenharmony_ci	default:
52398c2ecf20Sopenharmony_ci		ret = 0;
52408c2ecf20Sopenharmony_ci		val = eval_num_arg(data, size, event, arg);
52418c2ecf20Sopenharmony_ci		trace_seq_printf(s, "%p", (void *)(intptr_t)val);
52428c2ecf20Sopenharmony_ci		break;
52438c2ecf20Sopenharmony_ci	}
52448c2ecf20Sopenharmony_ci
52458c2ecf20Sopenharmony_ci	return ret;
52468c2ecf20Sopenharmony_ci
52478c2ecf20Sopenharmony_ci}
52488c2ecf20Sopenharmony_ci
52498c2ecf20Sopenharmony_cistatic int print_arg_number(struct trace_seq *s, const char *format, int plen,
52508c2ecf20Sopenharmony_ci			    void *data, int size, int ls,
52518c2ecf20Sopenharmony_ci			    struct tep_event *event, struct tep_print_arg *arg)
52528c2ecf20Sopenharmony_ci{
52538c2ecf20Sopenharmony_ci	unsigned long long val;
52548c2ecf20Sopenharmony_ci
52558c2ecf20Sopenharmony_ci	val = eval_num_arg(data, size, event, arg);
52568c2ecf20Sopenharmony_ci
52578c2ecf20Sopenharmony_ci	switch (ls) {
52588c2ecf20Sopenharmony_ci	case -2:
52598c2ecf20Sopenharmony_ci		if (plen >= 0)
52608c2ecf20Sopenharmony_ci			trace_seq_printf(s, format, plen, (char)val);
52618c2ecf20Sopenharmony_ci		else
52628c2ecf20Sopenharmony_ci			trace_seq_printf(s, format, (char)val);
52638c2ecf20Sopenharmony_ci		break;
52648c2ecf20Sopenharmony_ci	case -1:
52658c2ecf20Sopenharmony_ci		if (plen >= 0)
52668c2ecf20Sopenharmony_ci			trace_seq_printf(s, format, plen, (short)val);
52678c2ecf20Sopenharmony_ci		else
52688c2ecf20Sopenharmony_ci			trace_seq_printf(s, format, (short)val);
52698c2ecf20Sopenharmony_ci		break;
52708c2ecf20Sopenharmony_ci	case 0:
52718c2ecf20Sopenharmony_ci		if (plen >= 0)
52728c2ecf20Sopenharmony_ci			trace_seq_printf(s, format, plen, (int)val);
52738c2ecf20Sopenharmony_ci		else
52748c2ecf20Sopenharmony_ci			trace_seq_printf(s, format, (int)val);
52758c2ecf20Sopenharmony_ci		break;
52768c2ecf20Sopenharmony_ci	case 1:
52778c2ecf20Sopenharmony_ci		if (plen >= 0)
52788c2ecf20Sopenharmony_ci			trace_seq_printf(s, format, plen, (long)val);
52798c2ecf20Sopenharmony_ci		else
52808c2ecf20Sopenharmony_ci			trace_seq_printf(s, format, (long)val);
52818c2ecf20Sopenharmony_ci		break;
52828c2ecf20Sopenharmony_ci	case 2:
52838c2ecf20Sopenharmony_ci		if (plen >= 0)
52848c2ecf20Sopenharmony_ci			trace_seq_printf(s, format, plen, (long long)val);
52858c2ecf20Sopenharmony_ci		else
52868c2ecf20Sopenharmony_ci			trace_seq_printf(s, format, (long long)val);
52878c2ecf20Sopenharmony_ci		break;
52888c2ecf20Sopenharmony_ci	default:
52898c2ecf20Sopenharmony_ci		do_warning_event(event, "bad count (%d)", ls);
52908c2ecf20Sopenharmony_ci		event->flags |= TEP_EVENT_FL_FAILED;
52918c2ecf20Sopenharmony_ci	}
52928c2ecf20Sopenharmony_ci	return 0;
52938c2ecf20Sopenharmony_ci}
52948c2ecf20Sopenharmony_ci
52958c2ecf20Sopenharmony_ci
52968c2ecf20Sopenharmony_cistatic void print_arg_string(struct trace_seq *s, const char *format, int plen,
52978c2ecf20Sopenharmony_ci			     void *data, int size,
52988c2ecf20Sopenharmony_ci			     struct tep_event *event, struct tep_print_arg *arg)
52998c2ecf20Sopenharmony_ci{
53008c2ecf20Sopenharmony_ci	struct trace_seq p;
53018c2ecf20Sopenharmony_ci
53028c2ecf20Sopenharmony_ci	/* Use helper trace_seq */
53038c2ecf20Sopenharmony_ci	trace_seq_init(&p);
53048c2ecf20Sopenharmony_ci	print_str_arg(&p, data, size, event,
53058c2ecf20Sopenharmony_ci		      format, plen, arg);
53068c2ecf20Sopenharmony_ci	trace_seq_terminate(&p);
53078c2ecf20Sopenharmony_ci	trace_seq_puts(s, p.buffer);
53088c2ecf20Sopenharmony_ci	trace_seq_destroy(&p);
53098c2ecf20Sopenharmony_ci}
53108c2ecf20Sopenharmony_ci
53118c2ecf20Sopenharmony_cistatic int parse_arg_format_pointer(const char *format)
53128c2ecf20Sopenharmony_ci{
53138c2ecf20Sopenharmony_ci	int ret = 0;
53148c2ecf20Sopenharmony_ci	int index;
53158c2ecf20Sopenharmony_ci	int loop;
53168c2ecf20Sopenharmony_ci
53178c2ecf20Sopenharmony_ci	switch (*format) {
53188c2ecf20Sopenharmony_ci	case 'F':
53198c2ecf20Sopenharmony_ci	case 'S':
53208c2ecf20Sopenharmony_ci	case 'f':
53218c2ecf20Sopenharmony_ci	case 's':
53228c2ecf20Sopenharmony_ci		ret++;
53238c2ecf20Sopenharmony_ci		break;
53248c2ecf20Sopenharmony_ci	case 'M':
53258c2ecf20Sopenharmony_ci	case 'm':
53268c2ecf20Sopenharmony_ci		/* [mM]R , [mM]F */
53278c2ecf20Sopenharmony_ci		switch (format[1]) {
53288c2ecf20Sopenharmony_ci		case 'R':
53298c2ecf20Sopenharmony_ci		case 'F':
53308c2ecf20Sopenharmony_ci			ret++;
53318c2ecf20Sopenharmony_ci			break;
53328c2ecf20Sopenharmony_ci		}
53338c2ecf20Sopenharmony_ci		ret++;
53348c2ecf20Sopenharmony_ci		break;
53358c2ecf20Sopenharmony_ci	case 'I':
53368c2ecf20Sopenharmony_ci	case 'i':
53378c2ecf20Sopenharmony_ci		index = 2;
53388c2ecf20Sopenharmony_ci		loop = 1;
53398c2ecf20Sopenharmony_ci		switch (format[1]) {
53408c2ecf20Sopenharmony_ci		case 'S':
53418c2ecf20Sopenharmony_ci			/*[S][pfs]*/
53428c2ecf20Sopenharmony_ci			while (loop) {
53438c2ecf20Sopenharmony_ci				switch (format[index]) {
53448c2ecf20Sopenharmony_ci				case 'p':
53458c2ecf20Sopenharmony_ci				case 'f':
53468c2ecf20Sopenharmony_ci				case 's':
53478c2ecf20Sopenharmony_ci					ret++;
53488c2ecf20Sopenharmony_ci					index++;
53498c2ecf20Sopenharmony_ci					break;
53508c2ecf20Sopenharmony_ci				default:
53518c2ecf20Sopenharmony_ci					loop = 0;
53528c2ecf20Sopenharmony_ci					break;
53538c2ecf20Sopenharmony_ci				}
53548c2ecf20Sopenharmony_ci			}
53558c2ecf20Sopenharmony_ci			/* fall through */
53568c2ecf20Sopenharmony_ci		case '4':
53578c2ecf20Sopenharmony_ci			/* [4S][hnbl] */
53588c2ecf20Sopenharmony_ci			switch (format[index]) {
53598c2ecf20Sopenharmony_ci			case 'h':
53608c2ecf20Sopenharmony_ci			case 'n':
53618c2ecf20Sopenharmony_ci			case 'l':
53628c2ecf20Sopenharmony_ci			case 'b':
53638c2ecf20Sopenharmony_ci				ret++;
53648c2ecf20Sopenharmony_ci				index++;
53658c2ecf20Sopenharmony_ci				break;
53668c2ecf20Sopenharmony_ci			}
53678c2ecf20Sopenharmony_ci			if (format[1] == '4') {
53688c2ecf20Sopenharmony_ci				ret++;
53698c2ecf20Sopenharmony_ci				break;
53708c2ecf20Sopenharmony_ci			}
53718c2ecf20Sopenharmony_ci			/* fall through */
53728c2ecf20Sopenharmony_ci		case '6':
53738c2ecf20Sopenharmony_ci			/* [6S]c */
53748c2ecf20Sopenharmony_ci			if (format[index] == 'c')
53758c2ecf20Sopenharmony_ci				ret++;
53768c2ecf20Sopenharmony_ci			ret++;
53778c2ecf20Sopenharmony_ci			break;
53788c2ecf20Sopenharmony_ci		}
53798c2ecf20Sopenharmony_ci		ret++;
53808c2ecf20Sopenharmony_ci		break;
53818c2ecf20Sopenharmony_ci	case 'U':
53828c2ecf20Sopenharmony_ci		switch (format[1]) {
53838c2ecf20Sopenharmony_ci		case 'L':
53848c2ecf20Sopenharmony_ci		case 'l':
53858c2ecf20Sopenharmony_ci		case 'B':
53868c2ecf20Sopenharmony_ci		case 'b':
53878c2ecf20Sopenharmony_ci			ret++;
53888c2ecf20Sopenharmony_ci			break;
53898c2ecf20Sopenharmony_ci		}
53908c2ecf20Sopenharmony_ci		ret++;
53918c2ecf20Sopenharmony_ci		break;
53928c2ecf20Sopenharmony_ci	case 'h':
53938c2ecf20Sopenharmony_ci		switch (format[1]) {
53948c2ecf20Sopenharmony_ci		case 'C':
53958c2ecf20Sopenharmony_ci		case 'D':
53968c2ecf20Sopenharmony_ci		case 'N':
53978c2ecf20Sopenharmony_ci			ret++;
53988c2ecf20Sopenharmony_ci			break;
53998c2ecf20Sopenharmony_ci		}
54008c2ecf20Sopenharmony_ci		ret++;
54018c2ecf20Sopenharmony_ci		break;
54028c2ecf20Sopenharmony_ci	default:
54038c2ecf20Sopenharmony_ci		break;
54048c2ecf20Sopenharmony_ci	}
54058c2ecf20Sopenharmony_ci
54068c2ecf20Sopenharmony_ci	return ret;
54078c2ecf20Sopenharmony_ci}
54088c2ecf20Sopenharmony_ci
54098c2ecf20Sopenharmony_cistatic void free_parse_args(struct tep_print_parse *arg)
54108c2ecf20Sopenharmony_ci{
54118c2ecf20Sopenharmony_ci	struct tep_print_parse *del;
54128c2ecf20Sopenharmony_ci
54138c2ecf20Sopenharmony_ci	while (arg) {
54148c2ecf20Sopenharmony_ci		del = arg;
54158c2ecf20Sopenharmony_ci		arg = del->next;
54168c2ecf20Sopenharmony_ci		free(del->format);
54178c2ecf20Sopenharmony_ci		free(del);
54188c2ecf20Sopenharmony_ci	}
54198c2ecf20Sopenharmony_ci}
54208c2ecf20Sopenharmony_ci
54218c2ecf20Sopenharmony_cistatic int parse_arg_add(struct tep_print_parse **parse, char *format,
54228c2ecf20Sopenharmony_ci			 enum tep_print_parse_type type,
54238c2ecf20Sopenharmony_ci			 struct tep_print_arg *arg,
54248c2ecf20Sopenharmony_ci			 struct tep_print_arg *len_as_arg,
54258c2ecf20Sopenharmony_ci			 int ls)
54268c2ecf20Sopenharmony_ci{
54278c2ecf20Sopenharmony_ci	struct tep_print_parse *parg = NULL;
54288c2ecf20Sopenharmony_ci
54298c2ecf20Sopenharmony_ci	parg = calloc(1, sizeof(*parg));
54308c2ecf20Sopenharmony_ci	if (!parg)
54318c2ecf20Sopenharmony_ci		goto error;
54328c2ecf20Sopenharmony_ci	parg->format = strdup(format);
54338c2ecf20Sopenharmony_ci	if (!parg->format)
54348c2ecf20Sopenharmony_ci		goto error;
54358c2ecf20Sopenharmony_ci	parg->type = type;
54368c2ecf20Sopenharmony_ci	parg->arg = arg;
54378c2ecf20Sopenharmony_ci	parg->len_as_arg = len_as_arg;
54388c2ecf20Sopenharmony_ci	parg->ls = ls;
54398c2ecf20Sopenharmony_ci	*parse = parg;
54408c2ecf20Sopenharmony_ci	return 0;
54418c2ecf20Sopenharmony_cierror:
54428c2ecf20Sopenharmony_ci	if (parg) {
54438c2ecf20Sopenharmony_ci		free(parg->format);
54448c2ecf20Sopenharmony_ci		free(parg);
54458c2ecf20Sopenharmony_ci	}
54468c2ecf20Sopenharmony_ci	return -1;
54478c2ecf20Sopenharmony_ci}
54488c2ecf20Sopenharmony_ci
54498c2ecf20Sopenharmony_cistatic int parse_arg_format(struct tep_print_parse **parse,
54508c2ecf20Sopenharmony_ci			    struct tep_event *event,
54518c2ecf20Sopenharmony_ci			    const char *format, struct tep_print_arg **arg)
54528c2ecf20Sopenharmony_ci{
54538c2ecf20Sopenharmony_ci	struct tep_print_arg *len_arg = NULL;
54548c2ecf20Sopenharmony_ci	char print_format[32];
54558c2ecf20Sopenharmony_ci	const char *start = format;
54568c2ecf20Sopenharmony_ci	int ret = 0;
54578c2ecf20Sopenharmony_ci	int ls = 0;
54588c2ecf20Sopenharmony_ci	int res;
54598c2ecf20Sopenharmony_ci	int len;
54608c2ecf20Sopenharmony_ci
54618c2ecf20Sopenharmony_ci	format++;
54628c2ecf20Sopenharmony_ci	ret++;
54638c2ecf20Sopenharmony_ci	for (; *format; format++) {
54648c2ecf20Sopenharmony_ci		switch (*format) {
54658c2ecf20Sopenharmony_ci		case '#':
54668c2ecf20Sopenharmony_ci			/* FIXME: need to handle properly */
54678c2ecf20Sopenharmony_ci			break;
54688c2ecf20Sopenharmony_ci		case 'h':
54698c2ecf20Sopenharmony_ci			ls--;
54708c2ecf20Sopenharmony_ci			break;
54718c2ecf20Sopenharmony_ci		case 'l':
54728c2ecf20Sopenharmony_ci			ls++;
54738c2ecf20Sopenharmony_ci			break;
54748c2ecf20Sopenharmony_ci		case 'L':
54758c2ecf20Sopenharmony_ci			ls = 2;
54768c2ecf20Sopenharmony_ci			break;
54778c2ecf20Sopenharmony_ci		case '.':
54788c2ecf20Sopenharmony_ci		case 'z':
54798c2ecf20Sopenharmony_ci		case 'Z':
54808c2ecf20Sopenharmony_ci		case '0' ... '9':
54818c2ecf20Sopenharmony_ci		case '-':
54828c2ecf20Sopenharmony_ci			break;
54838c2ecf20Sopenharmony_ci		case '*':
54848c2ecf20Sopenharmony_ci			/* The argument is the length. */
54858c2ecf20Sopenharmony_ci			if (!*arg) {
54868c2ecf20Sopenharmony_ci				do_warning_event(event, "no argument match");
54878c2ecf20Sopenharmony_ci				event->flags |= TEP_EVENT_FL_FAILED;
54888c2ecf20Sopenharmony_ci				goto out_failed;
54898c2ecf20Sopenharmony_ci			}
54908c2ecf20Sopenharmony_ci			if (len_arg) {
54918c2ecf20Sopenharmony_ci				do_warning_event(event, "argument already matched");
54928c2ecf20Sopenharmony_ci				event->flags |= TEP_EVENT_FL_FAILED;
54938c2ecf20Sopenharmony_ci				goto out_failed;
54948c2ecf20Sopenharmony_ci			}
54958c2ecf20Sopenharmony_ci			len_arg = *arg;
54968c2ecf20Sopenharmony_ci			*arg = (*arg)->next;
54978c2ecf20Sopenharmony_ci			break;
54988c2ecf20Sopenharmony_ci		case 'p':
54998c2ecf20Sopenharmony_ci			if (!*arg) {
55008c2ecf20Sopenharmony_ci				do_warning_event(event, "no argument match");
55018c2ecf20Sopenharmony_ci				event->flags |= TEP_EVENT_FL_FAILED;
55028c2ecf20Sopenharmony_ci				goto out_failed;
55038c2ecf20Sopenharmony_ci			}
55048c2ecf20Sopenharmony_ci			res = parse_arg_format_pointer(format + 1);
55058c2ecf20Sopenharmony_ci			if (res > 0) {
55068c2ecf20Sopenharmony_ci				format += res;
55078c2ecf20Sopenharmony_ci				ret += res;
55088c2ecf20Sopenharmony_ci			}
55098c2ecf20Sopenharmony_ci			len = ((unsigned long)format + 1) -
55108c2ecf20Sopenharmony_ci				(unsigned long)start;
55118c2ecf20Sopenharmony_ci			/* should never happen */
55128c2ecf20Sopenharmony_ci			if (len > 31) {
55138c2ecf20Sopenharmony_ci				do_warning_event(event, "bad format!");
55148c2ecf20Sopenharmony_ci				event->flags |= TEP_EVENT_FL_FAILED;
55158c2ecf20Sopenharmony_ci				len = 31;
55168c2ecf20Sopenharmony_ci			}
55178c2ecf20Sopenharmony_ci			memcpy(print_format, start, len);
55188c2ecf20Sopenharmony_ci			print_format[len] = 0;
55198c2ecf20Sopenharmony_ci
55208c2ecf20Sopenharmony_ci			parse_arg_add(parse, print_format,
55218c2ecf20Sopenharmony_ci				      PRINT_FMT_ARG_POINTER, *arg, len_arg, ls);
55228c2ecf20Sopenharmony_ci			*arg = (*arg)->next;
55238c2ecf20Sopenharmony_ci			ret++;
55248c2ecf20Sopenharmony_ci			return ret;
55258c2ecf20Sopenharmony_ci		case 'd':
55268c2ecf20Sopenharmony_ci		case 'u':
55278c2ecf20Sopenharmony_ci		case 'i':
55288c2ecf20Sopenharmony_ci		case 'x':
55298c2ecf20Sopenharmony_ci		case 'X':
55308c2ecf20Sopenharmony_ci		case 'o':
55318c2ecf20Sopenharmony_ci			if (!*arg) {
55328c2ecf20Sopenharmony_ci				do_warning_event(event, "no argument match");
55338c2ecf20Sopenharmony_ci				event->flags |= TEP_EVENT_FL_FAILED;
55348c2ecf20Sopenharmony_ci				goto out_failed;
55358c2ecf20Sopenharmony_ci			}
55368c2ecf20Sopenharmony_ci
55378c2ecf20Sopenharmony_ci			len = ((unsigned long)format + 1) -
55388c2ecf20Sopenharmony_ci				(unsigned long)start;
55398c2ecf20Sopenharmony_ci
55408c2ecf20Sopenharmony_ci			/* should never happen */
55418c2ecf20Sopenharmony_ci			if (len > 30) {
55428c2ecf20Sopenharmony_ci				do_warning_event(event, "bad format!");
55438c2ecf20Sopenharmony_ci				event->flags |= TEP_EVENT_FL_FAILED;
55448c2ecf20Sopenharmony_ci				len = 31;
55458c2ecf20Sopenharmony_ci			}
55468c2ecf20Sopenharmony_ci			memcpy(print_format, start, len);
55478c2ecf20Sopenharmony_ci			print_format[len] = 0;
55488c2ecf20Sopenharmony_ci
55498c2ecf20Sopenharmony_ci			if (event->tep->long_size == 8 && ls == 1 &&
55508c2ecf20Sopenharmony_ci			    sizeof(long) != 8) {
55518c2ecf20Sopenharmony_ci				char *p;
55528c2ecf20Sopenharmony_ci
55538c2ecf20Sopenharmony_ci				/* make %l into %ll */
55548c2ecf20Sopenharmony_ci				if (ls == 1 && (p = strchr(print_format, 'l')))
55558c2ecf20Sopenharmony_ci					memmove(p+1, p, strlen(p)+1);
55568c2ecf20Sopenharmony_ci				ls = 2;
55578c2ecf20Sopenharmony_ci			}
55588c2ecf20Sopenharmony_ci			if (ls < -2 || ls > 2) {
55598c2ecf20Sopenharmony_ci				do_warning_event(event, "bad count (%d)", ls);
55608c2ecf20Sopenharmony_ci				event->flags |= TEP_EVENT_FL_FAILED;
55618c2ecf20Sopenharmony_ci			}
55628c2ecf20Sopenharmony_ci			parse_arg_add(parse, print_format,
55638c2ecf20Sopenharmony_ci				      PRINT_FMT_ARG_DIGIT, *arg, len_arg, ls);
55648c2ecf20Sopenharmony_ci			*arg = (*arg)->next;
55658c2ecf20Sopenharmony_ci			ret++;
55668c2ecf20Sopenharmony_ci			return ret;
55678c2ecf20Sopenharmony_ci		case 's':
55688c2ecf20Sopenharmony_ci			if (!*arg) {
55698c2ecf20Sopenharmony_ci				do_warning_event(event, "no matching argument");
55708c2ecf20Sopenharmony_ci				event->flags |= TEP_EVENT_FL_FAILED;
55718c2ecf20Sopenharmony_ci				goto out_failed;
55728c2ecf20Sopenharmony_ci			}
55738c2ecf20Sopenharmony_ci
55748c2ecf20Sopenharmony_ci			len = ((unsigned long)format + 1) -
55758c2ecf20Sopenharmony_ci				(unsigned long)start;
55768c2ecf20Sopenharmony_ci
55778c2ecf20Sopenharmony_ci			/* should never happen */
55788c2ecf20Sopenharmony_ci			if (len > 31) {
55798c2ecf20Sopenharmony_ci				do_warning_event(event, "bad format!");
55808c2ecf20Sopenharmony_ci				event->flags |= TEP_EVENT_FL_FAILED;
55818c2ecf20Sopenharmony_ci				len = 31;
55828c2ecf20Sopenharmony_ci			}
55838c2ecf20Sopenharmony_ci
55848c2ecf20Sopenharmony_ci			memcpy(print_format, start, len);
55858c2ecf20Sopenharmony_ci			print_format[len] = 0;
55868c2ecf20Sopenharmony_ci
55878c2ecf20Sopenharmony_ci			parse_arg_add(parse, print_format,
55888c2ecf20Sopenharmony_ci					PRINT_FMT_ARG_STRING, *arg, len_arg, 0);
55898c2ecf20Sopenharmony_ci			*arg = (*arg)->next;
55908c2ecf20Sopenharmony_ci			ret++;
55918c2ecf20Sopenharmony_ci			return ret;
55928c2ecf20Sopenharmony_ci		default:
55938c2ecf20Sopenharmony_ci			snprintf(print_format, 32, ">%c<", *format);
55948c2ecf20Sopenharmony_ci			parse_arg_add(parse, print_format,
55958c2ecf20Sopenharmony_ci					PRINT_FMT_STRING, NULL, NULL, 0);
55968c2ecf20Sopenharmony_ci			ret++;
55978c2ecf20Sopenharmony_ci			return ret;
55988c2ecf20Sopenharmony_ci		}
55998c2ecf20Sopenharmony_ci		ret++;
56008c2ecf20Sopenharmony_ci	}
56018c2ecf20Sopenharmony_ci
56028c2ecf20Sopenharmony_ciout_failed:
56038c2ecf20Sopenharmony_ci	return ret;
56048c2ecf20Sopenharmony_ci
56058c2ecf20Sopenharmony_ci}
56068c2ecf20Sopenharmony_ci
56078c2ecf20Sopenharmony_cistatic int parse_arg_string(struct tep_print_parse **parse, const char *format)
56088c2ecf20Sopenharmony_ci{
56098c2ecf20Sopenharmony_ci	struct trace_seq s;
56108c2ecf20Sopenharmony_ci	int ret = 0;
56118c2ecf20Sopenharmony_ci
56128c2ecf20Sopenharmony_ci	trace_seq_init(&s);
56138c2ecf20Sopenharmony_ci	for (; *format; format++) {
56148c2ecf20Sopenharmony_ci		if (*format == '\\') {
56158c2ecf20Sopenharmony_ci			format++;
56168c2ecf20Sopenharmony_ci			ret++;
56178c2ecf20Sopenharmony_ci			switch (*format) {
56188c2ecf20Sopenharmony_ci			case 'n':
56198c2ecf20Sopenharmony_ci				trace_seq_putc(&s, '\n');
56208c2ecf20Sopenharmony_ci				break;
56218c2ecf20Sopenharmony_ci			case 't':
56228c2ecf20Sopenharmony_ci				trace_seq_putc(&s, '\t');
56238c2ecf20Sopenharmony_ci				break;
56248c2ecf20Sopenharmony_ci			case 'r':
56258c2ecf20Sopenharmony_ci				trace_seq_putc(&s, '\r');
56268c2ecf20Sopenharmony_ci				break;
56278c2ecf20Sopenharmony_ci			case '\\':
56288c2ecf20Sopenharmony_ci				trace_seq_putc(&s, '\\');
56298c2ecf20Sopenharmony_ci				break;
56308c2ecf20Sopenharmony_ci			default:
56318c2ecf20Sopenharmony_ci				trace_seq_putc(&s, *format);
56328c2ecf20Sopenharmony_ci				break;
56338c2ecf20Sopenharmony_ci			}
56348c2ecf20Sopenharmony_ci		} else if (*format == '%') {
56358c2ecf20Sopenharmony_ci			if (*(format + 1) == '%') {
56368c2ecf20Sopenharmony_ci				trace_seq_putc(&s, '%');
56378c2ecf20Sopenharmony_ci				format++;
56388c2ecf20Sopenharmony_ci				ret++;
56398c2ecf20Sopenharmony_ci			} else
56408c2ecf20Sopenharmony_ci				break;
56418c2ecf20Sopenharmony_ci		} else
56428c2ecf20Sopenharmony_ci			trace_seq_putc(&s, *format);
56438c2ecf20Sopenharmony_ci
56448c2ecf20Sopenharmony_ci		ret++;
56458c2ecf20Sopenharmony_ci	}
56468c2ecf20Sopenharmony_ci	trace_seq_terminate(&s);
56478c2ecf20Sopenharmony_ci	parse_arg_add(parse, s.buffer, PRINT_FMT_STRING, NULL, NULL, 0);
56488c2ecf20Sopenharmony_ci	trace_seq_destroy(&s);
56498c2ecf20Sopenharmony_ci
56508c2ecf20Sopenharmony_ci	return ret;
56518c2ecf20Sopenharmony_ci}
56528c2ecf20Sopenharmony_ci
56538c2ecf20Sopenharmony_cistatic struct tep_print_parse *
56548c2ecf20Sopenharmony_ciparse_args(struct tep_event *event, const char *format, struct tep_print_arg *arg)
56558c2ecf20Sopenharmony_ci{
56568c2ecf20Sopenharmony_ci	struct tep_print_parse *parse_ret = NULL;
56578c2ecf20Sopenharmony_ci	struct tep_print_parse **parse = NULL;
56588c2ecf20Sopenharmony_ci	int ret;
56598c2ecf20Sopenharmony_ci	int len;
56608c2ecf20Sopenharmony_ci
56618c2ecf20Sopenharmony_ci	len = strlen(format);
56628c2ecf20Sopenharmony_ci	while (*format) {
56638c2ecf20Sopenharmony_ci		if (!parse_ret)
56648c2ecf20Sopenharmony_ci			parse = &parse_ret;
56658c2ecf20Sopenharmony_ci		if (*format == '%' && *(format + 1) != '%')
56668c2ecf20Sopenharmony_ci			ret = parse_arg_format(parse, event, format, &arg);
56678c2ecf20Sopenharmony_ci		else
56688c2ecf20Sopenharmony_ci			ret = parse_arg_string(parse, format);
56698c2ecf20Sopenharmony_ci		if (*parse)
56708c2ecf20Sopenharmony_ci			parse = &((*parse)->next);
56718c2ecf20Sopenharmony_ci
56728c2ecf20Sopenharmony_ci		len -= ret;
56738c2ecf20Sopenharmony_ci		if (len > 0)
56748c2ecf20Sopenharmony_ci			format += ret;
56758c2ecf20Sopenharmony_ci		else
56768c2ecf20Sopenharmony_ci			break;
56778c2ecf20Sopenharmony_ci	}
56788c2ecf20Sopenharmony_ci	return parse_ret;
56798c2ecf20Sopenharmony_ci}
56808c2ecf20Sopenharmony_ci
56818c2ecf20Sopenharmony_cistatic void print_event_cache(struct tep_print_parse *parse, struct trace_seq *s,
56828c2ecf20Sopenharmony_ci			      void *data, int size, struct tep_event *event)
56838c2ecf20Sopenharmony_ci{
56848c2ecf20Sopenharmony_ci	int len_arg;
56858c2ecf20Sopenharmony_ci
56868c2ecf20Sopenharmony_ci	while (parse) {
56878c2ecf20Sopenharmony_ci		if (parse->len_as_arg)
56888c2ecf20Sopenharmony_ci			len_arg = eval_num_arg(data, size, event, parse->len_as_arg);
56898c2ecf20Sopenharmony_ci		switch (parse->type) {
56908c2ecf20Sopenharmony_ci		case PRINT_FMT_ARG_DIGIT:
56918c2ecf20Sopenharmony_ci			print_arg_number(s, parse->format,
56928c2ecf20Sopenharmony_ci					parse->len_as_arg ? len_arg : -1, data,
56938c2ecf20Sopenharmony_ci					 size, parse->ls, event, parse->arg);
56948c2ecf20Sopenharmony_ci			break;
56958c2ecf20Sopenharmony_ci		case PRINT_FMT_ARG_POINTER:
56968c2ecf20Sopenharmony_ci			print_arg_pointer(s, parse->format,
56978c2ecf20Sopenharmony_ci					  parse->len_as_arg ? len_arg : 1,
56988c2ecf20Sopenharmony_ci					  data, size, event, parse->arg);
56998c2ecf20Sopenharmony_ci			break;
57008c2ecf20Sopenharmony_ci		case PRINT_FMT_ARG_STRING:
57018c2ecf20Sopenharmony_ci			print_arg_string(s, parse->format,
57028c2ecf20Sopenharmony_ci					 parse->len_as_arg ? len_arg : -1,
57038c2ecf20Sopenharmony_ci					 data, size, event, parse->arg);
57048c2ecf20Sopenharmony_ci			break;
57058c2ecf20Sopenharmony_ci		case PRINT_FMT_STRING:
57068c2ecf20Sopenharmony_ci		default:
57078c2ecf20Sopenharmony_ci			trace_seq_printf(s, "%s", parse->format);
57088c2ecf20Sopenharmony_ci			break;
57098c2ecf20Sopenharmony_ci		}
57108c2ecf20Sopenharmony_ci		parse = parse->next;
57118c2ecf20Sopenharmony_ci	}
57128c2ecf20Sopenharmony_ci}
57138c2ecf20Sopenharmony_ci
57148c2ecf20Sopenharmony_cistatic void pretty_print(struct trace_seq *s, void *data, int size, struct tep_event *event)
57158c2ecf20Sopenharmony_ci{
57168c2ecf20Sopenharmony_ci	struct tep_print_parse *parse = event->print_fmt.print_cache;
57178c2ecf20Sopenharmony_ci	struct tep_print_arg *args = NULL;
57188c2ecf20Sopenharmony_ci	char *bprint_fmt = NULL;
57198c2ecf20Sopenharmony_ci
57208c2ecf20Sopenharmony_ci	if (event->flags & TEP_EVENT_FL_FAILED) {
57218c2ecf20Sopenharmony_ci		trace_seq_printf(s, "[FAILED TO PARSE]");
57228c2ecf20Sopenharmony_ci		tep_print_fields(s, data, size, event);
57238c2ecf20Sopenharmony_ci		return;
57248c2ecf20Sopenharmony_ci	}
57258c2ecf20Sopenharmony_ci
57268c2ecf20Sopenharmony_ci	if (event->flags & TEP_EVENT_FL_ISBPRINT) {
57278c2ecf20Sopenharmony_ci		bprint_fmt = get_bprint_format(data, size, event);
57288c2ecf20Sopenharmony_ci		args = make_bprint_args(bprint_fmt, data, size, event);
57298c2ecf20Sopenharmony_ci		parse = parse_args(event, bprint_fmt, args);
57308c2ecf20Sopenharmony_ci	}
57318c2ecf20Sopenharmony_ci
57328c2ecf20Sopenharmony_ci	print_event_cache(parse, s, data, size, event);
57338c2ecf20Sopenharmony_ci
57348c2ecf20Sopenharmony_ci	if (event->flags & TEP_EVENT_FL_ISBPRINT) {
57358c2ecf20Sopenharmony_ci		free_parse_args(parse);
57368c2ecf20Sopenharmony_ci		free_args(args);
57378c2ecf20Sopenharmony_ci		free(bprint_fmt);
57388c2ecf20Sopenharmony_ci	}
57398c2ecf20Sopenharmony_ci}
57408c2ecf20Sopenharmony_ci
57418c2ecf20Sopenharmony_ci/*
57428c2ecf20Sopenharmony_ci * This parses out the Latency format (interrupts disabled,
57438c2ecf20Sopenharmony_ci * need rescheduling, in hard/soft interrupt, preempt count
57448c2ecf20Sopenharmony_ci * and lock depth) and places it into the trace_seq.
57458c2ecf20Sopenharmony_ci */
57468c2ecf20Sopenharmony_cistatic void data_latency_format(struct tep_handle *tep, struct trace_seq *s,
57478c2ecf20Sopenharmony_ci				char *format, struct tep_record *record)
57488c2ecf20Sopenharmony_ci{
57498c2ecf20Sopenharmony_ci	static int check_lock_depth = 1;
57508c2ecf20Sopenharmony_ci	static int check_migrate_disable = 1;
57518c2ecf20Sopenharmony_ci	static int lock_depth_exists;
57528c2ecf20Sopenharmony_ci	static int migrate_disable_exists;
57538c2ecf20Sopenharmony_ci	unsigned int lat_flags;
57548c2ecf20Sopenharmony_ci	struct trace_seq sq;
57558c2ecf20Sopenharmony_ci	unsigned int pc;
57568c2ecf20Sopenharmony_ci	int lock_depth = 0;
57578c2ecf20Sopenharmony_ci	int migrate_disable = 0;
57588c2ecf20Sopenharmony_ci	int hardirq;
57598c2ecf20Sopenharmony_ci	int softirq;
57608c2ecf20Sopenharmony_ci	void *data = record->data;
57618c2ecf20Sopenharmony_ci
57628c2ecf20Sopenharmony_ci	trace_seq_init(&sq);
57638c2ecf20Sopenharmony_ci	lat_flags = parse_common_flags(tep, data);
57648c2ecf20Sopenharmony_ci	pc = parse_common_pc(tep, data);
57658c2ecf20Sopenharmony_ci	/* lock_depth may not always exist */
57668c2ecf20Sopenharmony_ci	if (lock_depth_exists)
57678c2ecf20Sopenharmony_ci		lock_depth = parse_common_lock_depth(tep, data);
57688c2ecf20Sopenharmony_ci	else if (check_lock_depth) {
57698c2ecf20Sopenharmony_ci		lock_depth = parse_common_lock_depth(tep, data);
57708c2ecf20Sopenharmony_ci		if (lock_depth < 0)
57718c2ecf20Sopenharmony_ci			check_lock_depth = 0;
57728c2ecf20Sopenharmony_ci		else
57738c2ecf20Sopenharmony_ci			lock_depth_exists = 1;
57748c2ecf20Sopenharmony_ci	}
57758c2ecf20Sopenharmony_ci
57768c2ecf20Sopenharmony_ci	/* migrate_disable may not always exist */
57778c2ecf20Sopenharmony_ci	if (migrate_disable_exists)
57788c2ecf20Sopenharmony_ci		migrate_disable = parse_common_migrate_disable(tep, data);
57798c2ecf20Sopenharmony_ci	else if (check_migrate_disable) {
57808c2ecf20Sopenharmony_ci		migrate_disable = parse_common_migrate_disable(tep, data);
57818c2ecf20Sopenharmony_ci		if (migrate_disable < 0)
57828c2ecf20Sopenharmony_ci			check_migrate_disable = 0;
57838c2ecf20Sopenharmony_ci		else
57848c2ecf20Sopenharmony_ci			migrate_disable_exists = 1;
57858c2ecf20Sopenharmony_ci	}
57868c2ecf20Sopenharmony_ci
57878c2ecf20Sopenharmony_ci	hardirq = lat_flags & TRACE_FLAG_HARDIRQ;
57888c2ecf20Sopenharmony_ci	softirq = lat_flags & TRACE_FLAG_SOFTIRQ;
57898c2ecf20Sopenharmony_ci
57908c2ecf20Sopenharmony_ci	trace_seq_printf(&sq, "%c%c%c",
57918c2ecf20Sopenharmony_ci	       (lat_flags & TRACE_FLAG_IRQS_OFF) ? 'd' :
57928c2ecf20Sopenharmony_ci	       (lat_flags & TRACE_FLAG_IRQS_NOSUPPORT) ?
57938c2ecf20Sopenharmony_ci	       'X' : '.',
57948c2ecf20Sopenharmony_ci	       (lat_flags & TRACE_FLAG_NEED_RESCHED) ?
57958c2ecf20Sopenharmony_ci	       'N' : '.',
57968c2ecf20Sopenharmony_ci	       (hardirq && softirq) ? 'H' :
57978c2ecf20Sopenharmony_ci	       hardirq ? 'h' : softirq ? 's' : '.');
57988c2ecf20Sopenharmony_ci
57998c2ecf20Sopenharmony_ci	if (pc)
58008c2ecf20Sopenharmony_ci		trace_seq_printf(&sq, "%x", pc);
58018c2ecf20Sopenharmony_ci	else
58028c2ecf20Sopenharmony_ci		trace_seq_printf(&sq, ".");
58038c2ecf20Sopenharmony_ci
58048c2ecf20Sopenharmony_ci	if (migrate_disable_exists) {
58058c2ecf20Sopenharmony_ci		if (migrate_disable < 0)
58068c2ecf20Sopenharmony_ci			trace_seq_printf(&sq, ".");
58078c2ecf20Sopenharmony_ci		else
58088c2ecf20Sopenharmony_ci			trace_seq_printf(&sq, "%d", migrate_disable);
58098c2ecf20Sopenharmony_ci	}
58108c2ecf20Sopenharmony_ci
58118c2ecf20Sopenharmony_ci	if (lock_depth_exists) {
58128c2ecf20Sopenharmony_ci		if (lock_depth < 0)
58138c2ecf20Sopenharmony_ci			trace_seq_printf(&sq, ".");
58148c2ecf20Sopenharmony_ci		else
58158c2ecf20Sopenharmony_ci			trace_seq_printf(&sq, "%d", lock_depth);
58168c2ecf20Sopenharmony_ci	}
58178c2ecf20Sopenharmony_ci
58188c2ecf20Sopenharmony_ci	if (sq.state == TRACE_SEQ__MEM_ALLOC_FAILED) {
58198c2ecf20Sopenharmony_ci		s->state = TRACE_SEQ__MEM_ALLOC_FAILED;
58208c2ecf20Sopenharmony_ci		return;
58218c2ecf20Sopenharmony_ci	}
58228c2ecf20Sopenharmony_ci
58238c2ecf20Sopenharmony_ci	trace_seq_terminate(&sq);
58248c2ecf20Sopenharmony_ci	trace_seq_puts(s, sq.buffer);
58258c2ecf20Sopenharmony_ci	trace_seq_destroy(&sq);
58268c2ecf20Sopenharmony_ci	trace_seq_terminate(s);
58278c2ecf20Sopenharmony_ci}
58288c2ecf20Sopenharmony_ci
58298c2ecf20Sopenharmony_ci/**
58308c2ecf20Sopenharmony_ci * tep_data_type - parse out the given event type
58318c2ecf20Sopenharmony_ci * @tep: a handle to the trace event parser context
58328c2ecf20Sopenharmony_ci * @rec: the record to read from
58338c2ecf20Sopenharmony_ci *
58348c2ecf20Sopenharmony_ci * This returns the event id from the @rec.
58358c2ecf20Sopenharmony_ci */
58368c2ecf20Sopenharmony_ciint tep_data_type(struct tep_handle *tep, struct tep_record *rec)
58378c2ecf20Sopenharmony_ci{
58388c2ecf20Sopenharmony_ci	return trace_parse_common_type(tep, rec->data);
58398c2ecf20Sopenharmony_ci}
58408c2ecf20Sopenharmony_ci
58418c2ecf20Sopenharmony_ci/**
58428c2ecf20Sopenharmony_ci * tep_data_pid - parse the PID from record
58438c2ecf20Sopenharmony_ci * @tep: a handle to the trace event parser context
58448c2ecf20Sopenharmony_ci * @rec: the record to parse
58458c2ecf20Sopenharmony_ci *
58468c2ecf20Sopenharmony_ci * This returns the PID from a record.
58478c2ecf20Sopenharmony_ci */
58488c2ecf20Sopenharmony_ciint tep_data_pid(struct tep_handle *tep, struct tep_record *rec)
58498c2ecf20Sopenharmony_ci{
58508c2ecf20Sopenharmony_ci	return parse_common_pid(tep, rec->data);
58518c2ecf20Sopenharmony_ci}
58528c2ecf20Sopenharmony_ci
58538c2ecf20Sopenharmony_ci/**
58548c2ecf20Sopenharmony_ci * tep_data_preempt_count - parse the preempt count from the record
58558c2ecf20Sopenharmony_ci * @tep: a handle to the trace event parser context
58568c2ecf20Sopenharmony_ci * @rec: the record to parse
58578c2ecf20Sopenharmony_ci *
58588c2ecf20Sopenharmony_ci * This returns the preempt count from a record.
58598c2ecf20Sopenharmony_ci */
58608c2ecf20Sopenharmony_ciint tep_data_preempt_count(struct tep_handle *tep, struct tep_record *rec)
58618c2ecf20Sopenharmony_ci{
58628c2ecf20Sopenharmony_ci	return parse_common_pc(tep, rec->data);
58638c2ecf20Sopenharmony_ci}
58648c2ecf20Sopenharmony_ci
58658c2ecf20Sopenharmony_ci/**
58668c2ecf20Sopenharmony_ci * tep_data_flags - parse the latency flags from the record
58678c2ecf20Sopenharmony_ci * @tep: a handle to the trace event parser context
58688c2ecf20Sopenharmony_ci * @rec: the record to parse
58698c2ecf20Sopenharmony_ci *
58708c2ecf20Sopenharmony_ci * This returns the latency flags from a record.
58718c2ecf20Sopenharmony_ci *
58728c2ecf20Sopenharmony_ci *  Use trace_flag_type enum for the flags (see event-parse.h).
58738c2ecf20Sopenharmony_ci */
58748c2ecf20Sopenharmony_ciint tep_data_flags(struct tep_handle *tep, struct tep_record *rec)
58758c2ecf20Sopenharmony_ci{
58768c2ecf20Sopenharmony_ci	return parse_common_flags(tep, rec->data);
58778c2ecf20Sopenharmony_ci}
58788c2ecf20Sopenharmony_ci
58798c2ecf20Sopenharmony_ci/**
58808c2ecf20Sopenharmony_ci * tep_data_comm_from_pid - return the command line from PID
58818c2ecf20Sopenharmony_ci * @tep: a handle to the trace event parser context
58828c2ecf20Sopenharmony_ci * @pid: the PID of the task to search for
58838c2ecf20Sopenharmony_ci *
58848c2ecf20Sopenharmony_ci * This returns a pointer to the command line that has the given
58858c2ecf20Sopenharmony_ci * @pid.
58868c2ecf20Sopenharmony_ci */
58878c2ecf20Sopenharmony_ciconst char *tep_data_comm_from_pid(struct tep_handle *tep, int pid)
58888c2ecf20Sopenharmony_ci{
58898c2ecf20Sopenharmony_ci	const char *comm;
58908c2ecf20Sopenharmony_ci
58918c2ecf20Sopenharmony_ci	comm = find_cmdline(tep, pid);
58928c2ecf20Sopenharmony_ci	return comm;
58938c2ecf20Sopenharmony_ci}
58948c2ecf20Sopenharmony_ci
58958c2ecf20Sopenharmony_cistatic struct tep_cmdline *
58968c2ecf20Sopenharmony_cipid_from_cmdlist(struct tep_handle *tep, const char *comm, struct tep_cmdline *next)
58978c2ecf20Sopenharmony_ci{
58988c2ecf20Sopenharmony_ci	struct cmdline_list *cmdlist = (struct cmdline_list *)next;
58998c2ecf20Sopenharmony_ci
59008c2ecf20Sopenharmony_ci	if (cmdlist)
59018c2ecf20Sopenharmony_ci		cmdlist = cmdlist->next;
59028c2ecf20Sopenharmony_ci	else
59038c2ecf20Sopenharmony_ci		cmdlist = tep->cmdlist;
59048c2ecf20Sopenharmony_ci
59058c2ecf20Sopenharmony_ci	while (cmdlist && strcmp(cmdlist->comm, comm) != 0)
59068c2ecf20Sopenharmony_ci		cmdlist = cmdlist->next;
59078c2ecf20Sopenharmony_ci
59088c2ecf20Sopenharmony_ci	return (struct tep_cmdline *)cmdlist;
59098c2ecf20Sopenharmony_ci}
59108c2ecf20Sopenharmony_ci
59118c2ecf20Sopenharmony_ci/**
59128c2ecf20Sopenharmony_ci * tep_data_pid_from_comm - return the pid from a given comm
59138c2ecf20Sopenharmony_ci * @tep: a handle to the trace event parser context
59148c2ecf20Sopenharmony_ci * @comm: the cmdline to find the pid from
59158c2ecf20Sopenharmony_ci * @next: the cmdline structure to find the next comm
59168c2ecf20Sopenharmony_ci *
59178c2ecf20Sopenharmony_ci * This returns the cmdline structure that holds a pid for a given
59188c2ecf20Sopenharmony_ci * comm, or NULL if none found. As there may be more than one pid for
59198c2ecf20Sopenharmony_ci * a given comm, the result of this call can be passed back into
59208c2ecf20Sopenharmony_ci * a recurring call in the @next parameter, and then it will find the
59218c2ecf20Sopenharmony_ci * next pid.
59228c2ecf20Sopenharmony_ci * Also, it does a linear search, so it may be slow.
59238c2ecf20Sopenharmony_ci */
59248c2ecf20Sopenharmony_cistruct tep_cmdline *tep_data_pid_from_comm(struct tep_handle *tep, const char *comm,
59258c2ecf20Sopenharmony_ci					   struct tep_cmdline *next)
59268c2ecf20Sopenharmony_ci{
59278c2ecf20Sopenharmony_ci	struct tep_cmdline *cmdline;
59288c2ecf20Sopenharmony_ci
59298c2ecf20Sopenharmony_ci	/*
59308c2ecf20Sopenharmony_ci	 * If the cmdlines have not been converted yet, then use
59318c2ecf20Sopenharmony_ci	 * the list.
59328c2ecf20Sopenharmony_ci	 */
59338c2ecf20Sopenharmony_ci	if (!tep->cmdlines)
59348c2ecf20Sopenharmony_ci		return pid_from_cmdlist(tep, comm, next);
59358c2ecf20Sopenharmony_ci
59368c2ecf20Sopenharmony_ci	if (next) {
59378c2ecf20Sopenharmony_ci		/*
59388c2ecf20Sopenharmony_ci		 * The next pointer could have been still from
59398c2ecf20Sopenharmony_ci		 * a previous call before cmdlines were created
59408c2ecf20Sopenharmony_ci		 */
59418c2ecf20Sopenharmony_ci		if (next < tep->cmdlines ||
59428c2ecf20Sopenharmony_ci		    next >= tep->cmdlines + tep->cmdline_count)
59438c2ecf20Sopenharmony_ci			next = NULL;
59448c2ecf20Sopenharmony_ci		else
59458c2ecf20Sopenharmony_ci			cmdline  = next++;
59468c2ecf20Sopenharmony_ci	}
59478c2ecf20Sopenharmony_ci
59488c2ecf20Sopenharmony_ci	if (!next)
59498c2ecf20Sopenharmony_ci		cmdline = tep->cmdlines;
59508c2ecf20Sopenharmony_ci
59518c2ecf20Sopenharmony_ci	while (cmdline < tep->cmdlines + tep->cmdline_count) {
59528c2ecf20Sopenharmony_ci		if (strcmp(cmdline->comm, comm) == 0)
59538c2ecf20Sopenharmony_ci			return cmdline;
59548c2ecf20Sopenharmony_ci		cmdline++;
59558c2ecf20Sopenharmony_ci	}
59568c2ecf20Sopenharmony_ci	return NULL;
59578c2ecf20Sopenharmony_ci}
59588c2ecf20Sopenharmony_ci
59598c2ecf20Sopenharmony_ci/**
59608c2ecf20Sopenharmony_ci * tep_cmdline_pid - return the pid associated to a given cmdline
59618c2ecf20Sopenharmony_ci * @tep: a handle to the trace event parser context
59628c2ecf20Sopenharmony_ci * @cmdline: The cmdline structure to get the pid from
59638c2ecf20Sopenharmony_ci *
59648c2ecf20Sopenharmony_ci * Returns the pid for a give cmdline. If @cmdline is NULL, then
59658c2ecf20Sopenharmony_ci * -1 is returned.
59668c2ecf20Sopenharmony_ci */
59678c2ecf20Sopenharmony_ciint tep_cmdline_pid(struct tep_handle *tep, struct tep_cmdline *cmdline)
59688c2ecf20Sopenharmony_ci{
59698c2ecf20Sopenharmony_ci	struct cmdline_list *cmdlist = (struct cmdline_list *)cmdline;
59708c2ecf20Sopenharmony_ci
59718c2ecf20Sopenharmony_ci	if (!cmdline)
59728c2ecf20Sopenharmony_ci		return -1;
59738c2ecf20Sopenharmony_ci
59748c2ecf20Sopenharmony_ci	/*
59758c2ecf20Sopenharmony_ci	 * If cmdlines have not been created yet, or cmdline is
59768c2ecf20Sopenharmony_ci	 * not part of the array, then treat it as a cmdlist instead.
59778c2ecf20Sopenharmony_ci	 */
59788c2ecf20Sopenharmony_ci	if (!tep->cmdlines ||
59798c2ecf20Sopenharmony_ci	    cmdline < tep->cmdlines ||
59808c2ecf20Sopenharmony_ci	    cmdline >= tep->cmdlines + tep->cmdline_count)
59818c2ecf20Sopenharmony_ci		return cmdlist->pid;
59828c2ecf20Sopenharmony_ci
59838c2ecf20Sopenharmony_ci	return cmdline->pid;
59848c2ecf20Sopenharmony_ci}
59858c2ecf20Sopenharmony_ci
59868c2ecf20Sopenharmony_ci/*
59878c2ecf20Sopenharmony_ci * This parses the raw @data using the given @event information and
59888c2ecf20Sopenharmony_ci * writes the print format into the trace_seq.
59898c2ecf20Sopenharmony_ci */
59908c2ecf20Sopenharmony_cistatic void print_event_info(struct trace_seq *s, char *format, bool raw,
59918c2ecf20Sopenharmony_ci			     struct tep_event *event, struct tep_record *record)
59928c2ecf20Sopenharmony_ci{
59938c2ecf20Sopenharmony_ci	int print_pretty = 1;
59948c2ecf20Sopenharmony_ci
59958c2ecf20Sopenharmony_ci	if (raw || (event->flags & TEP_EVENT_FL_PRINTRAW))
59968c2ecf20Sopenharmony_ci		tep_print_fields(s, record->data, record->size, event);
59978c2ecf20Sopenharmony_ci	else {
59988c2ecf20Sopenharmony_ci
59998c2ecf20Sopenharmony_ci		if (event->handler && !(event->flags & TEP_EVENT_FL_NOHANDLE))
60008c2ecf20Sopenharmony_ci			print_pretty = event->handler(s, record, event,
60018c2ecf20Sopenharmony_ci						      event->context);
60028c2ecf20Sopenharmony_ci
60038c2ecf20Sopenharmony_ci		if (print_pretty)
60048c2ecf20Sopenharmony_ci			pretty_print(s, record->data, record->size, event);
60058c2ecf20Sopenharmony_ci	}
60068c2ecf20Sopenharmony_ci
60078c2ecf20Sopenharmony_ci	trace_seq_terminate(s);
60088c2ecf20Sopenharmony_ci}
60098c2ecf20Sopenharmony_ci
60108c2ecf20Sopenharmony_ci/**
60118c2ecf20Sopenharmony_ci * tep_find_event_by_record - return the event from a given record
60128c2ecf20Sopenharmony_ci * @tep: a handle to the trace event parser context
60138c2ecf20Sopenharmony_ci * @record: The record to get the event from
60148c2ecf20Sopenharmony_ci *
60158c2ecf20Sopenharmony_ci * Returns the associated event for a given record, or NULL if non is
60168c2ecf20Sopenharmony_ci * is found.
60178c2ecf20Sopenharmony_ci */
60188c2ecf20Sopenharmony_cistruct tep_event *
60198c2ecf20Sopenharmony_citep_find_event_by_record(struct tep_handle *tep, struct tep_record *record)
60208c2ecf20Sopenharmony_ci{
60218c2ecf20Sopenharmony_ci	int type;
60228c2ecf20Sopenharmony_ci
60238c2ecf20Sopenharmony_ci	if (record->size < 0) {
60248c2ecf20Sopenharmony_ci		do_warning("ug! negative record size %d", record->size);
60258c2ecf20Sopenharmony_ci		return NULL;
60268c2ecf20Sopenharmony_ci	}
60278c2ecf20Sopenharmony_ci
60288c2ecf20Sopenharmony_ci	type = trace_parse_common_type(tep, record->data);
60298c2ecf20Sopenharmony_ci
60308c2ecf20Sopenharmony_ci	return tep_find_event(tep, type);
60318c2ecf20Sopenharmony_ci}
60328c2ecf20Sopenharmony_ci
60338c2ecf20Sopenharmony_ci/*
60348c2ecf20Sopenharmony_ci * Writes the timestamp of the record into @s. Time divisor and precision can be
60358c2ecf20Sopenharmony_ci * specified as part of printf @format string. Example:
60368c2ecf20Sopenharmony_ci *	"%3.1000d" - divide the time by 1000 and print the first 3 digits
60378c2ecf20Sopenharmony_ci *	before the dot. Thus, the timestamp "123456000" will be printed as
60388c2ecf20Sopenharmony_ci *	"123.456"
60398c2ecf20Sopenharmony_ci */
60408c2ecf20Sopenharmony_cistatic void print_event_time(struct tep_handle *tep, struct trace_seq *s,
60418c2ecf20Sopenharmony_ci				 char *format, struct tep_event *event,
60428c2ecf20Sopenharmony_ci				 struct tep_record *record)
60438c2ecf20Sopenharmony_ci{
60448c2ecf20Sopenharmony_ci	unsigned long long time;
60458c2ecf20Sopenharmony_ci	char *divstr;
60468c2ecf20Sopenharmony_ci	int prec = 0, pr;
60478c2ecf20Sopenharmony_ci	int div = 0;
60488c2ecf20Sopenharmony_ci	int p10 = 1;
60498c2ecf20Sopenharmony_ci
60508c2ecf20Sopenharmony_ci	if (isdigit(*(format + 1)))
60518c2ecf20Sopenharmony_ci		prec = atoi(format + 1);
60528c2ecf20Sopenharmony_ci	divstr = strchr(format, '.');
60538c2ecf20Sopenharmony_ci	if (divstr && isdigit(*(divstr + 1)))
60548c2ecf20Sopenharmony_ci		div = atoi(divstr + 1);
60558c2ecf20Sopenharmony_ci	time = record->ts;
60568c2ecf20Sopenharmony_ci	if (div) {
60578c2ecf20Sopenharmony_ci		time += div / 2;
60588c2ecf20Sopenharmony_ci		time /= div;
60598c2ecf20Sopenharmony_ci	}
60608c2ecf20Sopenharmony_ci	pr = prec;
60618c2ecf20Sopenharmony_ci	while (pr--)
60628c2ecf20Sopenharmony_ci		p10 *= 10;
60638c2ecf20Sopenharmony_ci
60648c2ecf20Sopenharmony_ci	if (p10 > 1 && p10 < time)
60658c2ecf20Sopenharmony_ci		trace_seq_printf(s, "%5llu.%0*llu", time / p10, prec, time % p10);
60668c2ecf20Sopenharmony_ci	else
60678c2ecf20Sopenharmony_ci		trace_seq_printf(s, "%12llu", time);
60688c2ecf20Sopenharmony_ci}
60698c2ecf20Sopenharmony_ci
60708c2ecf20Sopenharmony_cistruct print_event_type {
60718c2ecf20Sopenharmony_ci	enum {
60728c2ecf20Sopenharmony_ci		EVENT_TYPE_INT = 1,
60738c2ecf20Sopenharmony_ci		EVENT_TYPE_STRING,
60748c2ecf20Sopenharmony_ci		EVENT_TYPE_UNKNOWN,
60758c2ecf20Sopenharmony_ci	} type;
60768c2ecf20Sopenharmony_ci	char format[32];
60778c2ecf20Sopenharmony_ci};
60788c2ecf20Sopenharmony_ci
60798c2ecf20Sopenharmony_cistatic void print_string(struct tep_handle *tep, struct trace_seq *s,
60808c2ecf20Sopenharmony_ci			 struct tep_record *record, struct tep_event *event,
60818c2ecf20Sopenharmony_ci			 const char *arg, struct print_event_type *type)
60828c2ecf20Sopenharmony_ci{
60838c2ecf20Sopenharmony_ci	const char *comm;
60848c2ecf20Sopenharmony_ci	int pid;
60858c2ecf20Sopenharmony_ci
60868c2ecf20Sopenharmony_ci	if (strncmp(arg, TEP_PRINT_LATENCY, strlen(TEP_PRINT_LATENCY)) == 0) {
60878c2ecf20Sopenharmony_ci		data_latency_format(tep, s, type->format, record);
60888c2ecf20Sopenharmony_ci	} else if (strncmp(arg, TEP_PRINT_COMM, strlen(TEP_PRINT_COMM)) == 0) {
60898c2ecf20Sopenharmony_ci		pid = parse_common_pid(tep, record->data);
60908c2ecf20Sopenharmony_ci		comm = find_cmdline(tep, pid);
60918c2ecf20Sopenharmony_ci		trace_seq_printf(s, type->format, comm);
60928c2ecf20Sopenharmony_ci	} else if (strncmp(arg, TEP_PRINT_INFO_RAW, strlen(TEP_PRINT_INFO_RAW)) == 0) {
60938c2ecf20Sopenharmony_ci		print_event_info(s, type->format, true, event, record);
60948c2ecf20Sopenharmony_ci	} else if (strncmp(arg, TEP_PRINT_INFO, strlen(TEP_PRINT_INFO)) == 0) {
60958c2ecf20Sopenharmony_ci		print_event_info(s, type->format, false, event, record);
60968c2ecf20Sopenharmony_ci	} else if  (strncmp(arg, TEP_PRINT_NAME, strlen(TEP_PRINT_NAME)) == 0) {
60978c2ecf20Sopenharmony_ci		trace_seq_printf(s, type->format, event->name);
60988c2ecf20Sopenharmony_ci	} else {
60998c2ecf20Sopenharmony_ci		trace_seq_printf(s, "[UNKNOWN TEP TYPE %s]", arg);
61008c2ecf20Sopenharmony_ci	}
61018c2ecf20Sopenharmony_ci
61028c2ecf20Sopenharmony_ci}
61038c2ecf20Sopenharmony_ci
61048c2ecf20Sopenharmony_cistatic void print_int(struct tep_handle *tep, struct trace_seq *s,
61058c2ecf20Sopenharmony_ci		      struct tep_record *record, struct tep_event *event,
61068c2ecf20Sopenharmony_ci		      int arg, struct print_event_type *type)
61078c2ecf20Sopenharmony_ci{
61088c2ecf20Sopenharmony_ci	int param;
61098c2ecf20Sopenharmony_ci
61108c2ecf20Sopenharmony_ci	switch (arg) {
61118c2ecf20Sopenharmony_ci	case TEP_PRINT_CPU:
61128c2ecf20Sopenharmony_ci		param = record->cpu;
61138c2ecf20Sopenharmony_ci		break;
61148c2ecf20Sopenharmony_ci	case TEP_PRINT_PID:
61158c2ecf20Sopenharmony_ci		param = parse_common_pid(tep, record->data);
61168c2ecf20Sopenharmony_ci		break;
61178c2ecf20Sopenharmony_ci	case TEP_PRINT_TIME:
61188c2ecf20Sopenharmony_ci		return print_event_time(tep, s, type->format, event, record);
61198c2ecf20Sopenharmony_ci	default:
61208c2ecf20Sopenharmony_ci		return;
61218c2ecf20Sopenharmony_ci	}
61228c2ecf20Sopenharmony_ci	trace_seq_printf(s, type->format, param);
61238c2ecf20Sopenharmony_ci}
61248c2ecf20Sopenharmony_ci
61258c2ecf20Sopenharmony_cistatic int tep_print_event_param_type(char *format,
61268c2ecf20Sopenharmony_ci				      struct print_event_type *type)
61278c2ecf20Sopenharmony_ci{
61288c2ecf20Sopenharmony_ci	char *str = format + 1;
61298c2ecf20Sopenharmony_ci	int i = 1;
61308c2ecf20Sopenharmony_ci
61318c2ecf20Sopenharmony_ci	type->type = EVENT_TYPE_UNKNOWN;
61328c2ecf20Sopenharmony_ci	while (*str) {
61338c2ecf20Sopenharmony_ci		switch (*str) {
61348c2ecf20Sopenharmony_ci		case 'd':
61358c2ecf20Sopenharmony_ci		case 'u':
61368c2ecf20Sopenharmony_ci		case 'i':
61378c2ecf20Sopenharmony_ci		case 'x':
61388c2ecf20Sopenharmony_ci		case 'X':
61398c2ecf20Sopenharmony_ci		case 'o':
61408c2ecf20Sopenharmony_ci			type->type = EVENT_TYPE_INT;
61418c2ecf20Sopenharmony_ci			break;
61428c2ecf20Sopenharmony_ci		case 's':
61438c2ecf20Sopenharmony_ci			type->type = EVENT_TYPE_STRING;
61448c2ecf20Sopenharmony_ci			break;
61458c2ecf20Sopenharmony_ci		}
61468c2ecf20Sopenharmony_ci		str++;
61478c2ecf20Sopenharmony_ci		i++;
61488c2ecf20Sopenharmony_ci		if (type->type != EVENT_TYPE_UNKNOWN)
61498c2ecf20Sopenharmony_ci			break;
61508c2ecf20Sopenharmony_ci	}
61518c2ecf20Sopenharmony_ci	memset(type->format, 0, 32);
61528c2ecf20Sopenharmony_ci	memcpy(type->format, format, i < 32 ? i : 31);
61538c2ecf20Sopenharmony_ci	return i;
61548c2ecf20Sopenharmony_ci}
61558c2ecf20Sopenharmony_ci
61568c2ecf20Sopenharmony_ci/**
61578c2ecf20Sopenharmony_ci * tep_print_event - Write various event information
61588c2ecf20Sopenharmony_ci * @tep: a handle to the trace event parser context
61598c2ecf20Sopenharmony_ci * @s: the trace_seq to write to
61608c2ecf20Sopenharmony_ci * @record: The record to get the event from
61618c2ecf20Sopenharmony_ci * @format: a printf format string. Supported event fileds:
61628c2ecf20Sopenharmony_ci *	TEP_PRINT_PID, "%d" - event PID
61638c2ecf20Sopenharmony_ci *	TEP_PRINT_CPU, "%d" - event CPU
61648c2ecf20Sopenharmony_ci *	TEP_PRINT_COMM, "%s" - event command string
61658c2ecf20Sopenharmony_ci *	TEP_PRINT_NAME, "%s" - event name
61668c2ecf20Sopenharmony_ci *	TEP_PRINT_LATENCY, "%s" - event latency
61678c2ecf20Sopenharmony_ci *	TEP_PRINT_TIME, %d - event time stamp. A divisor and precision
61688c2ecf20Sopenharmony_ci *			can be specified as part of this format string:
61698c2ecf20Sopenharmony_ci *			"%precision.divisord". Example:
61708c2ecf20Sopenharmony_ci *			"%3.1000d" - divide the time by 1000 and print the first
61718c2ecf20Sopenharmony_ci *			3 digits before the dot. Thus, the time stamp
61728c2ecf20Sopenharmony_ci *			"123456000" will be printed as "123.456"
61738c2ecf20Sopenharmony_ci *	TEP_PRINT_INFO, "%s" - event information. If any width is specified in
61748c2ecf20Sopenharmony_ci *			the format string, the event information will be printed
61758c2ecf20Sopenharmony_ci *			in raw format.
61768c2ecf20Sopenharmony_ci * Writes the specified event information into @s.
61778c2ecf20Sopenharmony_ci */
61788c2ecf20Sopenharmony_civoid tep_print_event(struct tep_handle *tep, struct trace_seq *s,
61798c2ecf20Sopenharmony_ci		     struct tep_record *record, const char *fmt, ...)
61808c2ecf20Sopenharmony_ci{
61818c2ecf20Sopenharmony_ci	struct print_event_type type;
61828c2ecf20Sopenharmony_ci	char *format = strdup(fmt);
61838c2ecf20Sopenharmony_ci	char *current = format;
61848c2ecf20Sopenharmony_ci	char *str = format;
61858c2ecf20Sopenharmony_ci	int offset;
61868c2ecf20Sopenharmony_ci	va_list args;
61878c2ecf20Sopenharmony_ci	struct tep_event *event;
61888c2ecf20Sopenharmony_ci
61898c2ecf20Sopenharmony_ci	if (!format)
61908c2ecf20Sopenharmony_ci		return;
61918c2ecf20Sopenharmony_ci
61928c2ecf20Sopenharmony_ci	event = tep_find_event_by_record(tep, record);
61938c2ecf20Sopenharmony_ci	va_start(args, fmt);
61948c2ecf20Sopenharmony_ci	while (*current) {
61958c2ecf20Sopenharmony_ci		current = strchr(str, '%');
61968c2ecf20Sopenharmony_ci		if (!current) {
61978c2ecf20Sopenharmony_ci			trace_seq_puts(s, str);
61988c2ecf20Sopenharmony_ci			break;
61998c2ecf20Sopenharmony_ci		}
62008c2ecf20Sopenharmony_ci		memset(&type, 0, sizeof(type));
62018c2ecf20Sopenharmony_ci		offset = tep_print_event_param_type(current, &type);
62028c2ecf20Sopenharmony_ci		*current = '\0';
62038c2ecf20Sopenharmony_ci		trace_seq_puts(s, str);
62048c2ecf20Sopenharmony_ci		current += offset;
62058c2ecf20Sopenharmony_ci		switch (type.type) {
62068c2ecf20Sopenharmony_ci		case EVENT_TYPE_STRING:
62078c2ecf20Sopenharmony_ci			print_string(tep, s, record, event,
62088c2ecf20Sopenharmony_ci				     va_arg(args, char*), &type);
62098c2ecf20Sopenharmony_ci			break;
62108c2ecf20Sopenharmony_ci		case EVENT_TYPE_INT:
62118c2ecf20Sopenharmony_ci			print_int(tep, s, record, event,
62128c2ecf20Sopenharmony_ci				  va_arg(args, int), &type);
62138c2ecf20Sopenharmony_ci			break;
62148c2ecf20Sopenharmony_ci		case EVENT_TYPE_UNKNOWN:
62158c2ecf20Sopenharmony_ci		default:
62168c2ecf20Sopenharmony_ci			trace_seq_printf(s, "[UNKNOWN TYPE]");
62178c2ecf20Sopenharmony_ci			break;
62188c2ecf20Sopenharmony_ci		}
62198c2ecf20Sopenharmony_ci		str = current;
62208c2ecf20Sopenharmony_ci
62218c2ecf20Sopenharmony_ci	}
62228c2ecf20Sopenharmony_ci	va_end(args);
62238c2ecf20Sopenharmony_ci	free(format);
62248c2ecf20Sopenharmony_ci}
62258c2ecf20Sopenharmony_ci
62268c2ecf20Sopenharmony_cistatic int events_id_cmp(const void *a, const void *b)
62278c2ecf20Sopenharmony_ci{
62288c2ecf20Sopenharmony_ci	struct tep_event * const * ea = a;
62298c2ecf20Sopenharmony_ci	struct tep_event * const * eb = b;
62308c2ecf20Sopenharmony_ci
62318c2ecf20Sopenharmony_ci	if ((*ea)->id < (*eb)->id)
62328c2ecf20Sopenharmony_ci		return -1;
62338c2ecf20Sopenharmony_ci
62348c2ecf20Sopenharmony_ci	if ((*ea)->id > (*eb)->id)
62358c2ecf20Sopenharmony_ci		return 1;
62368c2ecf20Sopenharmony_ci
62378c2ecf20Sopenharmony_ci	return 0;
62388c2ecf20Sopenharmony_ci}
62398c2ecf20Sopenharmony_ci
62408c2ecf20Sopenharmony_cistatic int events_name_cmp(const void *a, const void *b)
62418c2ecf20Sopenharmony_ci{
62428c2ecf20Sopenharmony_ci	struct tep_event * const * ea = a;
62438c2ecf20Sopenharmony_ci	struct tep_event * const * eb = b;
62448c2ecf20Sopenharmony_ci	int res;
62458c2ecf20Sopenharmony_ci
62468c2ecf20Sopenharmony_ci	res = strcmp((*ea)->name, (*eb)->name);
62478c2ecf20Sopenharmony_ci	if (res)
62488c2ecf20Sopenharmony_ci		return res;
62498c2ecf20Sopenharmony_ci
62508c2ecf20Sopenharmony_ci	res = strcmp((*ea)->system, (*eb)->system);
62518c2ecf20Sopenharmony_ci	if (res)
62528c2ecf20Sopenharmony_ci		return res;
62538c2ecf20Sopenharmony_ci
62548c2ecf20Sopenharmony_ci	return events_id_cmp(a, b);
62558c2ecf20Sopenharmony_ci}
62568c2ecf20Sopenharmony_ci
62578c2ecf20Sopenharmony_cistatic int events_system_cmp(const void *a, const void *b)
62588c2ecf20Sopenharmony_ci{
62598c2ecf20Sopenharmony_ci	struct tep_event * const * ea = a;
62608c2ecf20Sopenharmony_ci	struct tep_event * const * eb = b;
62618c2ecf20Sopenharmony_ci	int res;
62628c2ecf20Sopenharmony_ci
62638c2ecf20Sopenharmony_ci	res = strcmp((*ea)->system, (*eb)->system);
62648c2ecf20Sopenharmony_ci	if (res)
62658c2ecf20Sopenharmony_ci		return res;
62668c2ecf20Sopenharmony_ci
62678c2ecf20Sopenharmony_ci	res = strcmp((*ea)->name, (*eb)->name);
62688c2ecf20Sopenharmony_ci	if (res)
62698c2ecf20Sopenharmony_ci		return res;
62708c2ecf20Sopenharmony_ci
62718c2ecf20Sopenharmony_ci	return events_id_cmp(a, b);
62728c2ecf20Sopenharmony_ci}
62738c2ecf20Sopenharmony_ci
62748c2ecf20Sopenharmony_cistatic struct tep_event **list_events_copy(struct tep_handle *tep)
62758c2ecf20Sopenharmony_ci{
62768c2ecf20Sopenharmony_ci	struct tep_event **events;
62778c2ecf20Sopenharmony_ci
62788c2ecf20Sopenharmony_ci	if (!tep)
62798c2ecf20Sopenharmony_ci		return NULL;
62808c2ecf20Sopenharmony_ci
62818c2ecf20Sopenharmony_ci	events = malloc(sizeof(*events) * (tep->nr_events + 1));
62828c2ecf20Sopenharmony_ci	if (!events)
62838c2ecf20Sopenharmony_ci		return NULL;
62848c2ecf20Sopenharmony_ci
62858c2ecf20Sopenharmony_ci	memcpy(events, tep->events, sizeof(*events) * tep->nr_events);
62868c2ecf20Sopenharmony_ci	events[tep->nr_events] = NULL;
62878c2ecf20Sopenharmony_ci	return events;
62888c2ecf20Sopenharmony_ci}
62898c2ecf20Sopenharmony_ci
62908c2ecf20Sopenharmony_cistatic void list_events_sort(struct tep_event **events, int nr_events,
62918c2ecf20Sopenharmony_ci			     enum tep_event_sort_type sort_type)
62928c2ecf20Sopenharmony_ci{
62938c2ecf20Sopenharmony_ci	int (*sort)(const void *a, const void *b);
62948c2ecf20Sopenharmony_ci
62958c2ecf20Sopenharmony_ci	switch (sort_type) {
62968c2ecf20Sopenharmony_ci	case TEP_EVENT_SORT_ID:
62978c2ecf20Sopenharmony_ci		sort = events_id_cmp;
62988c2ecf20Sopenharmony_ci		break;
62998c2ecf20Sopenharmony_ci	case TEP_EVENT_SORT_NAME:
63008c2ecf20Sopenharmony_ci		sort = events_name_cmp;
63018c2ecf20Sopenharmony_ci		break;
63028c2ecf20Sopenharmony_ci	case TEP_EVENT_SORT_SYSTEM:
63038c2ecf20Sopenharmony_ci		sort = events_system_cmp;
63048c2ecf20Sopenharmony_ci		break;
63058c2ecf20Sopenharmony_ci	default:
63068c2ecf20Sopenharmony_ci		sort = NULL;
63078c2ecf20Sopenharmony_ci	}
63088c2ecf20Sopenharmony_ci
63098c2ecf20Sopenharmony_ci	if (sort)
63108c2ecf20Sopenharmony_ci		qsort(events, nr_events, sizeof(*events), sort);
63118c2ecf20Sopenharmony_ci}
63128c2ecf20Sopenharmony_ci
63138c2ecf20Sopenharmony_ci/**
63148c2ecf20Sopenharmony_ci * tep_list_events - Get events, sorted by given criteria.
63158c2ecf20Sopenharmony_ci * @tep: a handle to the tep context
63168c2ecf20Sopenharmony_ci * @sort_type: desired sort order of the events in the array
63178c2ecf20Sopenharmony_ci *
63188c2ecf20Sopenharmony_ci * Returns an array of pointers to all events, sorted by the given
63198c2ecf20Sopenharmony_ci * @sort_type criteria. The last element of the array is NULL. The returned
63208c2ecf20Sopenharmony_ci * memory must not be freed, it is managed by the library.
63218c2ecf20Sopenharmony_ci * The function is not thread safe.
63228c2ecf20Sopenharmony_ci */
63238c2ecf20Sopenharmony_cistruct tep_event **tep_list_events(struct tep_handle *tep,
63248c2ecf20Sopenharmony_ci				   enum tep_event_sort_type sort_type)
63258c2ecf20Sopenharmony_ci{
63268c2ecf20Sopenharmony_ci	struct tep_event **events;
63278c2ecf20Sopenharmony_ci
63288c2ecf20Sopenharmony_ci	if (!tep)
63298c2ecf20Sopenharmony_ci		return NULL;
63308c2ecf20Sopenharmony_ci
63318c2ecf20Sopenharmony_ci	events = tep->sort_events;
63328c2ecf20Sopenharmony_ci	if (events && tep->last_type == sort_type)
63338c2ecf20Sopenharmony_ci		return events;
63348c2ecf20Sopenharmony_ci
63358c2ecf20Sopenharmony_ci	if (!events) {
63368c2ecf20Sopenharmony_ci		events = list_events_copy(tep);
63378c2ecf20Sopenharmony_ci		if (!events)
63388c2ecf20Sopenharmony_ci			return NULL;
63398c2ecf20Sopenharmony_ci
63408c2ecf20Sopenharmony_ci		tep->sort_events = events;
63418c2ecf20Sopenharmony_ci
63428c2ecf20Sopenharmony_ci		/* the internal events are sorted by id */
63438c2ecf20Sopenharmony_ci		if (sort_type == TEP_EVENT_SORT_ID) {
63448c2ecf20Sopenharmony_ci			tep->last_type = sort_type;
63458c2ecf20Sopenharmony_ci			return events;
63468c2ecf20Sopenharmony_ci		}
63478c2ecf20Sopenharmony_ci	}
63488c2ecf20Sopenharmony_ci
63498c2ecf20Sopenharmony_ci	list_events_sort(events, tep->nr_events, sort_type);
63508c2ecf20Sopenharmony_ci	tep->last_type = sort_type;
63518c2ecf20Sopenharmony_ci
63528c2ecf20Sopenharmony_ci	return events;
63538c2ecf20Sopenharmony_ci}
63548c2ecf20Sopenharmony_ci
63558c2ecf20Sopenharmony_ci
63568c2ecf20Sopenharmony_ci/**
63578c2ecf20Sopenharmony_ci * tep_list_events_copy - Thread safe version of tep_list_events()
63588c2ecf20Sopenharmony_ci * @tep: a handle to the tep context
63598c2ecf20Sopenharmony_ci * @sort_type: desired sort order of the events in the array
63608c2ecf20Sopenharmony_ci *
63618c2ecf20Sopenharmony_ci * Returns an array of pointers to all events, sorted by the given
63628c2ecf20Sopenharmony_ci * @sort_type criteria. The last element of the array is NULL. The returned
63638c2ecf20Sopenharmony_ci * array is newly allocated inside the function and must be freed by the caller
63648c2ecf20Sopenharmony_ci */
63658c2ecf20Sopenharmony_cistruct tep_event **tep_list_events_copy(struct tep_handle *tep,
63668c2ecf20Sopenharmony_ci					enum tep_event_sort_type sort_type)
63678c2ecf20Sopenharmony_ci{
63688c2ecf20Sopenharmony_ci	struct tep_event **events;
63698c2ecf20Sopenharmony_ci
63708c2ecf20Sopenharmony_ci	if (!tep)
63718c2ecf20Sopenharmony_ci		return NULL;
63728c2ecf20Sopenharmony_ci
63738c2ecf20Sopenharmony_ci	events = list_events_copy(tep);
63748c2ecf20Sopenharmony_ci	if (!events)
63758c2ecf20Sopenharmony_ci		return NULL;
63768c2ecf20Sopenharmony_ci
63778c2ecf20Sopenharmony_ci	/* the internal events are sorted by id */
63788c2ecf20Sopenharmony_ci	if (sort_type == TEP_EVENT_SORT_ID)
63798c2ecf20Sopenharmony_ci		return events;
63808c2ecf20Sopenharmony_ci
63818c2ecf20Sopenharmony_ci	list_events_sort(events, tep->nr_events, sort_type);
63828c2ecf20Sopenharmony_ci
63838c2ecf20Sopenharmony_ci	return events;
63848c2ecf20Sopenharmony_ci}
63858c2ecf20Sopenharmony_ci
63868c2ecf20Sopenharmony_cistatic struct tep_format_field **
63878c2ecf20Sopenharmony_ciget_event_fields(const char *type, const char *name,
63888c2ecf20Sopenharmony_ci		 int count, struct tep_format_field *list)
63898c2ecf20Sopenharmony_ci{
63908c2ecf20Sopenharmony_ci	struct tep_format_field **fields;
63918c2ecf20Sopenharmony_ci	struct tep_format_field *field;
63928c2ecf20Sopenharmony_ci	int i = 0;
63938c2ecf20Sopenharmony_ci
63948c2ecf20Sopenharmony_ci	fields = malloc(sizeof(*fields) * (count + 1));
63958c2ecf20Sopenharmony_ci	if (!fields)
63968c2ecf20Sopenharmony_ci		return NULL;
63978c2ecf20Sopenharmony_ci
63988c2ecf20Sopenharmony_ci	for (field = list; field; field = field->next) {
63998c2ecf20Sopenharmony_ci		fields[i++] = field;
64008c2ecf20Sopenharmony_ci		if (i == count + 1) {
64018c2ecf20Sopenharmony_ci			do_warning("event %s has more %s fields than specified",
64028c2ecf20Sopenharmony_ci				name, type);
64038c2ecf20Sopenharmony_ci			i--;
64048c2ecf20Sopenharmony_ci			break;
64058c2ecf20Sopenharmony_ci		}
64068c2ecf20Sopenharmony_ci	}
64078c2ecf20Sopenharmony_ci
64088c2ecf20Sopenharmony_ci	if (i != count)
64098c2ecf20Sopenharmony_ci		do_warning("event %s has less %s fields than specified",
64108c2ecf20Sopenharmony_ci			name, type);
64118c2ecf20Sopenharmony_ci
64128c2ecf20Sopenharmony_ci	fields[i] = NULL;
64138c2ecf20Sopenharmony_ci
64148c2ecf20Sopenharmony_ci	return fields;
64158c2ecf20Sopenharmony_ci}
64168c2ecf20Sopenharmony_ci
64178c2ecf20Sopenharmony_ci/**
64188c2ecf20Sopenharmony_ci * tep_event_common_fields - return a list of common fields for an event
64198c2ecf20Sopenharmony_ci * @event: the event to return the common fields of.
64208c2ecf20Sopenharmony_ci *
64218c2ecf20Sopenharmony_ci * Returns an allocated array of fields. The last item in the array is NULL.
64228c2ecf20Sopenharmony_ci * The array must be freed with free().
64238c2ecf20Sopenharmony_ci */
64248c2ecf20Sopenharmony_cistruct tep_format_field **tep_event_common_fields(struct tep_event *event)
64258c2ecf20Sopenharmony_ci{
64268c2ecf20Sopenharmony_ci	return get_event_fields("common", event->name,
64278c2ecf20Sopenharmony_ci				event->format.nr_common,
64288c2ecf20Sopenharmony_ci				event->format.common_fields);
64298c2ecf20Sopenharmony_ci}
64308c2ecf20Sopenharmony_ci
64318c2ecf20Sopenharmony_ci/**
64328c2ecf20Sopenharmony_ci * tep_event_fields - return a list of event specific fields for an event
64338c2ecf20Sopenharmony_ci * @event: the event to return the fields of.
64348c2ecf20Sopenharmony_ci *
64358c2ecf20Sopenharmony_ci * Returns an allocated array of fields. The last item in the array is NULL.
64368c2ecf20Sopenharmony_ci * The array must be freed with free().
64378c2ecf20Sopenharmony_ci */
64388c2ecf20Sopenharmony_cistruct tep_format_field **tep_event_fields(struct tep_event *event)
64398c2ecf20Sopenharmony_ci{
64408c2ecf20Sopenharmony_ci	return get_event_fields("event", event->name,
64418c2ecf20Sopenharmony_ci				event->format.nr_fields,
64428c2ecf20Sopenharmony_ci				event->format.fields);
64438c2ecf20Sopenharmony_ci}
64448c2ecf20Sopenharmony_ci
64458c2ecf20Sopenharmony_cistatic void print_fields(struct trace_seq *s, struct tep_print_flag_sym *field)
64468c2ecf20Sopenharmony_ci{
64478c2ecf20Sopenharmony_ci	trace_seq_printf(s, "{ %s, %s }", field->value, field->str);
64488c2ecf20Sopenharmony_ci	if (field->next) {
64498c2ecf20Sopenharmony_ci		trace_seq_puts(s, ", ");
64508c2ecf20Sopenharmony_ci		print_fields(s, field->next);
64518c2ecf20Sopenharmony_ci	}
64528c2ecf20Sopenharmony_ci}
64538c2ecf20Sopenharmony_ci
64548c2ecf20Sopenharmony_ci/* for debugging */
64558c2ecf20Sopenharmony_cistatic void print_args(struct tep_print_arg *args)
64568c2ecf20Sopenharmony_ci{
64578c2ecf20Sopenharmony_ci	int print_paren = 1;
64588c2ecf20Sopenharmony_ci	struct trace_seq s;
64598c2ecf20Sopenharmony_ci
64608c2ecf20Sopenharmony_ci	switch (args->type) {
64618c2ecf20Sopenharmony_ci	case TEP_PRINT_NULL:
64628c2ecf20Sopenharmony_ci		printf("null");
64638c2ecf20Sopenharmony_ci		break;
64648c2ecf20Sopenharmony_ci	case TEP_PRINT_ATOM:
64658c2ecf20Sopenharmony_ci		printf("%s", args->atom.atom);
64668c2ecf20Sopenharmony_ci		break;
64678c2ecf20Sopenharmony_ci	case TEP_PRINT_FIELD:
64688c2ecf20Sopenharmony_ci		printf("REC->%s", args->field.name);
64698c2ecf20Sopenharmony_ci		break;
64708c2ecf20Sopenharmony_ci	case TEP_PRINT_FLAGS:
64718c2ecf20Sopenharmony_ci		printf("__print_flags(");
64728c2ecf20Sopenharmony_ci		print_args(args->flags.field);
64738c2ecf20Sopenharmony_ci		printf(", %s, ", args->flags.delim);
64748c2ecf20Sopenharmony_ci		trace_seq_init(&s);
64758c2ecf20Sopenharmony_ci		print_fields(&s, args->flags.flags);
64768c2ecf20Sopenharmony_ci		trace_seq_do_printf(&s);
64778c2ecf20Sopenharmony_ci		trace_seq_destroy(&s);
64788c2ecf20Sopenharmony_ci		printf(")");
64798c2ecf20Sopenharmony_ci		break;
64808c2ecf20Sopenharmony_ci	case TEP_PRINT_SYMBOL:
64818c2ecf20Sopenharmony_ci		printf("__print_symbolic(");
64828c2ecf20Sopenharmony_ci		print_args(args->symbol.field);
64838c2ecf20Sopenharmony_ci		printf(", ");
64848c2ecf20Sopenharmony_ci		trace_seq_init(&s);
64858c2ecf20Sopenharmony_ci		print_fields(&s, args->symbol.symbols);
64868c2ecf20Sopenharmony_ci		trace_seq_do_printf(&s);
64878c2ecf20Sopenharmony_ci		trace_seq_destroy(&s);
64888c2ecf20Sopenharmony_ci		printf(")");
64898c2ecf20Sopenharmony_ci		break;
64908c2ecf20Sopenharmony_ci	case TEP_PRINT_HEX:
64918c2ecf20Sopenharmony_ci		printf("__print_hex(");
64928c2ecf20Sopenharmony_ci		print_args(args->hex.field);
64938c2ecf20Sopenharmony_ci		printf(", ");
64948c2ecf20Sopenharmony_ci		print_args(args->hex.size);
64958c2ecf20Sopenharmony_ci		printf(")");
64968c2ecf20Sopenharmony_ci		break;
64978c2ecf20Sopenharmony_ci	case TEP_PRINT_HEX_STR:
64988c2ecf20Sopenharmony_ci		printf("__print_hex_str(");
64998c2ecf20Sopenharmony_ci		print_args(args->hex.field);
65008c2ecf20Sopenharmony_ci		printf(", ");
65018c2ecf20Sopenharmony_ci		print_args(args->hex.size);
65028c2ecf20Sopenharmony_ci		printf(")");
65038c2ecf20Sopenharmony_ci		break;
65048c2ecf20Sopenharmony_ci	case TEP_PRINT_INT_ARRAY:
65058c2ecf20Sopenharmony_ci		printf("__print_array(");
65068c2ecf20Sopenharmony_ci		print_args(args->int_array.field);
65078c2ecf20Sopenharmony_ci		printf(", ");
65088c2ecf20Sopenharmony_ci		print_args(args->int_array.count);
65098c2ecf20Sopenharmony_ci		printf(", ");
65108c2ecf20Sopenharmony_ci		print_args(args->int_array.el_size);
65118c2ecf20Sopenharmony_ci		printf(")");
65128c2ecf20Sopenharmony_ci		break;
65138c2ecf20Sopenharmony_ci	case TEP_PRINT_STRING:
65148c2ecf20Sopenharmony_ci	case TEP_PRINT_BSTRING:
65158c2ecf20Sopenharmony_ci		printf("__get_str(%s)", args->string.string);
65168c2ecf20Sopenharmony_ci		break;
65178c2ecf20Sopenharmony_ci	case TEP_PRINT_BITMASK:
65188c2ecf20Sopenharmony_ci		printf("__get_bitmask(%s)", args->bitmask.bitmask);
65198c2ecf20Sopenharmony_ci		break;
65208c2ecf20Sopenharmony_ci	case TEP_PRINT_TYPE:
65218c2ecf20Sopenharmony_ci		printf("(%s)", args->typecast.type);
65228c2ecf20Sopenharmony_ci		print_args(args->typecast.item);
65238c2ecf20Sopenharmony_ci		break;
65248c2ecf20Sopenharmony_ci	case TEP_PRINT_OP:
65258c2ecf20Sopenharmony_ci		if (strcmp(args->op.op, ":") == 0)
65268c2ecf20Sopenharmony_ci			print_paren = 0;
65278c2ecf20Sopenharmony_ci		if (print_paren)
65288c2ecf20Sopenharmony_ci			printf("(");
65298c2ecf20Sopenharmony_ci		print_args(args->op.left);
65308c2ecf20Sopenharmony_ci		printf(" %s ", args->op.op);
65318c2ecf20Sopenharmony_ci		print_args(args->op.right);
65328c2ecf20Sopenharmony_ci		if (print_paren)
65338c2ecf20Sopenharmony_ci			printf(")");
65348c2ecf20Sopenharmony_ci		break;
65358c2ecf20Sopenharmony_ci	default:
65368c2ecf20Sopenharmony_ci		/* we should warn... */
65378c2ecf20Sopenharmony_ci		return;
65388c2ecf20Sopenharmony_ci	}
65398c2ecf20Sopenharmony_ci	if (args->next) {
65408c2ecf20Sopenharmony_ci		printf("\n");
65418c2ecf20Sopenharmony_ci		print_args(args->next);
65428c2ecf20Sopenharmony_ci	}
65438c2ecf20Sopenharmony_ci}
65448c2ecf20Sopenharmony_ci
65458c2ecf20Sopenharmony_cistatic void parse_header_field(const char *field,
65468c2ecf20Sopenharmony_ci			       int *offset, int *size, int mandatory)
65478c2ecf20Sopenharmony_ci{
65488c2ecf20Sopenharmony_ci	unsigned long long save_input_buf_ptr;
65498c2ecf20Sopenharmony_ci	unsigned long long save_input_buf_siz;
65508c2ecf20Sopenharmony_ci	char *token;
65518c2ecf20Sopenharmony_ci	int type;
65528c2ecf20Sopenharmony_ci
65538c2ecf20Sopenharmony_ci	save_input_buf_ptr = input_buf_ptr;
65548c2ecf20Sopenharmony_ci	save_input_buf_siz = input_buf_siz;
65558c2ecf20Sopenharmony_ci
65568c2ecf20Sopenharmony_ci	if (read_expected(TEP_EVENT_ITEM, "field") < 0)
65578c2ecf20Sopenharmony_ci		return;
65588c2ecf20Sopenharmony_ci	if (read_expected(TEP_EVENT_OP, ":") < 0)
65598c2ecf20Sopenharmony_ci		return;
65608c2ecf20Sopenharmony_ci
65618c2ecf20Sopenharmony_ci	/* type */
65628c2ecf20Sopenharmony_ci	if (read_expect_type(TEP_EVENT_ITEM, &token) < 0)
65638c2ecf20Sopenharmony_ci		goto fail;
65648c2ecf20Sopenharmony_ci	free_token(token);
65658c2ecf20Sopenharmony_ci
65668c2ecf20Sopenharmony_ci	/*
65678c2ecf20Sopenharmony_ci	 * If this is not a mandatory field, then test it first.
65688c2ecf20Sopenharmony_ci	 */
65698c2ecf20Sopenharmony_ci	if (mandatory) {
65708c2ecf20Sopenharmony_ci		if (read_expected(TEP_EVENT_ITEM, field) < 0)
65718c2ecf20Sopenharmony_ci			return;
65728c2ecf20Sopenharmony_ci	} else {
65738c2ecf20Sopenharmony_ci		if (read_expect_type(TEP_EVENT_ITEM, &token) < 0)
65748c2ecf20Sopenharmony_ci			goto fail;
65758c2ecf20Sopenharmony_ci		if (strcmp(token, field) != 0)
65768c2ecf20Sopenharmony_ci			goto discard;
65778c2ecf20Sopenharmony_ci		free_token(token);
65788c2ecf20Sopenharmony_ci	}
65798c2ecf20Sopenharmony_ci
65808c2ecf20Sopenharmony_ci	if (read_expected(TEP_EVENT_OP, ";") < 0)
65818c2ecf20Sopenharmony_ci		return;
65828c2ecf20Sopenharmony_ci	if (read_expected(TEP_EVENT_ITEM, "offset") < 0)
65838c2ecf20Sopenharmony_ci		return;
65848c2ecf20Sopenharmony_ci	if (read_expected(TEP_EVENT_OP, ":") < 0)
65858c2ecf20Sopenharmony_ci		return;
65868c2ecf20Sopenharmony_ci	if (read_expect_type(TEP_EVENT_ITEM, &token) < 0)
65878c2ecf20Sopenharmony_ci		goto fail;
65888c2ecf20Sopenharmony_ci	*offset = atoi(token);
65898c2ecf20Sopenharmony_ci	free_token(token);
65908c2ecf20Sopenharmony_ci	if (read_expected(TEP_EVENT_OP, ";") < 0)
65918c2ecf20Sopenharmony_ci		return;
65928c2ecf20Sopenharmony_ci	if (read_expected(TEP_EVENT_ITEM, "size") < 0)
65938c2ecf20Sopenharmony_ci		return;
65948c2ecf20Sopenharmony_ci	if (read_expected(TEP_EVENT_OP, ":") < 0)
65958c2ecf20Sopenharmony_ci		return;
65968c2ecf20Sopenharmony_ci	if (read_expect_type(TEP_EVENT_ITEM, &token) < 0)
65978c2ecf20Sopenharmony_ci		goto fail;
65988c2ecf20Sopenharmony_ci	*size = atoi(token);
65998c2ecf20Sopenharmony_ci	free_token(token);
66008c2ecf20Sopenharmony_ci	if (read_expected(TEP_EVENT_OP, ";") < 0)
66018c2ecf20Sopenharmony_ci		return;
66028c2ecf20Sopenharmony_ci	type = read_token(&token);
66038c2ecf20Sopenharmony_ci	if (type != TEP_EVENT_NEWLINE) {
66048c2ecf20Sopenharmony_ci		/* newer versions of the kernel have a "signed" type */
66058c2ecf20Sopenharmony_ci		if (type != TEP_EVENT_ITEM)
66068c2ecf20Sopenharmony_ci			goto fail;
66078c2ecf20Sopenharmony_ci
66088c2ecf20Sopenharmony_ci		if (strcmp(token, "signed") != 0)
66098c2ecf20Sopenharmony_ci			goto fail;
66108c2ecf20Sopenharmony_ci
66118c2ecf20Sopenharmony_ci		free_token(token);
66128c2ecf20Sopenharmony_ci
66138c2ecf20Sopenharmony_ci		if (read_expected(TEP_EVENT_OP, ":") < 0)
66148c2ecf20Sopenharmony_ci			return;
66158c2ecf20Sopenharmony_ci
66168c2ecf20Sopenharmony_ci		if (read_expect_type(TEP_EVENT_ITEM, &token))
66178c2ecf20Sopenharmony_ci			goto fail;
66188c2ecf20Sopenharmony_ci
66198c2ecf20Sopenharmony_ci		free_token(token);
66208c2ecf20Sopenharmony_ci		if (read_expected(TEP_EVENT_OP, ";") < 0)
66218c2ecf20Sopenharmony_ci			return;
66228c2ecf20Sopenharmony_ci
66238c2ecf20Sopenharmony_ci		if (read_expect_type(TEP_EVENT_NEWLINE, &token))
66248c2ecf20Sopenharmony_ci			goto fail;
66258c2ecf20Sopenharmony_ci	}
66268c2ecf20Sopenharmony_ci fail:
66278c2ecf20Sopenharmony_ci	free_token(token);
66288c2ecf20Sopenharmony_ci	return;
66298c2ecf20Sopenharmony_ci
66308c2ecf20Sopenharmony_ci discard:
66318c2ecf20Sopenharmony_ci	input_buf_ptr = save_input_buf_ptr;
66328c2ecf20Sopenharmony_ci	input_buf_siz = save_input_buf_siz;
66338c2ecf20Sopenharmony_ci	*offset = 0;
66348c2ecf20Sopenharmony_ci	*size = 0;
66358c2ecf20Sopenharmony_ci	free_token(token);
66368c2ecf20Sopenharmony_ci}
66378c2ecf20Sopenharmony_ci
66388c2ecf20Sopenharmony_ci/**
66398c2ecf20Sopenharmony_ci * tep_parse_header_page - parse the data stored in the header page
66408c2ecf20Sopenharmony_ci * @tep: a handle to the trace event parser context
66418c2ecf20Sopenharmony_ci * @buf: the buffer storing the header page format string
66428c2ecf20Sopenharmony_ci * @size: the size of @buf
66438c2ecf20Sopenharmony_ci * @long_size: the long size to use if there is no header
66448c2ecf20Sopenharmony_ci *
66458c2ecf20Sopenharmony_ci * This parses the header page format for information on the
66468c2ecf20Sopenharmony_ci * ring buffer used. The @buf should be copied from
66478c2ecf20Sopenharmony_ci *
66488c2ecf20Sopenharmony_ci * /sys/kernel/debug/tracing/events/header_page
66498c2ecf20Sopenharmony_ci */
66508c2ecf20Sopenharmony_ciint tep_parse_header_page(struct tep_handle *tep, char *buf, unsigned long size,
66518c2ecf20Sopenharmony_ci			  int long_size)
66528c2ecf20Sopenharmony_ci{
66538c2ecf20Sopenharmony_ci	int ignore;
66548c2ecf20Sopenharmony_ci
66558c2ecf20Sopenharmony_ci	if (!size) {
66568c2ecf20Sopenharmony_ci		/*
66578c2ecf20Sopenharmony_ci		 * Old kernels did not have header page info.
66588c2ecf20Sopenharmony_ci		 * Sorry but we just use what we find here in user space.
66598c2ecf20Sopenharmony_ci		 */
66608c2ecf20Sopenharmony_ci		tep->header_page_ts_size = sizeof(long long);
66618c2ecf20Sopenharmony_ci		tep->header_page_size_size = long_size;
66628c2ecf20Sopenharmony_ci		tep->header_page_data_offset = sizeof(long long) + long_size;
66638c2ecf20Sopenharmony_ci		tep->old_format = 1;
66648c2ecf20Sopenharmony_ci		return -1;
66658c2ecf20Sopenharmony_ci	}
66668c2ecf20Sopenharmony_ci	init_input_buf(buf, size);
66678c2ecf20Sopenharmony_ci
66688c2ecf20Sopenharmony_ci	parse_header_field("timestamp", &tep->header_page_ts_offset,
66698c2ecf20Sopenharmony_ci			   &tep->header_page_ts_size, 1);
66708c2ecf20Sopenharmony_ci	parse_header_field("commit", &tep->header_page_size_offset,
66718c2ecf20Sopenharmony_ci			   &tep->header_page_size_size, 1);
66728c2ecf20Sopenharmony_ci	parse_header_field("overwrite", &tep->header_page_overwrite,
66738c2ecf20Sopenharmony_ci			   &ignore, 0);
66748c2ecf20Sopenharmony_ci	parse_header_field("data", &tep->header_page_data_offset,
66758c2ecf20Sopenharmony_ci			   &tep->header_page_data_size, 1);
66768c2ecf20Sopenharmony_ci
66778c2ecf20Sopenharmony_ci	return 0;
66788c2ecf20Sopenharmony_ci}
66798c2ecf20Sopenharmony_ci
66808c2ecf20Sopenharmony_cistatic int event_matches(struct tep_event *event,
66818c2ecf20Sopenharmony_ci			 int id, const char *sys_name,
66828c2ecf20Sopenharmony_ci			 const char *event_name)
66838c2ecf20Sopenharmony_ci{
66848c2ecf20Sopenharmony_ci	if (id >= 0 && id != event->id)
66858c2ecf20Sopenharmony_ci		return 0;
66868c2ecf20Sopenharmony_ci
66878c2ecf20Sopenharmony_ci	if (event_name && (strcmp(event_name, event->name) != 0))
66888c2ecf20Sopenharmony_ci		return 0;
66898c2ecf20Sopenharmony_ci
66908c2ecf20Sopenharmony_ci	if (sys_name && (strcmp(sys_name, event->system) != 0))
66918c2ecf20Sopenharmony_ci		return 0;
66928c2ecf20Sopenharmony_ci
66938c2ecf20Sopenharmony_ci	return 1;
66948c2ecf20Sopenharmony_ci}
66958c2ecf20Sopenharmony_ci
66968c2ecf20Sopenharmony_cistatic void free_handler(struct event_handler *handle)
66978c2ecf20Sopenharmony_ci{
66988c2ecf20Sopenharmony_ci	free((void *)handle->sys_name);
66998c2ecf20Sopenharmony_ci	free((void *)handle->event_name);
67008c2ecf20Sopenharmony_ci	free(handle);
67018c2ecf20Sopenharmony_ci}
67028c2ecf20Sopenharmony_ci
67038c2ecf20Sopenharmony_cistatic int find_event_handle(struct tep_handle *tep, struct tep_event *event)
67048c2ecf20Sopenharmony_ci{
67058c2ecf20Sopenharmony_ci	struct event_handler *handle, **next;
67068c2ecf20Sopenharmony_ci
67078c2ecf20Sopenharmony_ci	for (next = &tep->handlers; *next;
67088c2ecf20Sopenharmony_ci	     next = &(*next)->next) {
67098c2ecf20Sopenharmony_ci		handle = *next;
67108c2ecf20Sopenharmony_ci		if (event_matches(event, handle->id,
67118c2ecf20Sopenharmony_ci				  handle->sys_name,
67128c2ecf20Sopenharmony_ci				  handle->event_name))
67138c2ecf20Sopenharmony_ci			break;
67148c2ecf20Sopenharmony_ci	}
67158c2ecf20Sopenharmony_ci
67168c2ecf20Sopenharmony_ci	if (!(*next))
67178c2ecf20Sopenharmony_ci		return 0;
67188c2ecf20Sopenharmony_ci
67198c2ecf20Sopenharmony_ci	pr_stat("overriding event (%d) %s:%s with new print handler",
67208c2ecf20Sopenharmony_ci		event->id, event->system, event->name);
67218c2ecf20Sopenharmony_ci
67228c2ecf20Sopenharmony_ci	event->handler = handle->func;
67238c2ecf20Sopenharmony_ci	event->context = handle->context;
67248c2ecf20Sopenharmony_ci
67258c2ecf20Sopenharmony_ci	*next = handle->next;
67268c2ecf20Sopenharmony_ci	free_handler(handle);
67278c2ecf20Sopenharmony_ci
67288c2ecf20Sopenharmony_ci	return 1;
67298c2ecf20Sopenharmony_ci}
67308c2ecf20Sopenharmony_ci
67318c2ecf20Sopenharmony_ci/**
67328c2ecf20Sopenharmony_ci * parse_format - parse the event format
67338c2ecf20Sopenharmony_ci * @buf: the buffer storing the event format string
67348c2ecf20Sopenharmony_ci * @size: the size of @buf
67358c2ecf20Sopenharmony_ci * @sys: the system the event belongs to
67368c2ecf20Sopenharmony_ci *
67378c2ecf20Sopenharmony_ci * This parses the event format and creates an event structure
67388c2ecf20Sopenharmony_ci * to quickly parse raw data for a given event.
67398c2ecf20Sopenharmony_ci *
67408c2ecf20Sopenharmony_ci * These files currently come from:
67418c2ecf20Sopenharmony_ci *
67428c2ecf20Sopenharmony_ci * /sys/kernel/debug/tracing/events/.../.../format
67438c2ecf20Sopenharmony_ci */
67448c2ecf20Sopenharmony_cistatic enum tep_errno parse_format(struct tep_event **eventp,
67458c2ecf20Sopenharmony_ci				   struct tep_handle *tep, const char *buf,
67468c2ecf20Sopenharmony_ci				   unsigned long size, const char *sys)
67478c2ecf20Sopenharmony_ci{
67488c2ecf20Sopenharmony_ci	struct tep_event *event;
67498c2ecf20Sopenharmony_ci	int ret;
67508c2ecf20Sopenharmony_ci
67518c2ecf20Sopenharmony_ci	init_input_buf(buf, size);
67528c2ecf20Sopenharmony_ci
67538c2ecf20Sopenharmony_ci	*eventp = event = alloc_event();
67548c2ecf20Sopenharmony_ci	if (!event)
67558c2ecf20Sopenharmony_ci		return TEP_ERRNO__MEM_ALLOC_FAILED;
67568c2ecf20Sopenharmony_ci
67578c2ecf20Sopenharmony_ci	event->name = event_read_name();
67588c2ecf20Sopenharmony_ci	if (!event->name) {
67598c2ecf20Sopenharmony_ci		/* Bad event? */
67608c2ecf20Sopenharmony_ci		ret = TEP_ERRNO__MEM_ALLOC_FAILED;
67618c2ecf20Sopenharmony_ci		goto event_alloc_failed;
67628c2ecf20Sopenharmony_ci	}
67638c2ecf20Sopenharmony_ci
67648c2ecf20Sopenharmony_ci	if (strcmp(sys, "ftrace") == 0) {
67658c2ecf20Sopenharmony_ci		event->flags |= TEP_EVENT_FL_ISFTRACE;
67668c2ecf20Sopenharmony_ci
67678c2ecf20Sopenharmony_ci		if (strcmp(event->name, "bprint") == 0)
67688c2ecf20Sopenharmony_ci			event->flags |= TEP_EVENT_FL_ISBPRINT;
67698c2ecf20Sopenharmony_ci	}
67708c2ecf20Sopenharmony_ci
67718c2ecf20Sopenharmony_ci	event->id = event_read_id();
67728c2ecf20Sopenharmony_ci	if (event->id < 0) {
67738c2ecf20Sopenharmony_ci		ret = TEP_ERRNO__READ_ID_FAILED;
67748c2ecf20Sopenharmony_ci		/*
67758c2ecf20Sopenharmony_ci		 * This isn't an allocation error actually.
67768c2ecf20Sopenharmony_ci		 * But as the ID is critical, just bail out.
67778c2ecf20Sopenharmony_ci		 */
67788c2ecf20Sopenharmony_ci		goto event_alloc_failed;
67798c2ecf20Sopenharmony_ci	}
67808c2ecf20Sopenharmony_ci
67818c2ecf20Sopenharmony_ci	event->system = strdup(sys);
67828c2ecf20Sopenharmony_ci	if (!event->system) {
67838c2ecf20Sopenharmony_ci		ret = TEP_ERRNO__MEM_ALLOC_FAILED;
67848c2ecf20Sopenharmony_ci		goto event_alloc_failed;
67858c2ecf20Sopenharmony_ci	}
67868c2ecf20Sopenharmony_ci
67878c2ecf20Sopenharmony_ci	/* Add tep to event so that it can be referenced */
67888c2ecf20Sopenharmony_ci	event->tep = tep;
67898c2ecf20Sopenharmony_ci
67908c2ecf20Sopenharmony_ci	ret = event_read_format(event);
67918c2ecf20Sopenharmony_ci	if (ret < 0) {
67928c2ecf20Sopenharmony_ci		ret = TEP_ERRNO__READ_FORMAT_FAILED;
67938c2ecf20Sopenharmony_ci		goto event_parse_failed;
67948c2ecf20Sopenharmony_ci	}
67958c2ecf20Sopenharmony_ci
67968c2ecf20Sopenharmony_ci	/*
67978c2ecf20Sopenharmony_ci	 * If the event has an override, don't print warnings if the event
67988c2ecf20Sopenharmony_ci	 * print format fails to parse.
67998c2ecf20Sopenharmony_ci	 */
68008c2ecf20Sopenharmony_ci	if (tep && find_event_handle(tep, event))
68018c2ecf20Sopenharmony_ci		show_warning = 0;
68028c2ecf20Sopenharmony_ci
68038c2ecf20Sopenharmony_ci	ret = event_read_print(event);
68048c2ecf20Sopenharmony_ci	show_warning = 1;
68058c2ecf20Sopenharmony_ci
68068c2ecf20Sopenharmony_ci	if (ret < 0) {
68078c2ecf20Sopenharmony_ci		ret = TEP_ERRNO__READ_PRINT_FAILED;
68088c2ecf20Sopenharmony_ci		goto event_parse_failed;
68098c2ecf20Sopenharmony_ci	}
68108c2ecf20Sopenharmony_ci
68118c2ecf20Sopenharmony_ci	if (!ret && (event->flags & TEP_EVENT_FL_ISFTRACE)) {
68128c2ecf20Sopenharmony_ci		struct tep_format_field *field;
68138c2ecf20Sopenharmony_ci		struct tep_print_arg *arg, **list;
68148c2ecf20Sopenharmony_ci
68158c2ecf20Sopenharmony_ci		/* old ftrace had no args */
68168c2ecf20Sopenharmony_ci		list = &event->print_fmt.args;
68178c2ecf20Sopenharmony_ci		for (field = event->format.fields; field; field = field->next) {
68188c2ecf20Sopenharmony_ci			arg = alloc_arg();
68198c2ecf20Sopenharmony_ci			if (!arg) {
68208c2ecf20Sopenharmony_ci				event->flags |= TEP_EVENT_FL_FAILED;
68218c2ecf20Sopenharmony_ci				return TEP_ERRNO__OLD_FTRACE_ARG_FAILED;
68228c2ecf20Sopenharmony_ci			}
68238c2ecf20Sopenharmony_ci			arg->type = TEP_PRINT_FIELD;
68248c2ecf20Sopenharmony_ci			arg->field.name = strdup(field->name);
68258c2ecf20Sopenharmony_ci			if (!arg->field.name) {
68268c2ecf20Sopenharmony_ci				event->flags |= TEP_EVENT_FL_FAILED;
68278c2ecf20Sopenharmony_ci				free_arg(arg);
68288c2ecf20Sopenharmony_ci				return TEP_ERRNO__OLD_FTRACE_ARG_FAILED;
68298c2ecf20Sopenharmony_ci			}
68308c2ecf20Sopenharmony_ci			arg->field.field = field;
68318c2ecf20Sopenharmony_ci			*list = arg;
68328c2ecf20Sopenharmony_ci			list = &arg->next;
68338c2ecf20Sopenharmony_ci		}
68348c2ecf20Sopenharmony_ci	}
68358c2ecf20Sopenharmony_ci
68368c2ecf20Sopenharmony_ci	if (!(event->flags & TEP_EVENT_FL_ISBPRINT))
68378c2ecf20Sopenharmony_ci		event->print_fmt.print_cache = parse_args(event,
68388c2ecf20Sopenharmony_ci							  event->print_fmt.format,
68398c2ecf20Sopenharmony_ci							  event->print_fmt.args);
68408c2ecf20Sopenharmony_ci
68418c2ecf20Sopenharmony_ci	return 0;
68428c2ecf20Sopenharmony_ci
68438c2ecf20Sopenharmony_ci event_parse_failed:
68448c2ecf20Sopenharmony_ci	event->flags |= TEP_EVENT_FL_FAILED;
68458c2ecf20Sopenharmony_ci	return ret;
68468c2ecf20Sopenharmony_ci
68478c2ecf20Sopenharmony_ci event_alloc_failed:
68488c2ecf20Sopenharmony_ci	free(event->system);
68498c2ecf20Sopenharmony_ci	free(event->name);
68508c2ecf20Sopenharmony_ci	free(event);
68518c2ecf20Sopenharmony_ci	*eventp = NULL;
68528c2ecf20Sopenharmony_ci	return ret;
68538c2ecf20Sopenharmony_ci}
68548c2ecf20Sopenharmony_ci
68558c2ecf20Sopenharmony_cistatic enum tep_errno
68568c2ecf20Sopenharmony_ci__parse_event(struct tep_handle *tep,
68578c2ecf20Sopenharmony_ci	      struct tep_event **eventp,
68588c2ecf20Sopenharmony_ci	      const char *buf, unsigned long size,
68598c2ecf20Sopenharmony_ci	      const char *sys)
68608c2ecf20Sopenharmony_ci{
68618c2ecf20Sopenharmony_ci	int ret = parse_format(eventp, tep, buf, size, sys);
68628c2ecf20Sopenharmony_ci	struct tep_event *event = *eventp;
68638c2ecf20Sopenharmony_ci
68648c2ecf20Sopenharmony_ci	if (event == NULL)
68658c2ecf20Sopenharmony_ci		return ret;
68668c2ecf20Sopenharmony_ci
68678c2ecf20Sopenharmony_ci	if (tep && add_event(tep, event)) {
68688c2ecf20Sopenharmony_ci		ret = TEP_ERRNO__MEM_ALLOC_FAILED;
68698c2ecf20Sopenharmony_ci		goto event_add_failed;
68708c2ecf20Sopenharmony_ci	}
68718c2ecf20Sopenharmony_ci
68728c2ecf20Sopenharmony_ci#define PRINT_ARGS 0
68738c2ecf20Sopenharmony_ci	if (PRINT_ARGS && event->print_fmt.args)
68748c2ecf20Sopenharmony_ci		print_args(event->print_fmt.args);
68758c2ecf20Sopenharmony_ci
68768c2ecf20Sopenharmony_ci	return 0;
68778c2ecf20Sopenharmony_ci
68788c2ecf20Sopenharmony_cievent_add_failed:
68798c2ecf20Sopenharmony_ci	free_tep_event(event);
68808c2ecf20Sopenharmony_ci	return ret;
68818c2ecf20Sopenharmony_ci}
68828c2ecf20Sopenharmony_ci
68838c2ecf20Sopenharmony_ci/**
68848c2ecf20Sopenharmony_ci * tep_parse_format - parse the event format
68858c2ecf20Sopenharmony_ci * @tep: a handle to the trace event parser context
68868c2ecf20Sopenharmony_ci * @eventp: returned format
68878c2ecf20Sopenharmony_ci * @buf: the buffer storing the event format string
68888c2ecf20Sopenharmony_ci * @size: the size of @buf
68898c2ecf20Sopenharmony_ci * @sys: the system the event belongs to
68908c2ecf20Sopenharmony_ci *
68918c2ecf20Sopenharmony_ci * This parses the event format and creates an event structure
68928c2ecf20Sopenharmony_ci * to quickly parse raw data for a given event.
68938c2ecf20Sopenharmony_ci *
68948c2ecf20Sopenharmony_ci * These files currently come from:
68958c2ecf20Sopenharmony_ci *
68968c2ecf20Sopenharmony_ci * /sys/kernel/debug/tracing/events/.../.../format
68978c2ecf20Sopenharmony_ci */
68988c2ecf20Sopenharmony_cienum tep_errno tep_parse_format(struct tep_handle *tep,
68998c2ecf20Sopenharmony_ci				struct tep_event **eventp,
69008c2ecf20Sopenharmony_ci				const char *buf,
69018c2ecf20Sopenharmony_ci				unsigned long size, const char *sys)
69028c2ecf20Sopenharmony_ci{
69038c2ecf20Sopenharmony_ci	return __parse_event(tep, eventp, buf, size, sys);
69048c2ecf20Sopenharmony_ci}
69058c2ecf20Sopenharmony_ci
69068c2ecf20Sopenharmony_ci/**
69078c2ecf20Sopenharmony_ci * tep_parse_event - parse the event format
69088c2ecf20Sopenharmony_ci * @tep: a handle to the trace event parser context
69098c2ecf20Sopenharmony_ci * @buf: the buffer storing the event format string
69108c2ecf20Sopenharmony_ci * @size: the size of @buf
69118c2ecf20Sopenharmony_ci * @sys: the system the event belongs to
69128c2ecf20Sopenharmony_ci *
69138c2ecf20Sopenharmony_ci * This parses the event format and creates an event structure
69148c2ecf20Sopenharmony_ci * to quickly parse raw data for a given event.
69158c2ecf20Sopenharmony_ci *
69168c2ecf20Sopenharmony_ci * These files currently come from:
69178c2ecf20Sopenharmony_ci *
69188c2ecf20Sopenharmony_ci * /sys/kernel/debug/tracing/events/.../.../format
69198c2ecf20Sopenharmony_ci */
69208c2ecf20Sopenharmony_cienum tep_errno tep_parse_event(struct tep_handle *tep, const char *buf,
69218c2ecf20Sopenharmony_ci			       unsigned long size, const char *sys)
69228c2ecf20Sopenharmony_ci{
69238c2ecf20Sopenharmony_ci	struct tep_event *event = NULL;
69248c2ecf20Sopenharmony_ci	return __parse_event(tep, &event, buf, size, sys);
69258c2ecf20Sopenharmony_ci}
69268c2ecf20Sopenharmony_ci
69278c2ecf20Sopenharmony_ciint get_field_val(struct trace_seq *s, struct tep_format_field *field,
69288c2ecf20Sopenharmony_ci		  const char *name, struct tep_record *record,
69298c2ecf20Sopenharmony_ci		  unsigned long long *val, int err)
69308c2ecf20Sopenharmony_ci{
69318c2ecf20Sopenharmony_ci	if (!field) {
69328c2ecf20Sopenharmony_ci		if (err)
69338c2ecf20Sopenharmony_ci			trace_seq_printf(s, "<CANT FIND FIELD %s>", name);
69348c2ecf20Sopenharmony_ci		return -1;
69358c2ecf20Sopenharmony_ci	}
69368c2ecf20Sopenharmony_ci
69378c2ecf20Sopenharmony_ci	if (tep_read_number_field(field, record->data, val)) {
69388c2ecf20Sopenharmony_ci		if (err)
69398c2ecf20Sopenharmony_ci			trace_seq_printf(s, " %s=INVALID", name);
69408c2ecf20Sopenharmony_ci		return -1;
69418c2ecf20Sopenharmony_ci	}
69428c2ecf20Sopenharmony_ci
69438c2ecf20Sopenharmony_ci	return 0;
69448c2ecf20Sopenharmony_ci}
69458c2ecf20Sopenharmony_ci
69468c2ecf20Sopenharmony_ci/**
69478c2ecf20Sopenharmony_ci * tep_get_field_raw - return the raw pointer into the data field
69488c2ecf20Sopenharmony_ci * @s: The seq to print to on error
69498c2ecf20Sopenharmony_ci * @event: the event that the field is for
69508c2ecf20Sopenharmony_ci * @name: The name of the field
69518c2ecf20Sopenharmony_ci * @record: The record with the field name.
69528c2ecf20Sopenharmony_ci * @len: place to store the field length.
69538c2ecf20Sopenharmony_ci * @err: print default error if failed.
69548c2ecf20Sopenharmony_ci *
69558c2ecf20Sopenharmony_ci * Returns a pointer into record->data of the field and places
69568c2ecf20Sopenharmony_ci * the length of the field in @len.
69578c2ecf20Sopenharmony_ci *
69588c2ecf20Sopenharmony_ci * On failure, it returns NULL.
69598c2ecf20Sopenharmony_ci */
69608c2ecf20Sopenharmony_civoid *tep_get_field_raw(struct trace_seq *s, struct tep_event *event,
69618c2ecf20Sopenharmony_ci			const char *name, struct tep_record *record,
69628c2ecf20Sopenharmony_ci			int *len, int err)
69638c2ecf20Sopenharmony_ci{
69648c2ecf20Sopenharmony_ci	struct tep_format_field *field;
69658c2ecf20Sopenharmony_ci	void *data = record->data;
69668c2ecf20Sopenharmony_ci	unsigned offset;
69678c2ecf20Sopenharmony_ci	int dummy;
69688c2ecf20Sopenharmony_ci
69698c2ecf20Sopenharmony_ci	if (!event)
69708c2ecf20Sopenharmony_ci		return NULL;
69718c2ecf20Sopenharmony_ci
69728c2ecf20Sopenharmony_ci	field = tep_find_field(event, name);
69738c2ecf20Sopenharmony_ci
69748c2ecf20Sopenharmony_ci	if (!field) {
69758c2ecf20Sopenharmony_ci		if (err)
69768c2ecf20Sopenharmony_ci			trace_seq_printf(s, "<CANT FIND FIELD %s>", name);
69778c2ecf20Sopenharmony_ci		return NULL;
69788c2ecf20Sopenharmony_ci	}
69798c2ecf20Sopenharmony_ci
69808c2ecf20Sopenharmony_ci	/* Allow @len to be NULL */
69818c2ecf20Sopenharmony_ci	if (!len)
69828c2ecf20Sopenharmony_ci		len = &dummy;
69838c2ecf20Sopenharmony_ci
69848c2ecf20Sopenharmony_ci	offset = field->offset;
69858c2ecf20Sopenharmony_ci	if (field->flags & TEP_FIELD_IS_DYNAMIC) {
69868c2ecf20Sopenharmony_ci		offset = tep_read_number(event->tep,
69878c2ecf20Sopenharmony_ci					 data + offset, field->size);
69888c2ecf20Sopenharmony_ci		*len = offset >> 16;
69898c2ecf20Sopenharmony_ci		offset &= 0xffff;
69908c2ecf20Sopenharmony_ci	} else
69918c2ecf20Sopenharmony_ci		*len = field->size;
69928c2ecf20Sopenharmony_ci
69938c2ecf20Sopenharmony_ci	return data + offset;
69948c2ecf20Sopenharmony_ci}
69958c2ecf20Sopenharmony_ci
69968c2ecf20Sopenharmony_ci/**
69978c2ecf20Sopenharmony_ci * tep_get_field_val - find a field and return its value
69988c2ecf20Sopenharmony_ci * @s: The seq to print to on error
69998c2ecf20Sopenharmony_ci * @event: the event that the field is for
70008c2ecf20Sopenharmony_ci * @name: The name of the field
70018c2ecf20Sopenharmony_ci * @record: The record with the field name.
70028c2ecf20Sopenharmony_ci * @val: place to store the value of the field.
70038c2ecf20Sopenharmony_ci * @err: print default error if failed.
70048c2ecf20Sopenharmony_ci *
70058c2ecf20Sopenharmony_ci * Returns 0 on success -1 on field not found.
70068c2ecf20Sopenharmony_ci */
70078c2ecf20Sopenharmony_ciint tep_get_field_val(struct trace_seq *s, struct tep_event *event,
70088c2ecf20Sopenharmony_ci		      const char *name, struct tep_record *record,
70098c2ecf20Sopenharmony_ci		      unsigned long long *val, int err)
70108c2ecf20Sopenharmony_ci{
70118c2ecf20Sopenharmony_ci	struct tep_format_field *field;
70128c2ecf20Sopenharmony_ci
70138c2ecf20Sopenharmony_ci	if (!event)
70148c2ecf20Sopenharmony_ci		return -1;
70158c2ecf20Sopenharmony_ci
70168c2ecf20Sopenharmony_ci	field = tep_find_field(event, name);
70178c2ecf20Sopenharmony_ci
70188c2ecf20Sopenharmony_ci	return get_field_val(s, field, name, record, val, err);
70198c2ecf20Sopenharmony_ci}
70208c2ecf20Sopenharmony_ci
70218c2ecf20Sopenharmony_ci/**
70228c2ecf20Sopenharmony_ci * tep_get_common_field_val - find a common field and return its value
70238c2ecf20Sopenharmony_ci * @s: The seq to print to on error
70248c2ecf20Sopenharmony_ci * @event: the event that the field is for
70258c2ecf20Sopenharmony_ci * @name: The name of the field
70268c2ecf20Sopenharmony_ci * @record: The record with the field name.
70278c2ecf20Sopenharmony_ci * @val: place to store the value of the field.
70288c2ecf20Sopenharmony_ci * @err: print default error if failed.
70298c2ecf20Sopenharmony_ci *
70308c2ecf20Sopenharmony_ci * Returns 0 on success -1 on field not found.
70318c2ecf20Sopenharmony_ci */
70328c2ecf20Sopenharmony_ciint tep_get_common_field_val(struct trace_seq *s, struct tep_event *event,
70338c2ecf20Sopenharmony_ci			     const char *name, struct tep_record *record,
70348c2ecf20Sopenharmony_ci			     unsigned long long *val, int err)
70358c2ecf20Sopenharmony_ci{
70368c2ecf20Sopenharmony_ci	struct tep_format_field *field;
70378c2ecf20Sopenharmony_ci
70388c2ecf20Sopenharmony_ci	if (!event)
70398c2ecf20Sopenharmony_ci		return -1;
70408c2ecf20Sopenharmony_ci
70418c2ecf20Sopenharmony_ci	field = tep_find_common_field(event, name);
70428c2ecf20Sopenharmony_ci
70438c2ecf20Sopenharmony_ci	return get_field_val(s, field, name, record, val, err);
70448c2ecf20Sopenharmony_ci}
70458c2ecf20Sopenharmony_ci
70468c2ecf20Sopenharmony_ci/**
70478c2ecf20Sopenharmony_ci * tep_get_any_field_val - find a any field and return its value
70488c2ecf20Sopenharmony_ci * @s: The seq to print to on error
70498c2ecf20Sopenharmony_ci * @event: the event that the field is for
70508c2ecf20Sopenharmony_ci * @name: The name of the field
70518c2ecf20Sopenharmony_ci * @record: The record with the field name.
70528c2ecf20Sopenharmony_ci * @val: place to store the value of the field.
70538c2ecf20Sopenharmony_ci * @err: print default error if failed.
70548c2ecf20Sopenharmony_ci *
70558c2ecf20Sopenharmony_ci * Returns 0 on success -1 on field not found.
70568c2ecf20Sopenharmony_ci */
70578c2ecf20Sopenharmony_ciint tep_get_any_field_val(struct trace_seq *s, struct tep_event *event,
70588c2ecf20Sopenharmony_ci			  const char *name, struct tep_record *record,
70598c2ecf20Sopenharmony_ci			  unsigned long long *val, int err)
70608c2ecf20Sopenharmony_ci{
70618c2ecf20Sopenharmony_ci	struct tep_format_field *field;
70628c2ecf20Sopenharmony_ci
70638c2ecf20Sopenharmony_ci	if (!event)
70648c2ecf20Sopenharmony_ci		return -1;
70658c2ecf20Sopenharmony_ci
70668c2ecf20Sopenharmony_ci	field = tep_find_any_field(event, name);
70678c2ecf20Sopenharmony_ci
70688c2ecf20Sopenharmony_ci	return get_field_val(s, field, name, record, val, err);
70698c2ecf20Sopenharmony_ci}
70708c2ecf20Sopenharmony_ci
70718c2ecf20Sopenharmony_ci/**
70728c2ecf20Sopenharmony_ci * tep_print_num_field - print a field and a format
70738c2ecf20Sopenharmony_ci * @s: The seq to print to
70748c2ecf20Sopenharmony_ci * @fmt: The printf format to print the field with.
70758c2ecf20Sopenharmony_ci * @event: the event that the field is for
70768c2ecf20Sopenharmony_ci * @name: The name of the field
70778c2ecf20Sopenharmony_ci * @record: The record with the field name.
70788c2ecf20Sopenharmony_ci * @err: print default error if failed.
70798c2ecf20Sopenharmony_ci *
70808c2ecf20Sopenharmony_ci * Returns positive value on success, negative in case of an error,
70818c2ecf20Sopenharmony_ci * or 0 if buffer is full.
70828c2ecf20Sopenharmony_ci */
70838c2ecf20Sopenharmony_ciint tep_print_num_field(struct trace_seq *s, const char *fmt,
70848c2ecf20Sopenharmony_ci			struct tep_event *event, const char *name,
70858c2ecf20Sopenharmony_ci			struct tep_record *record, int err)
70868c2ecf20Sopenharmony_ci{
70878c2ecf20Sopenharmony_ci	struct tep_format_field *field = tep_find_field(event, name);
70888c2ecf20Sopenharmony_ci	unsigned long long val;
70898c2ecf20Sopenharmony_ci
70908c2ecf20Sopenharmony_ci	if (!field)
70918c2ecf20Sopenharmony_ci		goto failed;
70928c2ecf20Sopenharmony_ci
70938c2ecf20Sopenharmony_ci	if (tep_read_number_field(field, record->data, &val))
70948c2ecf20Sopenharmony_ci		goto failed;
70958c2ecf20Sopenharmony_ci
70968c2ecf20Sopenharmony_ci	return trace_seq_printf(s, fmt, val);
70978c2ecf20Sopenharmony_ci
70988c2ecf20Sopenharmony_ci failed:
70998c2ecf20Sopenharmony_ci	if (err)
71008c2ecf20Sopenharmony_ci		trace_seq_printf(s, "CAN'T FIND FIELD \"%s\"", name);
71018c2ecf20Sopenharmony_ci	return -1;
71028c2ecf20Sopenharmony_ci}
71038c2ecf20Sopenharmony_ci
71048c2ecf20Sopenharmony_ci/**
71058c2ecf20Sopenharmony_ci * tep_print_func_field - print a field and a format for function pointers
71068c2ecf20Sopenharmony_ci * @s: The seq to print to
71078c2ecf20Sopenharmony_ci * @fmt: The printf format to print the field with.
71088c2ecf20Sopenharmony_ci * @event: the event that the field is for
71098c2ecf20Sopenharmony_ci * @name: The name of the field
71108c2ecf20Sopenharmony_ci * @record: The record with the field name.
71118c2ecf20Sopenharmony_ci * @err: print default error if failed.
71128c2ecf20Sopenharmony_ci *
71138c2ecf20Sopenharmony_ci * Returns positive value on success, negative in case of an error,
71148c2ecf20Sopenharmony_ci * or 0 if buffer is full.
71158c2ecf20Sopenharmony_ci */
71168c2ecf20Sopenharmony_ciint tep_print_func_field(struct trace_seq *s, const char *fmt,
71178c2ecf20Sopenharmony_ci			 struct tep_event *event, const char *name,
71188c2ecf20Sopenharmony_ci			 struct tep_record *record, int err)
71198c2ecf20Sopenharmony_ci{
71208c2ecf20Sopenharmony_ci	struct tep_format_field *field = tep_find_field(event, name);
71218c2ecf20Sopenharmony_ci	struct tep_handle *tep = event->tep;
71228c2ecf20Sopenharmony_ci	unsigned long long val;
71238c2ecf20Sopenharmony_ci	struct func_map *func;
71248c2ecf20Sopenharmony_ci	char tmp[128];
71258c2ecf20Sopenharmony_ci
71268c2ecf20Sopenharmony_ci	if (!field)
71278c2ecf20Sopenharmony_ci		goto failed;
71288c2ecf20Sopenharmony_ci
71298c2ecf20Sopenharmony_ci	if (tep_read_number_field(field, record->data, &val))
71308c2ecf20Sopenharmony_ci		goto failed;
71318c2ecf20Sopenharmony_ci
71328c2ecf20Sopenharmony_ci	func = find_func(tep, val);
71338c2ecf20Sopenharmony_ci
71348c2ecf20Sopenharmony_ci	if (func)
71358c2ecf20Sopenharmony_ci		snprintf(tmp, 128, "%s/0x%llx", func->func, func->addr - val);
71368c2ecf20Sopenharmony_ci	else
71378c2ecf20Sopenharmony_ci		sprintf(tmp, "0x%08llx", val);
71388c2ecf20Sopenharmony_ci
71398c2ecf20Sopenharmony_ci	return trace_seq_printf(s, fmt, tmp);
71408c2ecf20Sopenharmony_ci
71418c2ecf20Sopenharmony_ci failed:
71428c2ecf20Sopenharmony_ci	if (err)
71438c2ecf20Sopenharmony_ci		trace_seq_printf(s, "CAN'T FIND FIELD \"%s\"", name);
71448c2ecf20Sopenharmony_ci	return -1;
71458c2ecf20Sopenharmony_ci}
71468c2ecf20Sopenharmony_ci
71478c2ecf20Sopenharmony_cistatic void free_func_handle(struct tep_function_handler *func)
71488c2ecf20Sopenharmony_ci{
71498c2ecf20Sopenharmony_ci	struct func_params *params;
71508c2ecf20Sopenharmony_ci
71518c2ecf20Sopenharmony_ci	free(func->name);
71528c2ecf20Sopenharmony_ci
71538c2ecf20Sopenharmony_ci	while (func->params) {
71548c2ecf20Sopenharmony_ci		params = func->params;
71558c2ecf20Sopenharmony_ci		func->params = params->next;
71568c2ecf20Sopenharmony_ci		free(params);
71578c2ecf20Sopenharmony_ci	}
71588c2ecf20Sopenharmony_ci
71598c2ecf20Sopenharmony_ci	free(func);
71608c2ecf20Sopenharmony_ci}
71618c2ecf20Sopenharmony_ci
71628c2ecf20Sopenharmony_ci/**
71638c2ecf20Sopenharmony_ci * tep_register_print_function - register a helper function
71648c2ecf20Sopenharmony_ci * @tep: a handle to the trace event parser context
71658c2ecf20Sopenharmony_ci * @func: the function to process the helper function
71668c2ecf20Sopenharmony_ci * @ret_type: the return type of the helper function
71678c2ecf20Sopenharmony_ci * @name: the name of the helper function
71688c2ecf20Sopenharmony_ci * @parameters: A list of enum tep_func_arg_type
71698c2ecf20Sopenharmony_ci *
71708c2ecf20Sopenharmony_ci * Some events may have helper functions in the print format arguments.
71718c2ecf20Sopenharmony_ci * This allows a plugin to dynamically create a way to process one
71728c2ecf20Sopenharmony_ci * of these functions.
71738c2ecf20Sopenharmony_ci *
71748c2ecf20Sopenharmony_ci * The @parameters is a variable list of tep_func_arg_type enums that
71758c2ecf20Sopenharmony_ci * must end with TEP_FUNC_ARG_VOID.
71768c2ecf20Sopenharmony_ci */
71778c2ecf20Sopenharmony_ciint tep_register_print_function(struct tep_handle *tep,
71788c2ecf20Sopenharmony_ci				tep_func_handler func,
71798c2ecf20Sopenharmony_ci				enum tep_func_arg_type ret_type,
71808c2ecf20Sopenharmony_ci				char *name, ...)
71818c2ecf20Sopenharmony_ci{
71828c2ecf20Sopenharmony_ci	struct tep_function_handler *func_handle;
71838c2ecf20Sopenharmony_ci	struct func_params **next_param;
71848c2ecf20Sopenharmony_ci	struct func_params *param;
71858c2ecf20Sopenharmony_ci	enum tep_func_arg_type type;
71868c2ecf20Sopenharmony_ci	va_list ap;
71878c2ecf20Sopenharmony_ci	int ret;
71888c2ecf20Sopenharmony_ci
71898c2ecf20Sopenharmony_ci	func_handle = find_func_handler(tep, name);
71908c2ecf20Sopenharmony_ci	if (func_handle) {
71918c2ecf20Sopenharmony_ci		/*
71928c2ecf20Sopenharmony_ci		 * This is most like caused by the users own
71938c2ecf20Sopenharmony_ci		 * plugins updating the function. This overrides the
71948c2ecf20Sopenharmony_ci		 * system defaults.
71958c2ecf20Sopenharmony_ci		 */
71968c2ecf20Sopenharmony_ci		pr_stat("override of function helper '%s'", name);
71978c2ecf20Sopenharmony_ci		remove_func_handler(tep, name);
71988c2ecf20Sopenharmony_ci	}
71998c2ecf20Sopenharmony_ci
72008c2ecf20Sopenharmony_ci	func_handle = calloc(1, sizeof(*func_handle));
72018c2ecf20Sopenharmony_ci	if (!func_handle) {
72028c2ecf20Sopenharmony_ci		do_warning("Failed to allocate function handler");
72038c2ecf20Sopenharmony_ci		return TEP_ERRNO__MEM_ALLOC_FAILED;
72048c2ecf20Sopenharmony_ci	}
72058c2ecf20Sopenharmony_ci
72068c2ecf20Sopenharmony_ci	func_handle->ret_type = ret_type;
72078c2ecf20Sopenharmony_ci	func_handle->name = strdup(name);
72088c2ecf20Sopenharmony_ci	func_handle->func = func;
72098c2ecf20Sopenharmony_ci	if (!func_handle->name) {
72108c2ecf20Sopenharmony_ci		do_warning("Failed to allocate function name");
72118c2ecf20Sopenharmony_ci		free(func_handle);
72128c2ecf20Sopenharmony_ci		return TEP_ERRNO__MEM_ALLOC_FAILED;
72138c2ecf20Sopenharmony_ci	}
72148c2ecf20Sopenharmony_ci
72158c2ecf20Sopenharmony_ci	next_param = &(func_handle->params);
72168c2ecf20Sopenharmony_ci	va_start(ap, name);
72178c2ecf20Sopenharmony_ci	for (;;) {
72188c2ecf20Sopenharmony_ci		type = va_arg(ap, enum tep_func_arg_type);
72198c2ecf20Sopenharmony_ci		if (type == TEP_FUNC_ARG_VOID)
72208c2ecf20Sopenharmony_ci			break;
72218c2ecf20Sopenharmony_ci
72228c2ecf20Sopenharmony_ci		if (type >= TEP_FUNC_ARG_MAX_TYPES) {
72238c2ecf20Sopenharmony_ci			do_warning("Invalid argument type %d", type);
72248c2ecf20Sopenharmony_ci			ret = TEP_ERRNO__INVALID_ARG_TYPE;
72258c2ecf20Sopenharmony_ci			goto out_free;
72268c2ecf20Sopenharmony_ci		}
72278c2ecf20Sopenharmony_ci
72288c2ecf20Sopenharmony_ci		param = malloc(sizeof(*param));
72298c2ecf20Sopenharmony_ci		if (!param) {
72308c2ecf20Sopenharmony_ci			do_warning("Failed to allocate function param");
72318c2ecf20Sopenharmony_ci			ret = TEP_ERRNO__MEM_ALLOC_FAILED;
72328c2ecf20Sopenharmony_ci			goto out_free;
72338c2ecf20Sopenharmony_ci		}
72348c2ecf20Sopenharmony_ci		param->type = type;
72358c2ecf20Sopenharmony_ci		param->next = NULL;
72368c2ecf20Sopenharmony_ci
72378c2ecf20Sopenharmony_ci		*next_param = param;
72388c2ecf20Sopenharmony_ci		next_param = &(param->next);
72398c2ecf20Sopenharmony_ci
72408c2ecf20Sopenharmony_ci		func_handle->nr_args++;
72418c2ecf20Sopenharmony_ci	}
72428c2ecf20Sopenharmony_ci	va_end(ap);
72438c2ecf20Sopenharmony_ci
72448c2ecf20Sopenharmony_ci	func_handle->next = tep->func_handlers;
72458c2ecf20Sopenharmony_ci	tep->func_handlers = func_handle;
72468c2ecf20Sopenharmony_ci
72478c2ecf20Sopenharmony_ci	return 0;
72488c2ecf20Sopenharmony_ci out_free:
72498c2ecf20Sopenharmony_ci	va_end(ap);
72508c2ecf20Sopenharmony_ci	free_func_handle(func_handle);
72518c2ecf20Sopenharmony_ci	return ret;
72528c2ecf20Sopenharmony_ci}
72538c2ecf20Sopenharmony_ci
72548c2ecf20Sopenharmony_ci/**
72558c2ecf20Sopenharmony_ci * tep_unregister_print_function - unregister a helper function
72568c2ecf20Sopenharmony_ci * @tep: a handle to the trace event parser context
72578c2ecf20Sopenharmony_ci * @func: the function to process the helper function
72588c2ecf20Sopenharmony_ci * @name: the name of the helper function
72598c2ecf20Sopenharmony_ci *
72608c2ecf20Sopenharmony_ci * This function removes existing print handler for function @name.
72618c2ecf20Sopenharmony_ci *
72628c2ecf20Sopenharmony_ci * Returns 0 if the handler was removed successully, -1 otherwise.
72638c2ecf20Sopenharmony_ci */
72648c2ecf20Sopenharmony_ciint tep_unregister_print_function(struct tep_handle *tep,
72658c2ecf20Sopenharmony_ci				  tep_func_handler func, char *name)
72668c2ecf20Sopenharmony_ci{
72678c2ecf20Sopenharmony_ci	struct tep_function_handler *func_handle;
72688c2ecf20Sopenharmony_ci
72698c2ecf20Sopenharmony_ci	func_handle = find_func_handler(tep, name);
72708c2ecf20Sopenharmony_ci	if (func_handle && func_handle->func == func) {
72718c2ecf20Sopenharmony_ci		remove_func_handler(tep, name);
72728c2ecf20Sopenharmony_ci		return 0;
72738c2ecf20Sopenharmony_ci	}
72748c2ecf20Sopenharmony_ci	return -1;
72758c2ecf20Sopenharmony_ci}
72768c2ecf20Sopenharmony_ci
72778c2ecf20Sopenharmony_cistatic struct tep_event *search_event(struct tep_handle *tep, int id,
72788c2ecf20Sopenharmony_ci				      const char *sys_name,
72798c2ecf20Sopenharmony_ci				      const char *event_name)
72808c2ecf20Sopenharmony_ci{
72818c2ecf20Sopenharmony_ci	struct tep_event *event;
72828c2ecf20Sopenharmony_ci
72838c2ecf20Sopenharmony_ci	if (id >= 0) {
72848c2ecf20Sopenharmony_ci		/* search by id */
72858c2ecf20Sopenharmony_ci		event = tep_find_event(tep, id);
72868c2ecf20Sopenharmony_ci		if (!event)
72878c2ecf20Sopenharmony_ci			return NULL;
72888c2ecf20Sopenharmony_ci		if (event_name && (strcmp(event_name, event->name) != 0))
72898c2ecf20Sopenharmony_ci			return NULL;
72908c2ecf20Sopenharmony_ci		if (sys_name && (strcmp(sys_name, event->system) != 0))
72918c2ecf20Sopenharmony_ci			return NULL;
72928c2ecf20Sopenharmony_ci	} else {
72938c2ecf20Sopenharmony_ci		event = tep_find_event_by_name(tep, sys_name, event_name);
72948c2ecf20Sopenharmony_ci		if (!event)
72958c2ecf20Sopenharmony_ci			return NULL;
72968c2ecf20Sopenharmony_ci	}
72978c2ecf20Sopenharmony_ci	return event;
72988c2ecf20Sopenharmony_ci}
72998c2ecf20Sopenharmony_ci
73008c2ecf20Sopenharmony_ci/**
73018c2ecf20Sopenharmony_ci * tep_register_event_handler - register a way to parse an event
73028c2ecf20Sopenharmony_ci * @tep: a handle to the trace event parser context
73038c2ecf20Sopenharmony_ci * @id: the id of the event to register
73048c2ecf20Sopenharmony_ci * @sys_name: the system name the event belongs to
73058c2ecf20Sopenharmony_ci * @event_name: the name of the event
73068c2ecf20Sopenharmony_ci * @func: the function to call to parse the event information
73078c2ecf20Sopenharmony_ci * @context: the data to be passed to @func
73088c2ecf20Sopenharmony_ci *
73098c2ecf20Sopenharmony_ci * This function allows a developer to override the parsing of
73108c2ecf20Sopenharmony_ci * a given event. If for some reason the default print format
73118c2ecf20Sopenharmony_ci * is not sufficient, this function will register a function
73128c2ecf20Sopenharmony_ci * for an event to be used to parse the data instead.
73138c2ecf20Sopenharmony_ci *
73148c2ecf20Sopenharmony_ci * If @id is >= 0, then it is used to find the event.
73158c2ecf20Sopenharmony_ci * else @sys_name and @event_name are used.
73168c2ecf20Sopenharmony_ci *
73178c2ecf20Sopenharmony_ci * Returns:
73188c2ecf20Sopenharmony_ci *  TEP_REGISTER_SUCCESS_OVERWRITE if an existing handler is overwritten
73198c2ecf20Sopenharmony_ci *  TEP_REGISTER_SUCCESS if a new handler is registered successfully
73208c2ecf20Sopenharmony_ci *  negative TEP_ERRNO_... in case of an error
73218c2ecf20Sopenharmony_ci *
73228c2ecf20Sopenharmony_ci */
73238c2ecf20Sopenharmony_ciint tep_register_event_handler(struct tep_handle *tep, int id,
73248c2ecf20Sopenharmony_ci			       const char *sys_name, const char *event_name,
73258c2ecf20Sopenharmony_ci			       tep_event_handler_func func, void *context)
73268c2ecf20Sopenharmony_ci{
73278c2ecf20Sopenharmony_ci	struct tep_event *event;
73288c2ecf20Sopenharmony_ci	struct event_handler *handle;
73298c2ecf20Sopenharmony_ci
73308c2ecf20Sopenharmony_ci	event = search_event(tep, id, sys_name, event_name);
73318c2ecf20Sopenharmony_ci	if (event == NULL)
73328c2ecf20Sopenharmony_ci		goto not_found;
73338c2ecf20Sopenharmony_ci
73348c2ecf20Sopenharmony_ci	pr_stat("overriding event (%d) %s:%s with new print handler",
73358c2ecf20Sopenharmony_ci		event->id, event->system, event->name);
73368c2ecf20Sopenharmony_ci
73378c2ecf20Sopenharmony_ci	event->handler = func;
73388c2ecf20Sopenharmony_ci	event->context = context;
73398c2ecf20Sopenharmony_ci	return TEP_REGISTER_SUCCESS_OVERWRITE;
73408c2ecf20Sopenharmony_ci
73418c2ecf20Sopenharmony_ci not_found:
73428c2ecf20Sopenharmony_ci	/* Save for later use. */
73438c2ecf20Sopenharmony_ci	handle = calloc(1, sizeof(*handle));
73448c2ecf20Sopenharmony_ci	if (!handle) {
73458c2ecf20Sopenharmony_ci		do_warning("Failed to allocate event handler");
73468c2ecf20Sopenharmony_ci		return TEP_ERRNO__MEM_ALLOC_FAILED;
73478c2ecf20Sopenharmony_ci	}
73488c2ecf20Sopenharmony_ci
73498c2ecf20Sopenharmony_ci	handle->id = id;
73508c2ecf20Sopenharmony_ci	if (event_name)
73518c2ecf20Sopenharmony_ci		handle->event_name = strdup(event_name);
73528c2ecf20Sopenharmony_ci	if (sys_name)
73538c2ecf20Sopenharmony_ci		handle->sys_name = strdup(sys_name);
73548c2ecf20Sopenharmony_ci
73558c2ecf20Sopenharmony_ci	if ((event_name && !handle->event_name) ||
73568c2ecf20Sopenharmony_ci	    (sys_name && !handle->sys_name)) {
73578c2ecf20Sopenharmony_ci		do_warning("Failed to allocate event/sys name");
73588c2ecf20Sopenharmony_ci		free((void *)handle->event_name);
73598c2ecf20Sopenharmony_ci		free((void *)handle->sys_name);
73608c2ecf20Sopenharmony_ci		free(handle);
73618c2ecf20Sopenharmony_ci		return TEP_ERRNO__MEM_ALLOC_FAILED;
73628c2ecf20Sopenharmony_ci	}
73638c2ecf20Sopenharmony_ci
73648c2ecf20Sopenharmony_ci	handle->func = func;
73658c2ecf20Sopenharmony_ci	handle->next = tep->handlers;
73668c2ecf20Sopenharmony_ci	tep->handlers = handle;
73678c2ecf20Sopenharmony_ci	handle->context = context;
73688c2ecf20Sopenharmony_ci
73698c2ecf20Sopenharmony_ci	return TEP_REGISTER_SUCCESS;
73708c2ecf20Sopenharmony_ci}
73718c2ecf20Sopenharmony_ci
73728c2ecf20Sopenharmony_cistatic int handle_matches(struct event_handler *handler, int id,
73738c2ecf20Sopenharmony_ci			  const char *sys_name, const char *event_name,
73748c2ecf20Sopenharmony_ci			  tep_event_handler_func func, void *context)
73758c2ecf20Sopenharmony_ci{
73768c2ecf20Sopenharmony_ci	if (id >= 0 && id != handler->id)
73778c2ecf20Sopenharmony_ci		return 0;
73788c2ecf20Sopenharmony_ci
73798c2ecf20Sopenharmony_ci	if (event_name && (strcmp(event_name, handler->event_name) != 0))
73808c2ecf20Sopenharmony_ci		return 0;
73818c2ecf20Sopenharmony_ci
73828c2ecf20Sopenharmony_ci	if (sys_name && (strcmp(sys_name, handler->sys_name) != 0))
73838c2ecf20Sopenharmony_ci		return 0;
73848c2ecf20Sopenharmony_ci
73858c2ecf20Sopenharmony_ci	if (func != handler->func || context != handler->context)
73868c2ecf20Sopenharmony_ci		return 0;
73878c2ecf20Sopenharmony_ci
73888c2ecf20Sopenharmony_ci	return 1;
73898c2ecf20Sopenharmony_ci}
73908c2ecf20Sopenharmony_ci
73918c2ecf20Sopenharmony_ci/**
73928c2ecf20Sopenharmony_ci * tep_unregister_event_handler - unregister an existing event handler
73938c2ecf20Sopenharmony_ci * @tep: a handle to the trace event parser context
73948c2ecf20Sopenharmony_ci * @id: the id of the event to unregister
73958c2ecf20Sopenharmony_ci * @sys_name: the system name the handler belongs to
73968c2ecf20Sopenharmony_ci * @event_name: the name of the event handler
73978c2ecf20Sopenharmony_ci * @func: the function to call to parse the event information
73988c2ecf20Sopenharmony_ci * @context: the data to be passed to @func
73998c2ecf20Sopenharmony_ci *
74008c2ecf20Sopenharmony_ci * This function removes existing event handler (parser).
74018c2ecf20Sopenharmony_ci *
74028c2ecf20Sopenharmony_ci * If @id is >= 0, then it is used to find the event.
74038c2ecf20Sopenharmony_ci * else @sys_name and @event_name are used.
74048c2ecf20Sopenharmony_ci *
74058c2ecf20Sopenharmony_ci * Returns 0 if handler was removed successfully, -1 if event was not found.
74068c2ecf20Sopenharmony_ci */
74078c2ecf20Sopenharmony_ciint tep_unregister_event_handler(struct tep_handle *tep, int id,
74088c2ecf20Sopenharmony_ci				 const char *sys_name, const char *event_name,
74098c2ecf20Sopenharmony_ci				 tep_event_handler_func func, void *context)
74108c2ecf20Sopenharmony_ci{
74118c2ecf20Sopenharmony_ci	struct tep_event *event;
74128c2ecf20Sopenharmony_ci	struct event_handler *handle;
74138c2ecf20Sopenharmony_ci	struct event_handler **next;
74148c2ecf20Sopenharmony_ci
74158c2ecf20Sopenharmony_ci	event = search_event(tep, id, sys_name, event_name);
74168c2ecf20Sopenharmony_ci	if (event == NULL)
74178c2ecf20Sopenharmony_ci		goto not_found;
74188c2ecf20Sopenharmony_ci
74198c2ecf20Sopenharmony_ci	if (event->handler == func && event->context == context) {
74208c2ecf20Sopenharmony_ci		pr_stat("removing override handler for event (%d) %s:%s. Going back to default handler.",
74218c2ecf20Sopenharmony_ci			event->id, event->system, event->name);
74228c2ecf20Sopenharmony_ci
74238c2ecf20Sopenharmony_ci		event->handler = NULL;
74248c2ecf20Sopenharmony_ci		event->context = NULL;
74258c2ecf20Sopenharmony_ci		return 0;
74268c2ecf20Sopenharmony_ci	}
74278c2ecf20Sopenharmony_ci
74288c2ecf20Sopenharmony_cinot_found:
74298c2ecf20Sopenharmony_ci	for (next = &tep->handlers; *next; next = &(*next)->next) {
74308c2ecf20Sopenharmony_ci		handle = *next;
74318c2ecf20Sopenharmony_ci		if (handle_matches(handle, id, sys_name, event_name,
74328c2ecf20Sopenharmony_ci				   func, context))
74338c2ecf20Sopenharmony_ci			break;
74348c2ecf20Sopenharmony_ci	}
74358c2ecf20Sopenharmony_ci
74368c2ecf20Sopenharmony_ci	if (!(*next))
74378c2ecf20Sopenharmony_ci		return -1;
74388c2ecf20Sopenharmony_ci
74398c2ecf20Sopenharmony_ci	*next = handle->next;
74408c2ecf20Sopenharmony_ci	free_handler(handle);
74418c2ecf20Sopenharmony_ci
74428c2ecf20Sopenharmony_ci	return 0;
74438c2ecf20Sopenharmony_ci}
74448c2ecf20Sopenharmony_ci
74458c2ecf20Sopenharmony_ci/**
74468c2ecf20Sopenharmony_ci * tep_alloc - create a tep handle
74478c2ecf20Sopenharmony_ci */
74488c2ecf20Sopenharmony_cistruct tep_handle *tep_alloc(void)
74498c2ecf20Sopenharmony_ci{
74508c2ecf20Sopenharmony_ci	struct tep_handle *tep = calloc(1, sizeof(*tep));
74518c2ecf20Sopenharmony_ci
74528c2ecf20Sopenharmony_ci	if (tep) {
74538c2ecf20Sopenharmony_ci		tep->ref_count = 1;
74548c2ecf20Sopenharmony_ci		tep->host_bigendian = tep_is_bigendian();
74558c2ecf20Sopenharmony_ci	}
74568c2ecf20Sopenharmony_ci
74578c2ecf20Sopenharmony_ci	return tep;
74588c2ecf20Sopenharmony_ci}
74598c2ecf20Sopenharmony_ci
74608c2ecf20Sopenharmony_civoid tep_ref(struct tep_handle *tep)
74618c2ecf20Sopenharmony_ci{
74628c2ecf20Sopenharmony_ci	tep->ref_count++;
74638c2ecf20Sopenharmony_ci}
74648c2ecf20Sopenharmony_ci
74658c2ecf20Sopenharmony_ciint tep_get_ref(struct tep_handle *tep)
74668c2ecf20Sopenharmony_ci{
74678c2ecf20Sopenharmony_ci	if (tep)
74688c2ecf20Sopenharmony_ci		return tep->ref_count;
74698c2ecf20Sopenharmony_ci	return 0;
74708c2ecf20Sopenharmony_ci}
74718c2ecf20Sopenharmony_ci
74728c2ecf20Sopenharmony_ci__hidden void free_tep_format_field(struct tep_format_field *field)
74738c2ecf20Sopenharmony_ci{
74748c2ecf20Sopenharmony_ci	free(field->type);
74758c2ecf20Sopenharmony_ci	if (field->alias != field->name)
74768c2ecf20Sopenharmony_ci		free(field->alias);
74778c2ecf20Sopenharmony_ci	free(field->name);
74788c2ecf20Sopenharmony_ci	free(field);
74798c2ecf20Sopenharmony_ci}
74808c2ecf20Sopenharmony_ci
74818c2ecf20Sopenharmony_cistatic void free_format_fields(struct tep_format_field *field)
74828c2ecf20Sopenharmony_ci{
74838c2ecf20Sopenharmony_ci	struct tep_format_field *next;
74848c2ecf20Sopenharmony_ci
74858c2ecf20Sopenharmony_ci	while (field) {
74868c2ecf20Sopenharmony_ci		next = field->next;
74878c2ecf20Sopenharmony_ci		free_tep_format_field(field);
74888c2ecf20Sopenharmony_ci		field = next;
74898c2ecf20Sopenharmony_ci	}
74908c2ecf20Sopenharmony_ci}
74918c2ecf20Sopenharmony_ci
74928c2ecf20Sopenharmony_cistatic void free_formats(struct tep_format *format)
74938c2ecf20Sopenharmony_ci{
74948c2ecf20Sopenharmony_ci	free_format_fields(format->common_fields);
74958c2ecf20Sopenharmony_ci	free_format_fields(format->fields);
74968c2ecf20Sopenharmony_ci}
74978c2ecf20Sopenharmony_ci
74988c2ecf20Sopenharmony_ci__hidden void free_tep_event(struct tep_event *event)
74998c2ecf20Sopenharmony_ci{
75008c2ecf20Sopenharmony_ci	free(event->name);
75018c2ecf20Sopenharmony_ci	free(event->system);
75028c2ecf20Sopenharmony_ci
75038c2ecf20Sopenharmony_ci	free_formats(&event->format);
75048c2ecf20Sopenharmony_ci
75058c2ecf20Sopenharmony_ci	free(event->print_fmt.format);
75068c2ecf20Sopenharmony_ci	free_args(event->print_fmt.args);
75078c2ecf20Sopenharmony_ci	free_parse_args(event->print_fmt.print_cache);
75088c2ecf20Sopenharmony_ci	free(event);
75098c2ecf20Sopenharmony_ci}
75108c2ecf20Sopenharmony_ci
75118c2ecf20Sopenharmony_ci/**
75128c2ecf20Sopenharmony_ci * tep_free - free a tep handle
75138c2ecf20Sopenharmony_ci * @tep: the tep handle to free
75148c2ecf20Sopenharmony_ci */
75158c2ecf20Sopenharmony_civoid tep_free(struct tep_handle *tep)
75168c2ecf20Sopenharmony_ci{
75178c2ecf20Sopenharmony_ci	struct cmdline_list *cmdlist, *cmdnext;
75188c2ecf20Sopenharmony_ci	struct func_list *funclist, *funcnext;
75198c2ecf20Sopenharmony_ci	struct printk_list *printklist, *printknext;
75208c2ecf20Sopenharmony_ci	struct tep_function_handler *func_handler;
75218c2ecf20Sopenharmony_ci	struct event_handler *handle;
75228c2ecf20Sopenharmony_ci	int i;
75238c2ecf20Sopenharmony_ci
75248c2ecf20Sopenharmony_ci	if (!tep)
75258c2ecf20Sopenharmony_ci		return;
75268c2ecf20Sopenharmony_ci
75278c2ecf20Sopenharmony_ci	cmdlist = tep->cmdlist;
75288c2ecf20Sopenharmony_ci	funclist = tep->funclist;
75298c2ecf20Sopenharmony_ci	printklist = tep->printklist;
75308c2ecf20Sopenharmony_ci
75318c2ecf20Sopenharmony_ci	tep->ref_count--;
75328c2ecf20Sopenharmony_ci	if (tep->ref_count)
75338c2ecf20Sopenharmony_ci		return;
75348c2ecf20Sopenharmony_ci
75358c2ecf20Sopenharmony_ci	if (tep->cmdlines) {
75368c2ecf20Sopenharmony_ci		for (i = 0; i < tep->cmdline_count; i++)
75378c2ecf20Sopenharmony_ci			free(tep->cmdlines[i].comm);
75388c2ecf20Sopenharmony_ci		free(tep->cmdlines);
75398c2ecf20Sopenharmony_ci	}
75408c2ecf20Sopenharmony_ci
75418c2ecf20Sopenharmony_ci	while (cmdlist) {
75428c2ecf20Sopenharmony_ci		cmdnext = cmdlist->next;
75438c2ecf20Sopenharmony_ci		free(cmdlist->comm);
75448c2ecf20Sopenharmony_ci		free(cmdlist);
75458c2ecf20Sopenharmony_ci		cmdlist = cmdnext;
75468c2ecf20Sopenharmony_ci	}
75478c2ecf20Sopenharmony_ci
75488c2ecf20Sopenharmony_ci	if (tep->func_map) {
75498c2ecf20Sopenharmony_ci		for (i = 0; i < (int)tep->func_count; i++) {
75508c2ecf20Sopenharmony_ci			free(tep->func_map[i].func);
75518c2ecf20Sopenharmony_ci			free(tep->func_map[i].mod);
75528c2ecf20Sopenharmony_ci		}
75538c2ecf20Sopenharmony_ci		free(tep->func_map);
75548c2ecf20Sopenharmony_ci	}
75558c2ecf20Sopenharmony_ci
75568c2ecf20Sopenharmony_ci	while (funclist) {
75578c2ecf20Sopenharmony_ci		funcnext = funclist->next;
75588c2ecf20Sopenharmony_ci		free(funclist->func);
75598c2ecf20Sopenharmony_ci		free(funclist->mod);
75608c2ecf20Sopenharmony_ci		free(funclist);
75618c2ecf20Sopenharmony_ci		funclist = funcnext;
75628c2ecf20Sopenharmony_ci	}
75638c2ecf20Sopenharmony_ci
75648c2ecf20Sopenharmony_ci	while (tep->func_handlers) {
75658c2ecf20Sopenharmony_ci		func_handler = tep->func_handlers;
75668c2ecf20Sopenharmony_ci		tep->func_handlers = func_handler->next;
75678c2ecf20Sopenharmony_ci		free_func_handle(func_handler);
75688c2ecf20Sopenharmony_ci	}
75698c2ecf20Sopenharmony_ci
75708c2ecf20Sopenharmony_ci	if (tep->printk_map) {
75718c2ecf20Sopenharmony_ci		for (i = 0; i < (int)tep->printk_count; i++)
75728c2ecf20Sopenharmony_ci			free(tep->printk_map[i].printk);
75738c2ecf20Sopenharmony_ci		free(tep->printk_map);
75748c2ecf20Sopenharmony_ci	}
75758c2ecf20Sopenharmony_ci
75768c2ecf20Sopenharmony_ci	while (printklist) {
75778c2ecf20Sopenharmony_ci		printknext = printklist->next;
75788c2ecf20Sopenharmony_ci		free(printklist->printk);
75798c2ecf20Sopenharmony_ci		free(printklist);
75808c2ecf20Sopenharmony_ci		printklist = printknext;
75818c2ecf20Sopenharmony_ci	}
75828c2ecf20Sopenharmony_ci
75838c2ecf20Sopenharmony_ci	for (i = 0; i < tep->nr_events; i++)
75848c2ecf20Sopenharmony_ci		free_tep_event(tep->events[i]);
75858c2ecf20Sopenharmony_ci
75868c2ecf20Sopenharmony_ci	while (tep->handlers) {
75878c2ecf20Sopenharmony_ci		handle = tep->handlers;
75888c2ecf20Sopenharmony_ci		tep->handlers = handle->next;
75898c2ecf20Sopenharmony_ci		free_handler(handle);
75908c2ecf20Sopenharmony_ci	}
75918c2ecf20Sopenharmony_ci
75928c2ecf20Sopenharmony_ci	free(tep->events);
75938c2ecf20Sopenharmony_ci	free(tep->sort_events);
75948c2ecf20Sopenharmony_ci	free(tep->func_resolver);
75958c2ecf20Sopenharmony_ci	free_tep_plugin_paths(tep);
75968c2ecf20Sopenharmony_ci
75978c2ecf20Sopenharmony_ci	free(tep);
75988c2ecf20Sopenharmony_ci}
75998c2ecf20Sopenharmony_ci
76008c2ecf20Sopenharmony_civoid tep_unref(struct tep_handle *tep)
76018c2ecf20Sopenharmony_ci{
76028c2ecf20Sopenharmony_ci	tep_free(tep);
76038c2ecf20Sopenharmony_ci}
7604