xref: /aosp_15_r20/external/libtraceevent/src/event-parse.c (revision 436bf2bcd5202612ffffe471bbcc1f277cc8d28e)
1*436bf2bcSAndroid Build Coastguard Worker // SPDX-License-Identifier: LGPL-2.1
2*436bf2bcSAndroid Build Coastguard Worker /*
3*436bf2bcSAndroid Build Coastguard Worker  * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <[email protected]>
4*436bf2bcSAndroid Build Coastguard Worker  *
5*436bf2bcSAndroid Build Coastguard Worker  *
6*436bf2bcSAndroid Build Coastguard Worker  *  The parts for function graph printing was taken and modified from the
7*436bf2bcSAndroid Build Coastguard Worker  *  Linux Kernel that were written by
8*436bf2bcSAndroid Build Coastguard Worker  *    - Copyright (C) 2009  Frederic Weisbecker,
9*436bf2bcSAndroid Build Coastguard Worker  *  Frederic Weisbecker gave his permission to relicense the code to
10*436bf2bcSAndroid Build Coastguard Worker  *  the Lesser General Public License.
11*436bf2bcSAndroid Build Coastguard Worker  */
12*436bf2bcSAndroid Build Coastguard Worker #include <inttypes.h>
13*436bf2bcSAndroid Build Coastguard Worker #include <stdio.h>
14*436bf2bcSAndroid Build Coastguard Worker #include <stdlib.h>
15*436bf2bcSAndroid Build Coastguard Worker #include <string.h>
16*436bf2bcSAndroid Build Coastguard Worker #include <stdarg.h>
17*436bf2bcSAndroid Build Coastguard Worker #include <ctype.h>
18*436bf2bcSAndroid Build Coastguard Worker #include <errno.h>
19*436bf2bcSAndroid Build Coastguard Worker #include <stdint.h>
20*436bf2bcSAndroid Build Coastguard Worker #include <unistd.h>
21*436bf2bcSAndroid Build Coastguard Worker #include <limits.h>
22*436bf2bcSAndroid Build Coastguard Worker #include <linux/time64.h>
23*436bf2bcSAndroid Build Coastguard Worker 
24*436bf2bcSAndroid Build Coastguard Worker #include <netinet/in.h>
25*436bf2bcSAndroid Build Coastguard Worker #include "event-parse.h"
26*436bf2bcSAndroid Build Coastguard Worker 
27*436bf2bcSAndroid Build Coastguard Worker #include "event-parse-local.h"
28*436bf2bcSAndroid Build Coastguard Worker #include "event-utils.h"
29*436bf2bcSAndroid Build Coastguard Worker #include "trace-seq.h"
30*436bf2bcSAndroid Build Coastguard Worker 
31*436bf2bcSAndroid Build Coastguard Worker static int is_flag_field;
32*436bf2bcSAndroid Build Coastguard Worker static int is_symbolic_field;
33*436bf2bcSAndroid Build Coastguard Worker 
34*436bf2bcSAndroid Build Coastguard Worker static int show_warning = 1;
35*436bf2bcSAndroid Build Coastguard Worker 
36*436bf2bcSAndroid Build Coastguard Worker #define do_warning(fmt, ...)				\
37*436bf2bcSAndroid Build Coastguard Worker 	do {						\
38*436bf2bcSAndroid Build Coastguard Worker 		if (show_warning)			\
39*436bf2bcSAndroid Build Coastguard Worker 			tep_warning(fmt, ##__VA_ARGS__);\
40*436bf2bcSAndroid Build Coastguard Worker 	} while (0)
41*436bf2bcSAndroid Build Coastguard Worker 
42*436bf2bcSAndroid Build Coastguard Worker #define do_warning_event(event, fmt, ...)				\
43*436bf2bcSAndroid Build Coastguard Worker 	do {								\
44*436bf2bcSAndroid Build Coastguard Worker 		if (!show_warning)					\
45*436bf2bcSAndroid Build Coastguard Worker 			continue;					\
46*436bf2bcSAndroid Build Coastguard Worker 									\
47*436bf2bcSAndroid Build Coastguard Worker 		if (event)						\
48*436bf2bcSAndroid Build Coastguard Worker 			tep_warning("[%s:%s] " fmt, event->system,	\
49*436bf2bcSAndroid Build Coastguard Worker 				    event->name, ##__VA_ARGS__);	\
50*436bf2bcSAndroid Build Coastguard Worker 		else							\
51*436bf2bcSAndroid Build Coastguard Worker 			tep_warning(fmt, ##__VA_ARGS__);		\
52*436bf2bcSAndroid Build Coastguard Worker 	} while (0)
53*436bf2bcSAndroid Build Coastguard Worker 
54*436bf2bcSAndroid Build Coastguard Worker /**
55*436bf2bcSAndroid Build Coastguard Worker  * init_input_buf - init buffer for parsing
56*436bf2bcSAndroid Build Coastguard Worker  * @buf: buffer to parse
57*436bf2bcSAndroid Build Coastguard Worker  * @size: the size of the buffer
58*436bf2bcSAndroid Build Coastguard Worker  *
59*436bf2bcSAndroid Build Coastguard Worker  * Initializes the internal buffer that tep_read_token() will parse.
60*436bf2bcSAndroid Build Coastguard Worker  */
init_input_buf(struct tep_handle * tep,const char * buf,unsigned long long size)61*436bf2bcSAndroid Build Coastguard Worker __hidden void init_input_buf(struct tep_handle *tep, const char *buf,
62*436bf2bcSAndroid Build Coastguard Worker 		unsigned long long size)
63*436bf2bcSAndroid Build Coastguard Worker {
64*436bf2bcSAndroid Build Coastguard Worker 	tep->input_buf = buf;
65*436bf2bcSAndroid Build Coastguard Worker 	tep->input_buf_siz = size;
66*436bf2bcSAndroid Build Coastguard Worker 	tep->input_buf_ptr = 0;
67*436bf2bcSAndroid Build Coastguard Worker }
68*436bf2bcSAndroid Build Coastguard Worker 
get_input_buf(struct tep_handle * tep)69*436bf2bcSAndroid Build Coastguard Worker __hidden const char *get_input_buf(struct tep_handle *tep)
70*436bf2bcSAndroid Build Coastguard Worker {
71*436bf2bcSAndroid Build Coastguard Worker 	return tep->input_buf;
72*436bf2bcSAndroid Build Coastguard Worker }
73*436bf2bcSAndroid Build Coastguard Worker 
get_input_buf_ptr(struct tep_handle * tep)74*436bf2bcSAndroid Build Coastguard Worker __hidden unsigned long long get_input_buf_ptr(struct tep_handle *tep)
75*436bf2bcSAndroid Build Coastguard Worker {
76*436bf2bcSAndroid Build Coastguard Worker 	return tep->input_buf_ptr;
77*436bf2bcSAndroid Build Coastguard Worker }
78*436bf2bcSAndroid Build Coastguard Worker 
79*436bf2bcSAndroid Build Coastguard Worker struct event_handler {
80*436bf2bcSAndroid Build Coastguard Worker 	struct event_handler		*next;
81*436bf2bcSAndroid Build Coastguard Worker 	int				id;
82*436bf2bcSAndroid Build Coastguard Worker 	const char			*sys_name;
83*436bf2bcSAndroid Build Coastguard Worker 	const char			*event_name;
84*436bf2bcSAndroid Build Coastguard Worker 	tep_event_handler_func		func;
85*436bf2bcSAndroid Build Coastguard Worker 	void				*context;
86*436bf2bcSAndroid Build Coastguard Worker };
87*436bf2bcSAndroid Build Coastguard Worker 
88*436bf2bcSAndroid Build Coastguard Worker struct func_params {
89*436bf2bcSAndroid Build Coastguard Worker 	struct func_params	*next;
90*436bf2bcSAndroid Build Coastguard Worker 	enum tep_func_arg_type	type;
91*436bf2bcSAndroid Build Coastguard Worker };
92*436bf2bcSAndroid Build Coastguard Worker 
93*436bf2bcSAndroid Build Coastguard Worker struct tep_function_handler {
94*436bf2bcSAndroid Build Coastguard Worker 	struct tep_function_handler	*next;
95*436bf2bcSAndroid Build Coastguard Worker 	enum tep_func_arg_type		ret_type;
96*436bf2bcSAndroid Build Coastguard Worker 	char				*name;
97*436bf2bcSAndroid Build Coastguard Worker 	tep_func_handler		func;
98*436bf2bcSAndroid Build Coastguard Worker 	struct func_params		*params;
99*436bf2bcSAndroid Build Coastguard Worker 	int				nr_args;
100*436bf2bcSAndroid Build Coastguard Worker };
101*436bf2bcSAndroid Build Coastguard Worker 
102*436bf2bcSAndroid Build Coastguard Worker static unsigned long long
103*436bf2bcSAndroid Build Coastguard Worker process_defined_func(struct trace_seq *s, void *data, int size,
104*436bf2bcSAndroid Build Coastguard Worker 		     struct tep_event *event, struct tep_print_arg *arg);
105*436bf2bcSAndroid Build Coastguard Worker 
106*436bf2bcSAndroid Build Coastguard Worker static void free_func_handle(struct tep_function_handler *func);
107*436bf2bcSAndroid Build Coastguard Worker 
breakpoint(void)108*436bf2bcSAndroid Build Coastguard Worker void breakpoint(void)
109*436bf2bcSAndroid Build Coastguard Worker {
110*436bf2bcSAndroid Build Coastguard Worker 	static int x;
111*436bf2bcSAndroid Build Coastguard Worker 	x++;
112*436bf2bcSAndroid Build Coastguard Worker }
113*436bf2bcSAndroid Build Coastguard Worker 
get_event_type(enum tep_event_type type)114*436bf2bcSAndroid Build Coastguard Worker static const char *get_event_type(enum tep_event_type type)
115*436bf2bcSAndroid Build Coastguard Worker {
116*436bf2bcSAndroid Build Coastguard Worker 	switch (type) {
117*436bf2bcSAndroid Build Coastguard Worker 	case TEP_EVENT_ERROR: return "ERROR";
118*436bf2bcSAndroid Build Coastguard Worker 	case TEP_EVENT_NONE: return "NONE";
119*436bf2bcSAndroid Build Coastguard Worker 	case TEP_EVENT_SPACE: return "SPACE";
120*436bf2bcSAndroid Build Coastguard Worker 	case TEP_EVENT_NEWLINE: return "NEWLINE";
121*436bf2bcSAndroid Build Coastguard Worker 	case TEP_EVENT_OP: return "OP";
122*436bf2bcSAndroid Build Coastguard Worker 	case TEP_EVENT_DELIM: return "DELIM";
123*436bf2bcSAndroid Build Coastguard Worker 	case TEP_EVENT_ITEM: return "ITEM";
124*436bf2bcSAndroid Build Coastguard Worker 	case TEP_EVENT_DQUOTE: return "DQUOTE";
125*436bf2bcSAndroid Build Coastguard Worker 	case TEP_EVENT_SQUOTE: return "SQUOTE";
126*436bf2bcSAndroid Build Coastguard Worker 	}
127*436bf2bcSAndroid Build Coastguard Worker 	return "(UNKNOWN)";
128*436bf2bcSAndroid Build Coastguard Worker }
129*436bf2bcSAndroid Build Coastguard Worker 
alloc_arg(void)130*436bf2bcSAndroid Build Coastguard Worker static struct tep_print_arg *alloc_arg(void)
131*436bf2bcSAndroid Build Coastguard Worker {
132*436bf2bcSAndroid Build Coastguard Worker 	return calloc(1, sizeof(struct tep_print_arg));
133*436bf2bcSAndroid Build Coastguard Worker }
134*436bf2bcSAndroid Build Coastguard Worker 
135*436bf2bcSAndroid Build Coastguard Worker struct tep_cmdline {
136*436bf2bcSAndroid Build Coastguard Worker 	char *comm;
137*436bf2bcSAndroid Build Coastguard Worker 	int pid;
138*436bf2bcSAndroid Build Coastguard Worker };
139*436bf2bcSAndroid Build Coastguard Worker 
cmdline_cmp(const void * a,const void * b)140*436bf2bcSAndroid Build Coastguard Worker static int cmdline_cmp(const void *a, const void *b)
141*436bf2bcSAndroid Build Coastguard Worker {
142*436bf2bcSAndroid Build Coastguard Worker 	const struct tep_cmdline *ca = a;
143*436bf2bcSAndroid Build Coastguard Worker 	const struct tep_cmdline *cb = b;
144*436bf2bcSAndroid Build Coastguard Worker 
145*436bf2bcSAndroid Build Coastguard Worker 	if (ca->pid < cb->pid)
146*436bf2bcSAndroid Build Coastguard Worker 		return -1;
147*436bf2bcSAndroid Build Coastguard Worker 	if (ca->pid > cb->pid)
148*436bf2bcSAndroid Build Coastguard Worker 		return 1;
149*436bf2bcSAndroid Build Coastguard Worker 
150*436bf2bcSAndroid Build Coastguard Worker 	return 0;
151*436bf2bcSAndroid Build Coastguard Worker }
152*436bf2bcSAndroid Build Coastguard Worker 
153*436bf2bcSAndroid Build Coastguard Worker /* Looking for where to place the key */
cmdline_slot_cmp(const void * a,const void * b)154*436bf2bcSAndroid Build Coastguard Worker static int cmdline_slot_cmp(const void *a, const void *b)
155*436bf2bcSAndroid Build Coastguard Worker {
156*436bf2bcSAndroid Build Coastguard Worker 	const struct tep_cmdline *ca = a;
157*436bf2bcSAndroid Build Coastguard Worker 	const struct tep_cmdline *cb = b;
158*436bf2bcSAndroid Build Coastguard Worker 	const struct tep_cmdline *cb1 = cb + 1;
159*436bf2bcSAndroid Build Coastguard Worker 
160*436bf2bcSAndroid Build Coastguard Worker 	if (ca->pid < cb->pid)
161*436bf2bcSAndroid Build Coastguard Worker 		return -1;
162*436bf2bcSAndroid Build Coastguard Worker 
163*436bf2bcSAndroid Build Coastguard Worker 	if (ca->pid > cb->pid) {
164*436bf2bcSAndroid Build Coastguard Worker 		if (ca->pid <= cb1->pid)
165*436bf2bcSAndroid Build Coastguard Worker 			return 0;
166*436bf2bcSAndroid Build Coastguard Worker 		return 1;
167*436bf2bcSAndroid Build Coastguard Worker 	}
168*436bf2bcSAndroid Build Coastguard Worker 
169*436bf2bcSAndroid Build Coastguard Worker 	return 0;
170*436bf2bcSAndroid Build Coastguard Worker }
171*436bf2bcSAndroid Build Coastguard Worker 
172*436bf2bcSAndroid Build Coastguard Worker struct cmdline_list {
173*436bf2bcSAndroid Build Coastguard Worker 	struct cmdline_list	*next;
174*436bf2bcSAndroid Build Coastguard Worker 	char			*comm;
175*436bf2bcSAndroid Build Coastguard Worker 	int			pid;
176*436bf2bcSAndroid Build Coastguard Worker };
177*436bf2bcSAndroid Build Coastguard Worker 
cmdline_init(struct tep_handle * tep)178*436bf2bcSAndroid Build Coastguard Worker static int cmdline_init(struct tep_handle *tep)
179*436bf2bcSAndroid Build Coastguard Worker {
180*436bf2bcSAndroid Build Coastguard Worker 	struct cmdline_list *cmdlist = tep->cmdlist;
181*436bf2bcSAndroid Build Coastguard Worker 	struct cmdline_list *item;
182*436bf2bcSAndroid Build Coastguard Worker 	struct tep_cmdline *cmdlines;
183*436bf2bcSAndroid Build Coastguard Worker 	int i;
184*436bf2bcSAndroid Build Coastguard Worker 
185*436bf2bcSAndroid Build Coastguard Worker 	cmdlines = malloc(sizeof(*cmdlines) * tep->cmdline_count);
186*436bf2bcSAndroid Build Coastguard Worker 	if (!cmdlines)
187*436bf2bcSAndroid Build Coastguard Worker 		return -1;
188*436bf2bcSAndroid Build Coastguard Worker 
189*436bf2bcSAndroid Build Coastguard Worker 	i = 0;
190*436bf2bcSAndroid Build Coastguard Worker 	while (cmdlist) {
191*436bf2bcSAndroid Build Coastguard Worker 		cmdlines[i].pid = cmdlist->pid;
192*436bf2bcSAndroid Build Coastguard Worker 		cmdlines[i].comm = cmdlist->comm;
193*436bf2bcSAndroid Build Coastguard Worker 		i++;
194*436bf2bcSAndroid Build Coastguard Worker 		item = cmdlist;
195*436bf2bcSAndroid Build Coastguard Worker 		cmdlist = cmdlist->next;
196*436bf2bcSAndroid Build Coastguard Worker 		free(item);
197*436bf2bcSAndroid Build Coastguard Worker 	}
198*436bf2bcSAndroid Build Coastguard Worker 
199*436bf2bcSAndroid Build Coastguard Worker 	qsort(cmdlines, tep->cmdline_count, sizeof(*cmdlines), cmdline_cmp);
200*436bf2bcSAndroid Build Coastguard Worker 
201*436bf2bcSAndroid Build Coastguard Worker 	tep->cmdlines = cmdlines;
202*436bf2bcSAndroid Build Coastguard Worker 	tep->cmdlist = NULL;
203*436bf2bcSAndroid Build Coastguard Worker 
204*436bf2bcSAndroid Build Coastguard Worker 	return 0;
205*436bf2bcSAndroid Build Coastguard Worker }
206*436bf2bcSAndroid Build Coastguard Worker 
find_cmdline(struct tep_handle * tep,int pid)207*436bf2bcSAndroid Build Coastguard Worker static const char *find_cmdline(struct tep_handle *tep, int pid)
208*436bf2bcSAndroid Build Coastguard Worker {
209*436bf2bcSAndroid Build Coastguard Worker 	const struct tep_cmdline *comm;
210*436bf2bcSAndroid Build Coastguard Worker 	struct tep_cmdline key;
211*436bf2bcSAndroid Build Coastguard Worker 
212*436bf2bcSAndroid Build Coastguard Worker 	if (!pid)
213*436bf2bcSAndroid Build Coastguard Worker 		return "<idle>";
214*436bf2bcSAndroid Build Coastguard Worker 
215*436bf2bcSAndroid Build Coastguard Worker 	if (!tep->cmdlines && cmdline_init(tep))
216*436bf2bcSAndroid Build Coastguard Worker 		return "<not enough memory for cmdlines!>";
217*436bf2bcSAndroid Build Coastguard Worker 
218*436bf2bcSAndroid Build Coastguard Worker 	key.pid = pid;
219*436bf2bcSAndroid Build Coastguard Worker 
220*436bf2bcSAndroid Build Coastguard Worker 	comm = bsearch(&key, tep->cmdlines, tep->cmdline_count,
221*436bf2bcSAndroid Build Coastguard Worker 		       sizeof(*tep->cmdlines), cmdline_cmp);
222*436bf2bcSAndroid Build Coastguard Worker 
223*436bf2bcSAndroid Build Coastguard Worker 	if (comm)
224*436bf2bcSAndroid Build Coastguard Worker 		return comm->comm;
225*436bf2bcSAndroid Build Coastguard Worker 	return "<...>";
226*436bf2bcSAndroid Build Coastguard Worker }
227*436bf2bcSAndroid Build Coastguard Worker 
228*436bf2bcSAndroid Build Coastguard Worker /**
229*436bf2bcSAndroid Build Coastguard Worker  * tep_is_pid_registered - return if a pid has a cmdline registered
230*436bf2bcSAndroid Build Coastguard Worker  * @tep: a handle to the trace event parser context
231*436bf2bcSAndroid Build Coastguard Worker  * @pid: The pid to check if it has a cmdline registered with.
232*436bf2bcSAndroid Build Coastguard Worker  *
233*436bf2bcSAndroid Build Coastguard Worker  * Returns true if the pid has a cmdline mapped to it
234*436bf2bcSAndroid Build Coastguard Worker  * false otherwise.
235*436bf2bcSAndroid Build Coastguard Worker  */
tep_is_pid_registered(struct tep_handle * tep,int pid)236*436bf2bcSAndroid Build Coastguard Worker bool tep_is_pid_registered(struct tep_handle *tep, int pid)
237*436bf2bcSAndroid Build Coastguard Worker {
238*436bf2bcSAndroid Build Coastguard Worker 	const struct tep_cmdline *comm;
239*436bf2bcSAndroid Build Coastguard Worker 	struct tep_cmdline key;
240*436bf2bcSAndroid Build Coastguard Worker 
241*436bf2bcSAndroid Build Coastguard Worker 	if (!pid)
242*436bf2bcSAndroid Build Coastguard Worker 		return true;
243*436bf2bcSAndroid Build Coastguard Worker 
244*436bf2bcSAndroid Build Coastguard Worker 	if (!tep->cmdlines && cmdline_init(tep))
245*436bf2bcSAndroid Build Coastguard Worker 		return false;
246*436bf2bcSAndroid Build Coastguard Worker 
247*436bf2bcSAndroid Build Coastguard Worker 	key.pid = pid;
248*436bf2bcSAndroid Build Coastguard Worker 
249*436bf2bcSAndroid Build Coastguard Worker 	comm = bsearch(&key, tep->cmdlines, tep->cmdline_count,
250*436bf2bcSAndroid Build Coastguard Worker 		       sizeof(*tep->cmdlines), cmdline_cmp);
251*436bf2bcSAndroid Build Coastguard Worker 
252*436bf2bcSAndroid Build Coastguard Worker 	if (comm)
253*436bf2bcSAndroid Build Coastguard Worker 		return true;
254*436bf2bcSAndroid Build Coastguard Worker 	return false;
255*436bf2bcSAndroid Build Coastguard Worker }
256*436bf2bcSAndroid Build Coastguard Worker 
257*436bf2bcSAndroid Build Coastguard Worker /*
258*436bf2bcSAndroid Build Coastguard Worker  * If the command lines have been converted to an array, then
259*436bf2bcSAndroid Build Coastguard Worker  * we must add this pid. This is much slower than when cmdlines
260*436bf2bcSAndroid Build Coastguard Worker  * are added before the array is initialized.
261*436bf2bcSAndroid Build Coastguard Worker  */
add_new_comm(struct tep_handle * tep,const char * comm,int pid,bool override)262*436bf2bcSAndroid Build Coastguard Worker static int add_new_comm(struct tep_handle *tep,
263*436bf2bcSAndroid Build Coastguard Worker 			const char *comm, int pid, bool override)
264*436bf2bcSAndroid Build Coastguard Worker {
265*436bf2bcSAndroid Build Coastguard Worker 	struct tep_cmdline *cmdlines = tep->cmdlines;
266*436bf2bcSAndroid Build Coastguard Worker 	struct tep_cmdline *cmdline;
267*436bf2bcSAndroid Build Coastguard Worker 	struct tep_cmdline key;
268*436bf2bcSAndroid Build Coastguard Worker 	char *new_comm;
269*436bf2bcSAndroid Build Coastguard Worker 	int cnt;
270*436bf2bcSAndroid Build Coastguard Worker 
271*436bf2bcSAndroid Build Coastguard Worker 	if (!pid)
272*436bf2bcSAndroid Build Coastguard Worker 		return 0;
273*436bf2bcSAndroid Build Coastguard Worker 
274*436bf2bcSAndroid Build Coastguard Worker 	/* avoid duplicates */
275*436bf2bcSAndroid Build Coastguard Worker 	key.pid = pid;
276*436bf2bcSAndroid Build Coastguard Worker 
277*436bf2bcSAndroid Build Coastguard Worker 	cmdline = bsearch(&key, tep->cmdlines, tep->cmdline_count,
278*436bf2bcSAndroid Build Coastguard Worker 			  sizeof(*tep->cmdlines), cmdline_cmp);
279*436bf2bcSAndroid Build Coastguard Worker 	if (cmdline) {
280*436bf2bcSAndroid Build Coastguard Worker 		if (!override) {
281*436bf2bcSAndroid Build Coastguard Worker 			errno = EEXIST;
282*436bf2bcSAndroid Build Coastguard Worker 			return -1;
283*436bf2bcSAndroid Build Coastguard Worker 		}
284*436bf2bcSAndroid Build Coastguard Worker 		new_comm = strdup(comm);
285*436bf2bcSAndroid Build Coastguard Worker 		if (!new_comm) {
286*436bf2bcSAndroid Build Coastguard Worker 			errno = ENOMEM;
287*436bf2bcSAndroid Build Coastguard Worker 			return -1;
288*436bf2bcSAndroid Build Coastguard Worker 		}
289*436bf2bcSAndroid Build Coastguard Worker 		free(cmdline->comm);
290*436bf2bcSAndroid Build Coastguard Worker 		cmdline->comm = new_comm;
291*436bf2bcSAndroid Build Coastguard Worker 
292*436bf2bcSAndroid Build Coastguard Worker 		return 0;
293*436bf2bcSAndroid Build Coastguard Worker 	}
294*436bf2bcSAndroid Build Coastguard Worker 
295*436bf2bcSAndroid Build Coastguard Worker 	cmdlines = realloc(cmdlines, sizeof(*cmdlines) * (tep->cmdline_count + 1));
296*436bf2bcSAndroid Build Coastguard Worker 	if (!cmdlines) {
297*436bf2bcSAndroid Build Coastguard Worker 		errno = ENOMEM;
298*436bf2bcSAndroid Build Coastguard Worker 		return -1;
299*436bf2bcSAndroid Build Coastguard Worker 	}
300*436bf2bcSAndroid Build Coastguard Worker 	tep->cmdlines = cmdlines;
301*436bf2bcSAndroid Build Coastguard Worker 
302*436bf2bcSAndroid Build Coastguard Worker 	key.comm = strdup(comm);
303*436bf2bcSAndroid Build Coastguard Worker 	if (!key.comm) {
304*436bf2bcSAndroid Build Coastguard Worker 		errno = ENOMEM;
305*436bf2bcSAndroid Build Coastguard Worker 		return -1;
306*436bf2bcSAndroid Build Coastguard Worker 	}
307*436bf2bcSAndroid Build Coastguard Worker 
308*436bf2bcSAndroid Build Coastguard Worker 	if (!tep->cmdline_count) {
309*436bf2bcSAndroid Build Coastguard Worker 		/* no entries yet */
310*436bf2bcSAndroid Build Coastguard Worker 		tep->cmdlines[0] = key;
311*436bf2bcSAndroid Build Coastguard Worker 		tep->cmdline_count++;
312*436bf2bcSAndroid Build Coastguard Worker 		return 0;
313*436bf2bcSAndroid Build Coastguard Worker 	}
314*436bf2bcSAndroid Build Coastguard Worker 
315*436bf2bcSAndroid Build Coastguard Worker 	/* Now find where we want to store the new cmdline */
316*436bf2bcSAndroid Build Coastguard Worker 	cmdline = bsearch(&key, tep->cmdlines, tep->cmdline_count - 1,
317*436bf2bcSAndroid Build Coastguard Worker 			  sizeof(*tep->cmdlines), cmdline_slot_cmp);
318*436bf2bcSAndroid Build Coastguard Worker 
319*436bf2bcSAndroid Build Coastguard Worker 	cnt = tep->cmdline_count;
320*436bf2bcSAndroid Build Coastguard Worker 	if (cmdline) {
321*436bf2bcSAndroid Build Coastguard Worker 		/* cmdline points to the one before the spot we want */
322*436bf2bcSAndroid Build Coastguard Worker 		cmdline++;
323*436bf2bcSAndroid Build Coastguard Worker 		cnt -= cmdline - tep->cmdlines;
324*436bf2bcSAndroid Build Coastguard Worker 
325*436bf2bcSAndroid Build Coastguard Worker 	} else {
326*436bf2bcSAndroid Build Coastguard Worker 		/* The new entry is either before or after the list */
327*436bf2bcSAndroid Build Coastguard Worker 		if (key.pid > tep->cmdlines[tep->cmdline_count - 1].pid) {
328*436bf2bcSAndroid Build Coastguard Worker 			tep->cmdlines[tep->cmdline_count++] = key;
329*436bf2bcSAndroid Build Coastguard Worker 			return 0;
330*436bf2bcSAndroid Build Coastguard Worker 		}
331*436bf2bcSAndroid Build Coastguard Worker 		cmdline = &tep->cmdlines[0];
332*436bf2bcSAndroid Build Coastguard Worker 	}
333*436bf2bcSAndroid Build Coastguard Worker 	memmove(cmdline + 1, cmdline, (cnt * sizeof(*cmdline)));
334*436bf2bcSAndroid Build Coastguard Worker 	*cmdline = key;
335*436bf2bcSAndroid Build Coastguard Worker 
336*436bf2bcSAndroid Build Coastguard Worker 	tep->cmdline_count++;
337*436bf2bcSAndroid Build Coastguard Worker 
338*436bf2bcSAndroid Build Coastguard Worker 	return 0;
339*436bf2bcSAndroid Build Coastguard Worker }
340*436bf2bcSAndroid Build Coastguard Worker 
_tep_register_comm(struct tep_handle * tep,const char * comm,int pid,bool override)341*436bf2bcSAndroid Build Coastguard Worker static int _tep_register_comm(struct tep_handle *tep,
342*436bf2bcSAndroid Build Coastguard Worker 			      const char *comm, int pid, bool override)
343*436bf2bcSAndroid Build Coastguard Worker {
344*436bf2bcSAndroid Build Coastguard Worker 	struct cmdline_list *item;
345*436bf2bcSAndroid Build Coastguard Worker 
346*436bf2bcSAndroid Build Coastguard Worker 	if (tep->cmdlines)
347*436bf2bcSAndroid Build Coastguard Worker 		return add_new_comm(tep, comm, pid, override);
348*436bf2bcSAndroid Build Coastguard Worker 
349*436bf2bcSAndroid Build Coastguard Worker 	item = malloc(sizeof(*item));
350*436bf2bcSAndroid Build Coastguard Worker 	if (!item)
351*436bf2bcSAndroid Build Coastguard Worker 		return -1;
352*436bf2bcSAndroid Build Coastguard Worker 
353*436bf2bcSAndroid Build Coastguard Worker 	if (comm)
354*436bf2bcSAndroid Build Coastguard Worker 		item->comm = strdup(comm);
355*436bf2bcSAndroid Build Coastguard Worker 	else
356*436bf2bcSAndroid Build Coastguard Worker 		item->comm = strdup("<...>");
357*436bf2bcSAndroid Build Coastguard Worker 	if (!item->comm) {
358*436bf2bcSAndroid Build Coastguard Worker 		free(item);
359*436bf2bcSAndroid Build Coastguard Worker 		return -1;
360*436bf2bcSAndroid Build Coastguard Worker 	}
361*436bf2bcSAndroid Build Coastguard Worker 	item->pid = pid;
362*436bf2bcSAndroid Build Coastguard Worker 	item->next = tep->cmdlist;
363*436bf2bcSAndroid Build Coastguard Worker 
364*436bf2bcSAndroid Build Coastguard Worker 	tep->cmdlist = item;
365*436bf2bcSAndroid Build Coastguard Worker 	tep->cmdline_count++;
366*436bf2bcSAndroid Build Coastguard Worker 
367*436bf2bcSAndroid Build Coastguard Worker 	return 0;
368*436bf2bcSAndroid Build Coastguard Worker }
369*436bf2bcSAndroid Build Coastguard Worker 
370*436bf2bcSAndroid Build Coastguard Worker /**
371*436bf2bcSAndroid Build Coastguard Worker  * tep_register_comm - register a pid / comm mapping
372*436bf2bcSAndroid Build Coastguard Worker  * @tep: a handle to the trace event parser context
373*436bf2bcSAndroid Build Coastguard Worker  * @comm: the command line to register
374*436bf2bcSAndroid Build Coastguard Worker  * @pid: the pid to map the command line to
375*436bf2bcSAndroid Build Coastguard Worker  *
376*436bf2bcSAndroid Build Coastguard Worker  * This adds a mapping to search for command line names with
377*436bf2bcSAndroid Build Coastguard Worker  * a given pid. The comm is duplicated. If a command with the same pid
378*436bf2bcSAndroid Build Coastguard Worker  * already exist, -1 is returned and errno is set to EEXIST
379*436bf2bcSAndroid Build Coastguard Worker  */
tep_register_comm(struct tep_handle * tep,const char * comm,int pid)380*436bf2bcSAndroid Build Coastguard Worker int tep_register_comm(struct tep_handle *tep, const char *comm, int pid)
381*436bf2bcSAndroid Build Coastguard Worker {
382*436bf2bcSAndroid Build Coastguard Worker 	return _tep_register_comm(tep, comm, pid, false);
383*436bf2bcSAndroid Build Coastguard Worker }
384*436bf2bcSAndroid Build Coastguard Worker 
385*436bf2bcSAndroid Build Coastguard Worker /**
386*436bf2bcSAndroid Build Coastguard Worker  * tep_override_comm - register a pid / comm mapping
387*436bf2bcSAndroid Build Coastguard Worker  * @tep: a handle to the trace event parser context
388*436bf2bcSAndroid Build Coastguard Worker  * @comm: the command line to register
389*436bf2bcSAndroid Build Coastguard Worker  * @pid: the pid to map the command line to
390*436bf2bcSAndroid Build Coastguard Worker  *
391*436bf2bcSAndroid Build Coastguard Worker  * This adds a mapping to search for command line names with
392*436bf2bcSAndroid Build Coastguard Worker  * a given pid. The comm is duplicated. If a command with the same pid
393*436bf2bcSAndroid Build Coastguard Worker  * already exist, the command string is udapted with the new one
394*436bf2bcSAndroid Build Coastguard Worker  */
tep_override_comm(struct tep_handle * tep,const char * comm,int pid)395*436bf2bcSAndroid Build Coastguard Worker int tep_override_comm(struct tep_handle *tep, const char *comm, int pid)
396*436bf2bcSAndroid Build Coastguard Worker {
397*436bf2bcSAndroid Build Coastguard Worker 	if (!tep->cmdlines && cmdline_init(tep)) {
398*436bf2bcSAndroid Build Coastguard Worker 		errno = ENOMEM;
399*436bf2bcSAndroid Build Coastguard Worker 		return -1;
400*436bf2bcSAndroid Build Coastguard Worker 	}
401*436bf2bcSAndroid Build Coastguard Worker 	return _tep_register_comm(tep, comm, pid, true);
402*436bf2bcSAndroid Build Coastguard Worker }
403*436bf2bcSAndroid Build Coastguard Worker 
404*436bf2bcSAndroid Build Coastguard Worker /**
405*436bf2bcSAndroid Build Coastguard Worker  * tep_parse_saved_cmdlines - parse the comms from the saved_cmdlines file
406*436bf2bcSAndroid Build Coastguard Worker  * @tep: a handle to the trace event parser
407*436bf2bcSAndroid Build Coastguard Worker  * @buf: A string buffer that holds the content of saved_cmdlines and ends with '\0'
408*436bf2bcSAndroid Build Coastguard Worker  *
409*436bf2bcSAndroid Build Coastguard Worker  * This is a helper function to parse the comms in the tracefs saved_cmdlines
410*436bf2bcSAndroid Build Coastguard Worker  * file (stored in a string buffer) and load the comms into the @tep handler
411*436bf2bcSAndroid Build Coastguard Worker  * such that comm name matches an process ID (pid). This is used to show
412*436bf2bcSAndroid Build Coastguard Worker  * the names of the processes as the events only hold the pid.
413*436bf2bcSAndroid Build Coastguard Worker  *
414*436bf2bcSAndroid Build Coastguard Worker  * Returns 0 on success, and -1 on error.
415*436bf2bcSAndroid Build Coastguard Worker  */
tep_parse_saved_cmdlines(struct tep_handle * tep,const char * buf)416*436bf2bcSAndroid Build Coastguard Worker int tep_parse_saved_cmdlines(struct tep_handle *tep, const char *buf)
417*436bf2bcSAndroid Build Coastguard Worker {
418*436bf2bcSAndroid Build Coastguard Worker 	char *copy;
419*436bf2bcSAndroid Build Coastguard Worker 	char *comm;
420*436bf2bcSAndroid Build Coastguard Worker 	char *line;
421*436bf2bcSAndroid Build Coastguard Worker 	char *next = NULL;
422*436bf2bcSAndroid Build Coastguard Worker 	int pid;
423*436bf2bcSAndroid Build Coastguard Worker 	int ret = -1;
424*436bf2bcSAndroid Build Coastguard Worker 	int n;
425*436bf2bcSAndroid Build Coastguard Worker 
426*436bf2bcSAndroid Build Coastguard Worker 	copy = strdup(buf);
427*436bf2bcSAndroid Build Coastguard Worker 	if (!copy)
428*436bf2bcSAndroid Build Coastguard Worker 		return -1;
429*436bf2bcSAndroid Build Coastguard Worker 
430*436bf2bcSAndroid Build Coastguard Worker 	line = strtok_r(copy, "\n", &next);
431*436bf2bcSAndroid Build Coastguard Worker 	while (line) {
432*436bf2bcSAndroid Build Coastguard Worker 		errno = 0;
433*436bf2bcSAndroid Build Coastguard Worker 		n = sscanf(line, "%d %m[^\n]s", &pid, &comm);
434*436bf2bcSAndroid Build Coastguard Worker 		if (errno || n != 2 || !comm)
435*436bf2bcSAndroid Build Coastguard Worker 			goto out;
436*436bf2bcSAndroid Build Coastguard Worker 		tep_register_comm(tep, comm, pid);
437*436bf2bcSAndroid Build Coastguard Worker 		free(comm);
438*436bf2bcSAndroid Build Coastguard Worker 		line = strtok_r(NULL, "\n", &next);
439*436bf2bcSAndroid Build Coastguard Worker 	}
440*436bf2bcSAndroid Build Coastguard Worker 	ret = 0;
441*436bf2bcSAndroid Build Coastguard Worker  out:
442*436bf2bcSAndroid Build Coastguard Worker 	free(copy);
443*436bf2bcSAndroid Build Coastguard Worker 	return ret;
444*436bf2bcSAndroid Build Coastguard Worker }
445*436bf2bcSAndroid Build Coastguard Worker 
446*436bf2bcSAndroid Build Coastguard Worker struct func_map {
447*436bf2bcSAndroid Build Coastguard Worker 	unsigned long long		addr;
448*436bf2bcSAndroid Build Coastguard Worker 	char				*func;
449*436bf2bcSAndroid Build Coastguard Worker 	char				*mod;
450*436bf2bcSAndroid Build Coastguard Worker };
451*436bf2bcSAndroid Build Coastguard Worker 
452*436bf2bcSAndroid Build Coastguard Worker struct func_list {
453*436bf2bcSAndroid Build Coastguard Worker 	struct func_list	*next;
454*436bf2bcSAndroid Build Coastguard Worker 	unsigned long long	addr;
455*436bf2bcSAndroid Build Coastguard Worker 	char			*func;
456*436bf2bcSAndroid Build Coastguard Worker 	char			*mod;
457*436bf2bcSAndroid Build Coastguard Worker };
458*436bf2bcSAndroid Build Coastguard Worker 
func_cmp(const void * a,const void * b)459*436bf2bcSAndroid Build Coastguard Worker static int func_cmp(const void *a, const void *b)
460*436bf2bcSAndroid Build Coastguard Worker {
461*436bf2bcSAndroid Build Coastguard Worker 	const struct func_map *fa = a;
462*436bf2bcSAndroid Build Coastguard Worker 	const struct func_map *fb = b;
463*436bf2bcSAndroid Build Coastguard Worker 
464*436bf2bcSAndroid Build Coastguard Worker 	if (fa->addr < fb->addr)
465*436bf2bcSAndroid Build Coastguard Worker 		return -1;
466*436bf2bcSAndroid Build Coastguard Worker 	if (fa->addr > fb->addr)
467*436bf2bcSAndroid Build Coastguard Worker 		return 1;
468*436bf2bcSAndroid Build Coastguard Worker 
469*436bf2bcSAndroid Build Coastguard Worker 	return 0;
470*436bf2bcSAndroid Build Coastguard Worker }
471*436bf2bcSAndroid Build Coastguard Worker 
472*436bf2bcSAndroid Build Coastguard Worker /*
473*436bf2bcSAndroid Build Coastguard Worker  * We are searching for a record in between, not an exact
474*436bf2bcSAndroid Build Coastguard Worker  * match.
475*436bf2bcSAndroid Build Coastguard Worker  */
func_bcmp(const void * a,const void * b)476*436bf2bcSAndroid Build Coastguard Worker static int func_bcmp(const void *a, const void *b)
477*436bf2bcSAndroid Build Coastguard Worker {
478*436bf2bcSAndroid Build Coastguard Worker 	const struct func_map *fa = a;
479*436bf2bcSAndroid Build Coastguard Worker 	const struct func_map *fb = b;
480*436bf2bcSAndroid Build Coastguard Worker 
481*436bf2bcSAndroid Build Coastguard Worker 	if ((fa->addr == fb->addr) ||
482*436bf2bcSAndroid Build Coastguard Worker 
483*436bf2bcSAndroid Build Coastguard Worker 	    (fa->addr > fb->addr &&
484*436bf2bcSAndroid Build Coastguard Worker 	     fa->addr < (fb+1)->addr))
485*436bf2bcSAndroid Build Coastguard Worker 		return 0;
486*436bf2bcSAndroid Build Coastguard Worker 
487*436bf2bcSAndroid Build Coastguard Worker 	if (fa->addr < fb->addr)
488*436bf2bcSAndroid Build Coastguard Worker 		return -1;
489*436bf2bcSAndroid Build Coastguard Worker 
490*436bf2bcSAndroid Build Coastguard Worker 	return 1;
491*436bf2bcSAndroid Build Coastguard Worker }
492*436bf2bcSAndroid Build Coastguard Worker 
func_map_init(struct tep_handle * tep)493*436bf2bcSAndroid Build Coastguard Worker static int func_map_init(struct tep_handle *tep)
494*436bf2bcSAndroid Build Coastguard Worker {
495*436bf2bcSAndroid Build Coastguard Worker 	struct func_list *funclist;
496*436bf2bcSAndroid Build Coastguard Worker 	struct func_list *item;
497*436bf2bcSAndroid Build Coastguard Worker 	struct func_map *func_map;
498*436bf2bcSAndroid Build Coastguard Worker 	int i;
499*436bf2bcSAndroid Build Coastguard Worker 
500*436bf2bcSAndroid Build Coastguard Worker 	func_map = malloc(sizeof(*func_map) * (tep->func_count + 1));
501*436bf2bcSAndroid Build Coastguard Worker 	if (!func_map)
502*436bf2bcSAndroid Build Coastguard Worker 		return -1;
503*436bf2bcSAndroid Build Coastguard Worker 
504*436bf2bcSAndroid Build Coastguard Worker 	funclist = tep->funclist;
505*436bf2bcSAndroid Build Coastguard Worker 
506*436bf2bcSAndroid Build Coastguard Worker 	i = 0;
507*436bf2bcSAndroid Build Coastguard Worker 	while (funclist) {
508*436bf2bcSAndroid Build Coastguard Worker 		func_map[i].func = funclist->func;
509*436bf2bcSAndroid Build Coastguard Worker 		func_map[i].addr = funclist->addr;
510*436bf2bcSAndroid Build Coastguard Worker 		func_map[i].mod = funclist->mod;
511*436bf2bcSAndroid Build Coastguard Worker 		i++;
512*436bf2bcSAndroid Build Coastguard Worker 		item = funclist;
513*436bf2bcSAndroid Build Coastguard Worker 		funclist = funclist->next;
514*436bf2bcSAndroid Build Coastguard Worker 		free(item);
515*436bf2bcSAndroid Build Coastguard Worker 	}
516*436bf2bcSAndroid Build Coastguard Worker 
517*436bf2bcSAndroid Build Coastguard Worker 	qsort(func_map, tep->func_count, sizeof(*func_map), func_cmp);
518*436bf2bcSAndroid Build Coastguard Worker 
519*436bf2bcSAndroid Build Coastguard Worker 	/*
520*436bf2bcSAndroid Build Coastguard Worker 	 * Add a special record at the end.
521*436bf2bcSAndroid Build Coastguard Worker 	 */
522*436bf2bcSAndroid Build Coastguard Worker 	func_map[tep->func_count].func = NULL;
523*436bf2bcSAndroid Build Coastguard Worker 	func_map[tep->func_count].addr = 0;
524*436bf2bcSAndroid Build Coastguard Worker 	func_map[tep->func_count].mod = NULL;
525*436bf2bcSAndroid Build Coastguard Worker 
526*436bf2bcSAndroid Build Coastguard Worker 	tep->func_map = func_map;
527*436bf2bcSAndroid Build Coastguard Worker 	tep->funclist = NULL;
528*436bf2bcSAndroid Build Coastguard Worker 
529*436bf2bcSAndroid Build Coastguard Worker 	return 0;
530*436bf2bcSAndroid Build Coastguard Worker }
531*436bf2bcSAndroid Build Coastguard Worker 
532*436bf2bcSAndroid Build Coastguard Worker static struct func_map *
__find_func(struct tep_handle * tep,unsigned long long addr)533*436bf2bcSAndroid Build Coastguard Worker __find_func(struct tep_handle *tep, unsigned long long addr)
534*436bf2bcSAndroid Build Coastguard Worker {
535*436bf2bcSAndroid Build Coastguard Worker 	struct func_map *func;
536*436bf2bcSAndroid Build Coastguard Worker 	struct func_map key;
537*436bf2bcSAndroid Build Coastguard Worker 
538*436bf2bcSAndroid Build Coastguard Worker 	if (!tep->func_map)
539*436bf2bcSAndroid Build Coastguard Worker 		func_map_init(tep);
540*436bf2bcSAndroid Build Coastguard Worker 
541*436bf2bcSAndroid Build Coastguard Worker 	key.addr = addr;
542*436bf2bcSAndroid Build Coastguard Worker 
543*436bf2bcSAndroid Build Coastguard Worker 	func = bsearch(&key, tep->func_map, tep->func_count,
544*436bf2bcSAndroid Build Coastguard Worker 		       sizeof(*tep->func_map), func_bcmp);
545*436bf2bcSAndroid Build Coastguard Worker 
546*436bf2bcSAndroid Build Coastguard Worker 	return func;
547*436bf2bcSAndroid Build Coastguard Worker }
548*436bf2bcSAndroid Build Coastguard Worker 
549*436bf2bcSAndroid Build Coastguard Worker struct func_resolver {
550*436bf2bcSAndroid Build Coastguard Worker 	tep_func_resolver_t	*func;
551*436bf2bcSAndroid Build Coastguard Worker 	void			*priv;
552*436bf2bcSAndroid Build Coastguard Worker 	struct func_map		map;
553*436bf2bcSAndroid Build Coastguard Worker };
554*436bf2bcSAndroid Build Coastguard Worker 
555*436bf2bcSAndroid Build Coastguard Worker /**
556*436bf2bcSAndroid Build Coastguard Worker  * tep_set_function_resolver - set an alternative function resolver
557*436bf2bcSAndroid Build Coastguard Worker  * @tep: a handle to the trace event parser context
558*436bf2bcSAndroid Build Coastguard Worker  * @resolver: function to be used
559*436bf2bcSAndroid Build Coastguard Worker  * @priv: resolver function private state.
560*436bf2bcSAndroid Build Coastguard Worker  *
561*436bf2bcSAndroid Build Coastguard Worker  * Some tools may have already a way to resolve kernel functions, allow them to
562*436bf2bcSAndroid Build Coastguard Worker  * keep using it instead of duplicating all the entries inside tep->funclist.
563*436bf2bcSAndroid Build Coastguard Worker  */
tep_set_function_resolver(struct tep_handle * tep,tep_func_resolver_t * func,void * priv)564*436bf2bcSAndroid Build Coastguard Worker int tep_set_function_resolver(struct tep_handle *tep,
565*436bf2bcSAndroid Build Coastguard Worker 			      tep_func_resolver_t *func, void *priv)
566*436bf2bcSAndroid Build Coastguard Worker {
567*436bf2bcSAndroid Build Coastguard Worker 	struct func_resolver *resolver = malloc(sizeof(*resolver));
568*436bf2bcSAndroid Build Coastguard Worker 
569*436bf2bcSAndroid Build Coastguard Worker 	if (resolver == NULL)
570*436bf2bcSAndroid Build Coastguard Worker 		return -1;
571*436bf2bcSAndroid Build Coastguard Worker 
572*436bf2bcSAndroid Build Coastguard Worker 	resolver->func = func;
573*436bf2bcSAndroid Build Coastguard Worker 	resolver->priv = priv;
574*436bf2bcSAndroid Build Coastguard Worker 
575*436bf2bcSAndroid Build Coastguard Worker 	free(tep->func_resolver);
576*436bf2bcSAndroid Build Coastguard Worker 	tep->func_resolver = resolver;
577*436bf2bcSAndroid Build Coastguard Worker 
578*436bf2bcSAndroid Build Coastguard Worker 	return 0;
579*436bf2bcSAndroid Build Coastguard Worker }
580*436bf2bcSAndroid Build Coastguard Worker 
581*436bf2bcSAndroid Build Coastguard Worker /**
582*436bf2bcSAndroid Build Coastguard Worker  * tep_reset_function_resolver - reset alternative function resolver
583*436bf2bcSAndroid Build Coastguard Worker  * @tep: a handle to the trace event parser context
584*436bf2bcSAndroid Build Coastguard Worker  *
585*436bf2bcSAndroid Build Coastguard Worker  * Stop using whatever alternative resolver was set, use the default
586*436bf2bcSAndroid Build Coastguard Worker  * one instead.
587*436bf2bcSAndroid Build Coastguard Worker  */
tep_reset_function_resolver(struct tep_handle * tep)588*436bf2bcSAndroid Build Coastguard Worker void tep_reset_function_resolver(struct tep_handle *tep)
589*436bf2bcSAndroid Build Coastguard Worker {
590*436bf2bcSAndroid Build Coastguard Worker 	free(tep->func_resolver);
591*436bf2bcSAndroid Build Coastguard Worker 	tep->func_resolver = NULL;
592*436bf2bcSAndroid Build Coastguard Worker }
593*436bf2bcSAndroid Build Coastguard Worker 
594*436bf2bcSAndroid Build Coastguard Worker static struct func_map *
find_func(struct tep_handle * tep,unsigned long long addr)595*436bf2bcSAndroid Build Coastguard Worker find_func(struct tep_handle *tep, unsigned long long addr)
596*436bf2bcSAndroid Build Coastguard Worker {
597*436bf2bcSAndroid Build Coastguard Worker 	struct func_map *map;
598*436bf2bcSAndroid Build Coastguard Worker 
599*436bf2bcSAndroid Build Coastguard Worker 	if (!tep->func_resolver)
600*436bf2bcSAndroid Build Coastguard Worker 		return __find_func(tep, addr);
601*436bf2bcSAndroid Build Coastguard Worker 
602*436bf2bcSAndroid Build Coastguard Worker 	map = &tep->func_resolver->map;
603*436bf2bcSAndroid Build Coastguard Worker 	map->mod  = NULL;
604*436bf2bcSAndroid Build Coastguard Worker 	map->addr = addr;
605*436bf2bcSAndroid Build Coastguard Worker 	map->func = tep->func_resolver->func(tep->func_resolver->priv,
606*436bf2bcSAndroid Build Coastguard Worker 					     &map->addr, &map->mod);
607*436bf2bcSAndroid Build Coastguard Worker 	if (map->func == NULL)
608*436bf2bcSAndroid Build Coastguard Worker 		return NULL;
609*436bf2bcSAndroid Build Coastguard Worker 
610*436bf2bcSAndroid Build Coastguard Worker 	return map;
611*436bf2bcSAndroid Build Coastguard Worker }
612*436bf2bcSAndroid Build Coastguard Worker 
613*436bf2bcSAndroid Build Coastguard Worker /**
614*436bf2bcSAndroid Build Coastguard Worker  * tep_find_function_info - find a function by a given address
615*436bf2bcSAndroid Build Coastguard Worker  * @tep: a handle to the trace event parser context
616*436bf2bcSAndroid Build Coastguard Worker  * @addr: the address to find the function with
617*436bf2bcSAndroid Build Coastguard Worker  * @name: Return the name of the function (if found)
618*436bf2bcSAndroid Build Coastguard Worker  * @start: Return the start of the function (if found)
619*436bf2bcSAndroid Build Coastguard Worker  * @size: Return the size of the function (if found)
620*436bf2bcSAndroid Build Coastguard Worker  *
621*436bf2bcSAndroid Build Coastguard Worker  * Returns 1 if found, and 0 if it is not.
622*436bf2bcSAndroid Build Coastguard Worker  *  If found then @name will point to the name of the function.
623*436bf2bcSAndroid Build Coastguard Worker  *                @start: will contain the starting address of the function.
624*436bf2bcSAndroid Build Coastguard Worker  *                @size: will contain the size of the function.
625*436bf2bcSAndroid Build Coastguard Worker  */
tep_find_function_info(struct tep_handle * tep,unsigned long long addr,const char ** name,unsigned long long * start,unsigned long * size)626*436bf2bcSAndroid Build Coastguard Worker int tep_find_function_info(struct tep_handle *tep, unsigned long long addr,
627*436bf2bcSAndroid Build Coastguard Worker 			   const char **name, unsigned long long *start,
628*436bf2bcSAndroid Build Coastguard Worker 			   unsigned long *size)
629*436bf2bcSAndroid Build Coastguard Worker {
630*436bf2bcSAndroid Build Coastguard Worker 	struct func_map *map;
631*436bf2bcSAndroid Build Coastguard Worker 
632*436bf2bcSAndroid Build Coastguard Worker 	map = find_func(tep, addr);
633*436bf2bcSAndroid Build Coastguard Worker 	if (!map)
634*436bf2bcSAndroid Build Coastguard Worker 		return 0;
635*436bf2bcSAndroid Build Coastguard Worker 
636*436bf2bcSAndroid Build Coastguard Worker 	if (name)
637*436bf2bcSAndroid Build Coastguard Worker 		*name = map->func;
638*436bf2bcSAndroid Build Coastguard Worker 	if (start)
639*436bf2bcSAndroid Build Coastguard Worker 		*start = map->addr;
640*436bf2bcSAndroid Build Coastguard Worker 	if (size) {
641*436bf2bcSAndroid Build Coastguard Worker 		if (!tep->func_resolver)
642*436bf2bcSAndroid Build Coastguard Worker 			*size = map[1].addr - map->addr;
643*436bf2bcSAndroid Build Coastguard Worker 		else
644*436bf2bcSAndroid Build Coastguard Worker 			*size = 0;
645*436bf2bcSAndroid Build Coastguard Worker 	}
646*436bf2bcSAndroid Build Coastguard Worker 
647*436bf2bcSAndroid Build Coastguard Worker 	return 1;
648*436bf2bcSAndroid Build Coastguard Worker }
649*436bf2bcSAndroid Build Coastguard Worker 
650*436bf2bcSAndroid Build Coastguard Worker /**
651*436bf2bcSAndroid Build Coastguard Worker  * tep_find_function - find a function by a given address
652*436bf2bcSAndroid Build Coastguard Worker  * @tep: a handle to the trace event parser context
653*436bf2bcSAndroid Build Coastguard Worker  * @addr: the address to find the function with
654*436bf2bcSAndroid Build Coastguard Worker  *
655*436bf2bcSAndroid Build Coastguard Worker  * Returns a pointer to the function stored that has the given
656*436bf2bcSAndroid Build Coastguard Worker  * address. Note, the address does not have to be exact, it
657*436bf2bcSAndroid Build Coastguard Worker  * will select the function that would contain the address.
658*436bf2bcSAndroid Build Coastguard Worker  */
tep_find_function(struct tep_handle * tep,unsigned long long addr)659*436bf2bcSAndroid Build Coastguard Worker const char *tep_find_function(struct tep_handle *tep, unsigned long long addr)
660*436bf2bcSAndroid Build Coastguard Worker {
661*436bf2bcSAndroid Build Coastguard Worker 	struct func_map *map;
662*436bf2bcSAndroid Build Coastguard Worker 
663*436bf2bcSAndroid Build Coastguard Worker 	map = find_func(tep, addr);
664*436bf2bcSAndroid Build Coastguard Worker 	if (!map)
665*436bf2bcSAndroid Build Coastguard Worker 		return NULL;
666*436bf2bcSAndroid Build Coastguard Worker 
667*436bf2bcSAndroid Build Coastguard Worker 	return map->func;
668*436bf2bcSAndroid Build Coastguard Worker }
669*436bf2bcSAndroid Build Coastguard Worker 
670*436bf2bcSAndroid Build Coastguard Worker /**
671*436bf2bcSAndroid Build Coastguard Worker  * tep_find_function_address - find a function address by a given address
672*436bf2bcSAndroid Build Coastguard Worker  * @tep: a handle to the trace event parser context
673*436bf2bcSAndroid Build Coastguard Worker  * @addr: the address to find the function with
674*436bf2bcSAndroid Build Coastguard Worker  *
675*436bf2bcSAndroid Build Coastguard Worker  * Returns the address the function starts at. This can be used in
676*436bf2bcSAndroid Build Coastguard Worker  * conjunction with tep_find_function to print both the function
677*436bf2bcSAndroid Build Coastguard Worker  * name and the function offset.
678*436bf2bcSAndroid Build Coastguard Worker  */
679*436bf2bcSAndroid Build Coastguard Worker unsigned long long
tep_find_function_address(struct tep_handle * tep,unsigned long long addr)680*436bf2bcSAndroid Build Coastguard Worker tep_find_function_address(struct tep_handle *tep, unsigned long long addr)
681*436bf2bcSAndroid Build Coastguard Worker {
682*436bf2bcSAndroid Build Coastguard Worker 	struct func_map *map;
683*436bf2bcSAndroid Build Coastguard Worker 
684*436bf2bcSAndroid Build Coastguard Worker 	map = find_func(tep, addr);
685*436bf2bcSAndroid Build Coastguard Worker 	if (!map)
686*436bf2bcSAndroid Build Coastguard Worker 		return 0;
687*436bf2bcSAndroid Build Coastguard Worker 
688*436bf2bcSAndroid Build Coastguard Worker 	return map->addr;
689*436bf2bcSAndroid Build Coastguard Worker }
690*436bf2bcSAndroid Build Coastguard Worker 
691*436bf2bcSAndroid Build Coastguard Worker /**
692*436bf2bcSAndroid Build Coastguard Worker  * tep_register_function - register a function with a given address
693*436bf2bcSAndroid Build Coastguard Worker  * @tep: a handle to the trace event parser context
694*436bf2bcSAndroid Build Coastguard Worker  * @function: the function name to register
695*436bf2bcSAndroid Build Coastguard Worker  * @addr: the address the function starts at
696*436bf2bcSAndroid Build Coastguard Worker  * @mod: the kernel module the function may be in (NULL for none)
697*436bf2bcSAndroid Build Coastguard Worker  *
698*436bf2bcSAndroid Build Coastguard Worker  * This registers a function name with an address and module.
699*436bf2bcSAndroid Build Coastguard Worker  * The @func passed in is duplicated.
700*436bf2bcSAndroid Build Coastguard Worker  */
tep_register_function(struct tep_handle * tep,char * func,unsigned long long addr,char * mod)701*436bf2bcSAndroid Build Coastguard Worker int tep_register_function(struct tep_handle *tep, char *func,
702*436bf2bcSAndroid Build Coastguard Worker 			  unsigned long long addr, char *mod)
703*436bf2bcSAndroid Build Coastguard Worker {
704*436bf2bcSAndroid Build Coastguard Worker 	struct func_list *item = malloc(sizeof(*item));
705*436bf2bcSAndroid Build Coastguard Worker 
706*436bf2bcSAndroid Build Coastguard Worker 	if (!item)
707*436bf2bcSAndroid Build Coastguard Worker 		return -1;
708*436bf2bcSAndroid Build Coastguard Worker 
709*436bf2bcSAndroid Build Coastguard Worker 	item->next = tep->funclist;
710*436bf2bcSAndroid Build Coastguard Worker 	item->func = strdup(func);
711*436bf2bcSAndroid Build Coastguard Worker 	if (!item->func)
712*436bf2bcSAndroid Build Coastguard Worker 		goto out_free;
713*436bf2bcSAndroid Build Coastguard Worker 
714*436bf2bcSAndroid Build Coastguard Worker 	if (mod) {
715*436bf2bcSAndroid Build Coastguard Worker 		item->mod = strdup(mod);
716*436bf2bcSAndroid Build Coastguard Worker 		if (!item->mod)
717*436bf2bcSAndroid Build Coastguard Worker 			goto out_free_func;
718*436bf2bcSAndroid Build Coastguard Worker 	} else
719*436bf2bcSAndroid Build Coastguard Worker 		item->mod = NULL;
720*436bf2bcSAndroid Build Coastguard Worker 	item->addr = addr;
721*436bf2bcSAndroid Build Coastguard Worker 
722*436bf2bcSAndroid Build Coastguard Worker 	tep->funclist = item;
723*436bf2bcSAndroid Build Coastguard Worker 	tep->func_count++;
724*436bf2bcSAndroid Build Coastguard Worker 
725*436bf2bcSAndroid Build Coastguard Worker 	return 0;
726*436bf2bcSAndroid Build Coastguard Worker 
727*436bf2bcSAndroid Build Coastguard Worker out_free_func:
728*436bf2bcSAndroid Build Coastguard Worker 	free(item->func);
729*436bf2bcSAndroid Build Coastguard Worker 	item->func = NULL;
730*436bf2bcSAndroid Build Coastguard Worker out_free:
731*436bf2bcSAndroid Build Coastguard Worker 	free(item);
732*436bf2bcSAndroid Build Coastguard Worker 	errno = ENOMEM;
733*436bf2bcSAndroid Build Coastguard Worker 	return -1;
734*436bf2bcSAndroid Build Coastguard Worker }
735*436bf2bcSAndroid Build Coastguard Worker 
736*436bf2bcSAndroid Build Coastguard Worker /**
737*436bf2bcSAndroid Build Coastguard Worker  * tep_parse_kallsyms - load functions from a read of /proc/kallsyms
738*436bf2bcSAndroid Build Coastguard Worker  * @tep: a handle to the trace event parser
739*436bf2bcSAndroid Build Coastguard Worker  * @kallsyms: A string buffer that holds the content of /proc/kallsyms and ends with '\0'
740*436bf2bcSAndroid Build Coastguard Worker  *
741*436bf2bcSAndroid Build Coastguard Worker  * This is a helper function to parse the Linux kernel /proc/kallsyms
742*436bf2bcSAndroid Build Coastguard Worker  * format (stored in a string buffer) and load the functions into
743*436bf2bcSAndroid Build Coastguard Worker  * the @tep handler such that function IP addresses can be mapped to
744*436bf2bcSAndroid Build Coastguard Worker  * their name when parsing events with %pS in the print format field.
745*436bf2bcSAndroid Build Coastguard Worker  *
746*436bf2bcSAndroid Build Coastguard Worker  * Returns 0 on success, and -1 on error.
747*436bf2bcSAndroid Build Coastguard Worker  */
tep_parse_kallsyms(struct tep_handle * tep,const char * kallsyms)748*436bf2bcSAndroid Build Coastguard Worker int tep_parse_kallsyms(struct tep_handle *tep, const char *kallsyms)
749*436bf2bcSAndroid Build Coastguard Worker {
750*436bf2bcSAndroid Build Coastguard Worker 	unsigned long long addr;
751*436bf2bcSAndroid Build Coastguard Worker 	char *copy;
752*436bf2bcSAndroid Build Coastguard Worker 	char *func;
753*436bf2bcSAndroid Build Coastguard Worker 	char *line;
754*436bf2bcSAndroid Build Coastguard Worker 	char *next = NULL;
755*436bf2bcSAndroid Build Coastguard Worker 	char *mod;
756*436bf2bcSAndroid Build Coastguard Worker 	char ch;
757*436bf2bcSAndroid Build Coastguard Worker 	int ret = -1;
758*436bf2bcSAndroid Build Coastguard Worker 
759*436bf2bcSAndroid Build Coastguard Worker 	copy = strdup(kallsyms);
760*436bf2bcSAndroid Build Coastguard Worker 	if (!copy)
761*436bf2bcSAndroid Build Coastguard Worker 		return -1;
762*436bf2bcSAndroid Build Coastguard Worker 
763*436bf2bcSAndroid Build Coastguard Worker 	line = strtok_r(copy, "\n", &next);
764*436bf2bcSAndroid Build Coastguard Worker 	while (line) {
765*436bf2bcSAndroid Build Coastguard Worker 		int func_start, func_end = 0;
766*436bf2bcSAndroid Build Coastguard Worker 		int mod_start, mod_end = 0;
767*436bf2bcSAndroid Build Coastguard Worker 		int n;
768*436bf2bcSAndroid Build Coastguard Worker 
769*436bf2bcSAndroid Build Coastguard Worker 		mod = NULL;
770*436bf2bcSAndroid Build Coastguard Worker 		errno = 0;
771*436bf2bcSAndroid Build Coastguard Worker 		n = sscanf(line, "%16llx %c %n%*s%n%*1[\t][%n%*s%n",
772*436bf2bcSAndroid Build Coastguard Worker 			   &addr, &ch, &func_start, &func_end, &mod_start, &mod_end);
773*436bf2bcSAndroid Build Coastguard Worker 		if (errno)
774*436bf2bcSAndroid Build Coastguard Worker 			goto out;
775*436bf2bcSAndroid Build Coastguard Worker 
776*436bf2bcSAndroid Build Coastguard Worker 		if (n != 2 || !func_end) {
777*436bf2bcSAndroid Build Coastguard Worker 			tep_warning("Failed to parse kallsyms n=%d func_end=%d",
778*436bf2bcSAndroid Build Coastguard Worker 				    n, func_end);
779*436bf2bcSAndroid Build Coastguard Worker 			goto out;
780*436bf2bcSAndroid Build Coastguard Worker 		}
781*436bf2bcSAndroid Build Coastguard Worker 
782*436bf2bcSAndroid Build Coastguard Worker 		func = line + func_start;
783*436bf2bcSAndroid Build Coastguard Worker 		/*
784*436bf2bcSAndroid Build Coastguard Worker 		 * Hacks for
785*436bf2bcSAndroid Build Coastguard Worker 		 *  - arm arch that adds a lot of bogus '$a' functions
786*436bf2bcSAndroid Build Coastguard Worker 		 *  - x86-64 that reports per-cpu variable offsets as absolute
787*436bf2bcSAndroid Build Coastguard Worker 		 */
788*436bf2bcSAndroid Build Coastguard Worker 		if (func[0] != '$' && ch != 'A' && ch != 'a') {
789*436bf2bcSAndroid Build Coastguard Worker 			line[func_end] = 0;
790*436bf2bcSAndroid Build Coastguard Worker 			if (mod_end) {
791*436bf2bcSAndroid Build Coastguard Worker 				mod = line + mod_start;
792*436bf2bcSAndroid Build Coastguard Worker 				/* truncate the extra ']' */
793*436bf2bcSAndroid Build Coastguard Worker 				line[mod_end - 1] = 0;
794*436bf2bcSAndroid Build Coastguard Worker 			}
795*436bf2bcSAndroid Build Coastguard Worker 			tep_register_function(tep, func, addr, mod);
796*436bf2bcSAndroid Build Coastguard Worker 		}
797*436bf2bcSAndroid Build Coastguard Worker 
798*436bf2bcSAndroid Build Coastguard Worker 		line = strtok_r(NULL, "\n", &next);
799*436bf2bcSAndroid Build Coastguard Worker 	}
800*436bf2bcSAndroid Build Coastguard Worker 	free(line);
801*436bf2bcSAndroid Build Coastguard Worker 	ret = 0;
802*436bf2bcSAndroid Build Coastguard Worker  out:
803*436bf2bcSAndroid Build Coastguard Worker 	free(copy);
804*436bf2bcSAndroid Build Coastguard Worker 
805*436bf2bcSAndroid Build Coastguard Worker 	return ret;
806*436bf2bcSAndroid Build Coastguard Worker }
807*436bf2bcSAndroid Build Coastguard Worker 
808*436bf2bcSAndroid Build Coastguard Worker /**
809*436bf2bcSAndroid Build Coastguard Worker  * tep_print_funcs - print out the stored functions
810*436bf2bcSAndroid Build Coastguard Worker  * @tep: a handle to the trace event parser context
811*436bf2bcSAndroid Build Coastguard Worker  *
812*436bf2bcSAndroid Build Coastguard Worker  * This prints out the stored functions.
813*436bf2bcSAndroid Build Coastguard Worker  */
tep_print_funcs(struct tep_handle * tep)814*436bf2bcSAndroid Build Coastguard Worker void tep_print_funcs(struct tep_handle *tep)
815*436bf2bcSAndroid Build Coastguard Worker {
816*436bf2bcSAndroid Build Coastguard Worker 	int i;
817*436bf2bcSAndroid Build Coastguard Worker 
818*436bf2bcSAndroid Build Coastguard Worker 	if (!tep->func_map)
819*436bf2bcSAndroid Build Coastguard Worker 		func_map_init(tep);
820*436bf2bcSAndroid Build Coastguard Worker 
821*436bf2bcSAndroid Build Coastguard Worker 	for (i = 0; i < (int)tep->func_count; i++) {
822*436bf2bcSAndroid Build Coastguard Worker 		printf("%016llx %s",
823*436bf2bcSAndroid Build Coastguard Worker 		       tep->func_map[i].addr,
824*436bf2bcSAndroid Build Coastguard Worker 		       tep->func_map[i].func);
825*436bf2bcSAndroid Build Coastguard Worker 		if (tep->func_map[i].mod)
826*436bf2bcSAndroid Build Coastguard Worker 			printf(" [%s]\n", tep->func_map[i].mod);
827*436bf2bcSAndroid Build Coastguard Worker 		else
828*436bf2bcSAndroid Build Coastguard Worker 			printf("\n");
829*436bf2bcSAndroid Build Coastguard Worker 	}
830*436bf2bcSAndroid Build Coastguard Worker }
831*436bf2bcSAndroid Build Coastguard Worker 
832*436bf2bcSAndroid Build Coastguard Worker struct printk_map {
833*436bf2bcSAndroid Build Coastguard Worker 	unsigned long long		addr;
834*436bf2bcSAndroid Build Coastguard Worker 	char				*printk;
835*436bf2bcSAndroid Build Coastguard Worker };
836*436bf2bcSAndroid Build Coastguard Worker 
837*436bf2bcSAndroid Build Coastguard Worker struct printk_list {
838*436bf2bcSAndroid Build Coastguard Worker 	struct printk_list	*next;
839*436bf2bcSAndroid Build Coastguard Worker 	unsigned long long	addr;
840*436bf2bcSAndroid Build Coastguard Worker 	char			*printk;
841*436bf2bcSAndroid Build Coastguard Worker };
842*436bf2bcSAndroid Build Coastguard Worker 
printk_cmp(const void * a,const void * b)843*436bf2bcSAndroid Build Coastguard Worker static int printk_cmp(const void *a, const void *b)
844*436bf2bcSAndroid Build Coastguard Worker {
845*436bf2bcSAndroid Build Coastguard Worker 	const struct printk_map *pa = a;
846*436bf2bcSAndroid Build Coastguard Worker 	const struct printk_map *pb = b;
847*436bf2bcSAndroid Build Coastguard Worker 
848*436bf2bcSAndroid Build Coastguard Worker 	if (pa->addr < pb->addr)
849*436bf2bcSAndroid Build Coastguard Worker 		return -1;
850*436bf2bcSAndroid Build Coastguard Worker 	if (pa->addr > pb->addr)
851*436bf2bcSAndroid Build Coastguard Worker 		return 1;
852*436bf2bcSAndroid Build Coastguard Worker 
853*436bf2bcSAndroid Build Coastguard Worker 	return 0;
854*436bf2bcSAndroid Build Coastguard Worker }
855*436bf2bcSAndroid Build Coastguard Worker 
printk_map_init(struct tep_handle * tep)856*436bf2bcSAndroid Build Coastguard Worker static int printk_map_init(struct tep_handle *tep)
857*436bf2bcSAndroid Build Coastguard Worker {
858*436bf2bcSAndroid Build Coastguard Worker 	struct printk_list *printklist;
859*436bf2bcSAndroid Build Coastguard Worker 	struct printk_list *item;
860*436bf2bcSAndroid Build Coastguard Worker 	struct printk_map *printk_map;
861*436bf2bcSAndroid Build Coastguard Worker 	int i;
862*436bf2bcSAndroid Build Coastguard Worker 
863*436bf2bcSAndroid Build Coastguard Worker 	printk_map = malloc(sizeof(*printk_map) * (tep->printk_count + 1));
864*436bf2bcSAndroid Build Coastguard Worker 	if (!printk_map)
865*436bf2bcSAndroid Build Coastguard Worker 		return -1;
866*436bf2bcSAndroid Build Coastguard Worker 
867*436bf2bcSAndroid Build Coastguard Worker 	printklist = tep->printklist;
868*436bf2bcSAndroid Build Coastguard Worker 
869*436bf2bcSAndroid Build Coastguard Worker 	i = 0;
870*436bf2bcSAndroid Build Coastguard Worker 	while (printklist) {
871*436bf2bcSAndroid Build Coastguard Worker 		printk_map[i].printk = printklist->printk;
872*436bf2bcSAndroid Build Coastguard Worker 		printk_map[i].addr = printklist->addr;
873*436bf2bcSAndroid Build Coastguard Worker 		i++;
874*436bf2bcSAndroid Build Coastguard Worker 		item = printklist;
875*436bf2bcSAndroid Build Coastguard Worker 		printklist = printklist->next;
876*436bf2bcSAndroid Build Coastguard Worker 		free(item);
877*436bf2bcSAndroid Build Coastguard Worker 	}
878*436bf2bcSAndroid Build Coastguard Worker 
879*436bf2bcSAndroid Build Coastguard Worker 	qsort(printk_map, tep->printk_count, sizeof(*printk_map), printk_cmp);
880*436bf2bcSAndroid Build Coastguard Worker 
881*436bf2bcSAndroid Build Coastguard Worker 	tep->printk_map = printk_map;
882*436bf2bcSAndroid Build Coastguard Worker 	tep->printklist = NULL;
883*436bf2bcSAndroid Build Coastguard Worker 
884*436bf2bcSAndroid Build Coastguard Worker 	return 0;
885*436bf2bcSAndroid Build Coastguard Worker }
886*436bf2bcSAndroid Build Coastguard Worker 
887*436bf2bcSAndroid Build Coastguard Worker static struct printk_map *
find_printk(struct tep_handle * tep,unsigned long long addr)888*436bf2bcSAndroid Build Coastguard Worker find_printk(struct tep_handle *tep, unsigned long long addr)
889*436bf2bcSAndroid Build Coastguard Worker {
890*436bf2bcSAndroid Build Coastguard Worker 	struct printk_map *printk;
891*436bf2bcSAndroid Build Coastguard Worker 	struct printk_map key;
892*436bf2bcSAndroid Build Coastguard Worker 
893*436bf2bcSAndroid Build Coastguard Worker 	if (!tep->printk_map && printk_map_init(tep))
894*436bf2bcSAndroid Build Coastguard Worker 		return NULL;
895*436bf2bcSAndroid Build Coastguard Worker 
896*436bf2bcSAndroid Build Coastguard Worker 	key.addr = addr;
897*436bf2bcSAndroid Build Coastguard Worker 
898*436bf2bcSAndroid Build Coastguard Worker 	printk = bsearch(&key, tep->printk_map, tep->printk_count,
899*436bf2bcSAndroid Build Coastguard Worker 			 sizeof(*tep->printk_map), printk_cmp);
900*436bf2bcSAndroid Build Coastguard Worker 
901*436bf2bcSAndroid Build Coastguard Worker 	return printk;
902*436bf2bcSAndroid Build Coastguard Worker }
903*436bf2bcSAndroid Build Coastguard Worker 
904*436bf2bcSAndroid Build Coastguard Worker /**
905*436bf2bcSAndroid Build Coastguard Worker  * tep_register_print_string - register a string by its address
906*436bf2bcSAndroid Build Coastguard Worker  * @tep: a handle to the trace event parser context
907*436bf2bcSAndroid Build Coastguard Worker  * @fmt: the string format to register
908*436bf2bcSAndroid Build Coastguard Worker  * @addr: the address the string was located at
909*436bf2bcSAndroid Build Coastguard Worker  *
910*436bf2bcSAndroid Build Coastguard Worker  * This registers a string by the address it was stored in the kernel.
911*436bf2bcSAndroid Build Coastguard Worker  * The @fmt passed in is duplicated.
912*436bf2bcSAndroid Build Coastguard Worker  */
tep_register_print_string(struct tep_handle * tep,const char * fmt,unsigned long long addr)913*436bf2bcSAndroid Build Coastguard Worker int tep_register_print_string(struct tep_handle *tep, const char *fmt,
914*436bf2bcSAndroid Build Coastguard Worker 			      unsigned long long addr)
915*436bf2bcSAndroid Build Coastguard Worker {
916*436bf2bcSAndroid Build Coastguard Worker 	struct printk_list *item = malloc(sizeof(*item));
917*436bf2bcSAndroid Build Coastguard Worker 	char *p;
918*436bf2bcSAndroid Build Coastguard Worker 
919*436bf2bcSAndroid Build Coastguard Worker 	if (!item)
920*436bf2bcSAndroid Build Coastguard Worker 		return -1;
921*436bf2bcSAndroid Build Coastguard Worker 
922*436bf2bcSAndroid Build Coastguard Worker 	item->next = tep->printklist;
923*436bf2bcSAndroid Build Coastguard Worker 	item->addr = addr;
924*436bf2bcSAndroid Build Coastguard Worker 
925*436bf2bcSAndroid Build Coastguard Worker 	/* Strip off quotes and '\n' from the end */
926*436bf2bcSAndroid Build Coastguard Worker 	if (fmt[0] == '"')
927*436bf2bcSAndroid Build Coastguard Worker 		fmt++;
928*436bf2bcSAndroid Build Coastguard Worker 	item->printk = strdup(fmt);
929*436bf2bcSAndroid Build Coastguard Worker 	if (!item->printk)
930*436bf2bcSAndroid Build Coastguard Worker 		goto out_free;
931*436bf2bcSAndroid Build Coastguard Worker 
932*436bf2bcSAndroid Build Coastguard Worker 	p = item->printk + strlen(item->printk) - 1;
933*436bf2bcSAndroid Build Coastguard Worker 	if (*p == '"')
934*436bf2bcSAndroid Build Coastguard Worker 		*p = 0;
935*436bf2bcSAndroid Build Coastguard Worker 
936*436bf2bcSAndroid Build Coastguard Worker 	p -= 2;
937*436bf2bcSAndroid Build Coastguard Worker 	if (strcmp(p, "\\n") == 0)
938*436bf2bcSAndroid Build Coastguard Worker 		*p = 0;
939*436bf2bcSAndroid Build Coastguard Worker 
940*436bf2bcSAndroid Build Coastguard Worker 	tep->printklist = item;
941*436bf2bcSAndroid Build Coastguard Worker 	tep->printk_count++;
942*436bf2bcSAndroid Build Coastguard Worker 
943*436bf2bcSAndroid Build Coastguard Worker 	return 0;
944*436bf2bcSAndroid Build Coastguard Worker 
945*436bf2bcSAndroid Build Coastguard Worker out_free:
946*436bf2bcSAndroid Build Coastguard Worker 	free(item);
947*436bf2bcSAndroid Build Coastguard Worker 	errno = ENOMEM;
948*436bf2bcSAndroid Build Coastguard Worker 	return -1;
949*436bf2bcSAndroid Build Coastguard Worker }
950*436bf2bcSAndroid Build Coastguard Worker 
951*436bf2bcSAndroid Build Coastguard Worker /**
952*436bf2bcSAndroid Build Coastguard Worker  * tep_print_printk - print out the stored strings
953*436bf2bcSAndroid Build Coastguard Worker  * @tep: a handle to the trace event parser context
954*436bf2bcSAndroid Build Coastguard Worker  *
955*436bf2bcSAndroid Build Coastguard Worker  * This prints the string formats that were stored.
956*436bf2bcSAndroid Build Coastguard Worker  */
tep_print_printk(struct tep_handle * tep)957*436bf2bcSAndroid Build Coastguard Worker void tep_print_printk(struct tep_handle *tep)
958*436bf2bcSAndroid Build Coastguard Worker {
959*436bf2bcSAndroid Build Coastguard Worker 	int i;
960*436bf2bcSAndroid Build Coastguard Worker 
961*436bf2bcSAndroid Build Coastguard Worker 	if (!tep->printk_map)
962*436bf2bcSAndroid Build Coastguard Worker 		printk_map_init(tep);
963*436bf2bcSAndroid Build Coastguard Worker 
964*436bf2bcSAndroid Build Coastguard Worker 	for (i = 0; i < (int)tep->printk_count; i++) {
965*436bf2bcSAndroid Build Coastguard Worker 		printf("%016llx %s\n",
966*436bf2bcSAndroid Build Coastguard Worker 		       tep->printk_map[i].addr,
967*436bf2bcSAndroid Build Coastguard Worker 		       tep->printk_map[i].printk);
968*436bf2bcSAndroid Build Coastguard Worker 	}
969*436bf2bcSAndroid Build Coastguard Worker }
970*436bf2bcSAndroid Build Coastguard Worker 
971*436bf2bcSAndroid Build Coastguard Worker /**
972*436bf2bcSAndroid Build Coastguard Worker  * tep_parse_printk_formats - Parse the address to strings
973*436bf2bcSAndroid Build Coastguard Worker  * @tep: a handle to the trace event parser
974*436bf2bcSAndroid Build Coastguard Worker  * @buf: A string buffer that holds the content of printk_formats and ends with '\0'
975*436bf2bcSAndroid Build Coastguard Worker  *
976*436bf2bcSAndroid Build Coastguard Worker  * This is a helper function to parse the address to printk formats in
977*436bf2bcSAndroid Build Coastguard Worker  * the kernel. Some events use %s to a kernel address that holds a constant
978*436bf2bcSAndroid Build Coastguard Worker  * string. The printk_formats file has a mapping of these addresses to the
979*436bf2bcSAndroid Build Coastguard Worker  * strings that are in the kernel. This parses the content of that file
980*436bf2bcSAndroid Build Coastguard Worker  * and registers those strings and their addresses so that the parsing of
981*436bf2bcSAndroid Build Coastguard Worker  * events can display the string as the event only has the address of the string.
982*436bf2bcSAndroid Build Coastguard Worker  *
983*436bf2bcSAndroid Build Coastguard Worker  * Returns 0 on success, and -1 on error.
984*436bf2bcSAndroid Build Coastguard Worker  */
tep_parse_printk_formats(struct tep_handle * tep,const char * buf)985*436bf2bcSAndroid Build Coastguard Worker int tep_parse_printk_formats(struct tep_handle *tep, const char *buf)
986*436bf2bcSAndroid Build Coastguard Worker {
987*436bf2bcSAndroid Build Coastguard Worker 	unsigned long long addr;
988*436bf2bcSAndroid Build Coastguard Worker 	char *addr_str;
989*436bf2bcSAndroid Build Coastguard Worker 	char *printk;
990*436bf2bcSAndroid Build Coastguard Worker 	char *copy;
991*436bf2bcSAndroid Build Coastguard Worker 	char *line;
992*436bf2bcSAndroid Build Coastguard Worker 	char *next;
993*436bf2bcSAndroid Build Coastguard Worker 	char *fmt;
994*436bf2bcSAndroid Build Coastguard Worker 	int ret = -1;
995*436bf2bcSAndroid Build Coastguard Worker 
996*436bf2bcSAndroid Build Coastguard Worker 	copy = strdup(buf);
997*436bf2bcSAndroid Build Coastguard Worker 	if (!copy)
998*436bf2bcSAndroid Build Coastguard Worker 		return -1;
999*436bf2bcSAndroid Build Coastguard Worker 
1000*436bf2bcSAndroid Build Coastguard Worker 	line = strtok_r(copy, "\n", &next);
1001*436bf2bcSAndroid Build Coastguard Worker 	while (line) {
1002*436bf2bcSAndroid Build Coastguard Worker 		addr_str = strtok_r(line, ":", &fmt);
1003*436bf2bcSAndroid Build Coastguard Worker 		if (!addr_str) {
1004*436bf2bcSAndroid Build Coastguard Worker 			tep_warning("printk format with empty entry");
1005*436bf2bcSAndroid Build Coastguard Worker 			break;
1006*436bf2bcSAndroid Build Coastguard Worker 		}
1007*436bf2bcSAndroid Build Coastguard Worker 		addr = strtoull(addr_str, NULL, 16);
1008*436bf2bcSAndroid Build Coastguard Worker 		/* fmt still has a space, skip it */
1009*436bf2bcSAndroid Build Coastguard Worker 		printk = strdup(fmt+1);
1010*436bf2bcSAndroid Build Coastguard Worker 		if (!printk)
1011*436bf2bcSAndroid Build Coastguard Worker 			goto out;
1012*436bf2bcSAndroid Build Coastguard Worker 		line = strtok_r(NULL, "\n", &next);
1013*436bf2bcSAndroid Build Coastguard Worker 		tep_register_print_string(tep, printk, addr);
1014*436bf2bcSAndroid Build Coastguard Worker 		free(printk);
1015*436bf2bcSAndroid Build Coastguard Worker 	}
1016*436bf2bcSAndroid Build Coastguard Worker 	ret = 0;
1017*436bf2bcSAndroid Build Coastguard Worker  out:
1018*436bf2bcSAndroid Build Coastguard Worker 	free(copy);
1019*436bf2bcSAndroid Build Coastguard Worker 	return ret;
1020*436bf2bcSAndroid Build Coastguard Worker }
1021*436bf2bcSAndroid Build Coastguard Worker 
alloc_event(void)1022*436bf2bcSAndroid Build Coastguard Worker static struct tep_event *alloc_event(void)
1023*436bf2bcSAndroid Build Coastguard Worker {
1024*436bf2bcSAndroid Build Coastguard Worker 	return calloc(1, sizeof(struct tep_event));
1025*436bf2bcSAndroid Build Coastguard Worker }
1026*436bf2bcSAndroid Build Coastguard Worker 
add_event(struct tep_handle * tep,struct tep_event * event)1027*436bf2bcSAndroid Build Coastguard Worker static int add_event(struct tep_handle *tep, struct tep_event *event)
1028*436bf2bcSAndroid Build Coastguard Worker {
1029*436bf2bcSAndroid Build Coastguard Worker 	int i;
1030*436bf2bcSAndroid Build Coastguard Worker 	struct tep_event **events = realloc(tep->events, sizeof(event) *
1031*436bf2bcSAndroid Build Coastguard Worker 					    (tep->nr_events + 1));
1032*436bf2bcSAndroid Build Coastguard Worker 	if (!events)
1033*436bf2bcSAndroid Build Coastguard Worker 		return -1;
1034*436bf2bcSAndroid Build Coastguard Worker 
1035*436bf2bcSAndroid Build Coastguard Worker 	tep->events = events;
1036*436bf2bcSAndroid Build Coastguard Worker 
1037*436bf2bcSAndroid Build Coastguard Worker 	for (i = 0; i < tep->nr_events; i++) {
1038*436bf2bcSAndroid Build Coastguard Worker 		if (tep->events[i]->id > event->id)
1039*436bf2bcSAndroid Build Coastguard Worker 			break;
1040*436bf2bcSAndroid Build Coastguard Worker 	}
1041*436bf2bcSAndroid Build Coastguard Worker 	if (i < tep->nr_events)
1042*436bf2bcSAndroid Build Coastguard Worker 		memmove(&tep->events[i + 1],
1043*436bf2bcSAndroid Build Coastguard Worker 			&tep->events[i],
1044*436bf2bcSAndroid Build Coastguard Worker 			sizeof(event) * (tep->nr_events - i));
1045*436bf2bcSAndroid Build Coastguard Worker 
1046*436bf2bcSAndroid Build Coastguard Worker 	tep->events[i] = event;
1047*436bf2bcSAndroid Build Coastguard Worker 	tep->nr_events++;
1048*436bf2bcSAndroid Build Coastguard Worker 
1049*436bf2bcSAndroid Build Coastguard Worker 	event->tep = tep;
1050*436bf2bcSAndroid Build Coastguard Worker 
1051*436bf2bcSAndroid Build Coastguard Worker 	return 0;
1052*436bf2bcSAndroid Build Coastguard Worker }
1053*436bf2bcSAndroid Build Coastguard Worker 
event_item_type(enum tep_event_type type)1054*436bf2bcSAndroid Build Coastguard Worker static int event_item_type(enum tep_event_type type)
1055*436bf2bcSAndroid Build Coastguard Worker {
1056*436bf2bcSAndroid Build Coastguard Worker 	switch (type) {
1057*436bf2bcSAndroid Build Coastguard Worker 	case TEP_EVENT_ITEM ... TEP_EVENT_SQUOTE:
1058*436bf2bcSAndroid Build Coastguard Worker 		return 1;
1059*436bf2bcSAndroid Build Coastguard Worker 	case TEP_EVENT_ERROR ... TEP_EVENT_DELIM:
1060*436bf2bcSAndroid Build Coastguard Worker 	default:
1061*436bf2bcSAndroid Build Coastguard Worker 		return 0;
1062*436bf2bcSAndroid Build Coastguard Worker 	}
1063*436bf2bcSAndroid Build Coastguard Worker }
1064*436bf2bcSAndroid Build Coastguard Worker 
free_flag_sym(struct tep_print_flag_sym * fsym)1065*436bf2bcSAndroid Build Coastguard Worker static void free_flag_sym(struct tep_print_flag_sym *fsym)
1066*436bf2bcSAndroid Build Coastguard Worker {
1067*436bf2bcSAndroid Build Coastguard Worker 	struct tep_print_flag_sym *next;
1068*436bf2bcSAndroid Build Coastguard Worker 
1069*436bf2bcSAndroid Build Coastguard Worker 	while (fsym) {
1070*436bf2bcSAndroid Build Coastguard Worker 		next = fsym->next;
1071*436bf2bcSAndroid Build Coastguard Worker 		free(fsym->value);
1072*436bf2bcSAndroid Build Coastguard Worker 		free(fsym->str);
1073*436bf2bcSAndroid Build Coastguard Worker 		free(fsym);
1074*436bf2bcSAndroid Build Coastguard Worker 		fsym = next;
1075*436bf2bcSAndroid Build Coastguard Worker 	}
1076*436bf2bcSAndroid Build Coastguard Worker }
1077*436bf2bcSAndroid Build Coastguard Worker 
free_arg(struct tep_print_arg * arg)1078*436bf2bcSAndroid Build Coastguard Worker static void free_arg(struct tep_print_arg *arg)
1079*436bf2bcSAndroid Build Coastguard Worker {
1080*436bf2bcSAndroid Build Coastguard Worker 	struct tep_print_arg *farg;
1081*436bf2bcSAndroid Build Coastguard Worker 
1082*436bf2bcSAndroid Build Coastguard Worker 	if (!arg)
1083*436bf2bcSAndroid Build Coastguard Worker 		return;
1084*436bf2bcSAndroid Build Coastguard Worker 
1085*436bf2bcSAndroid Build Coastguard Worker 	switch (arg->type) {
1086*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_ATOM:
1087*436bf2bcSAndroid Build Coastguard Worker 		free(arg->atom.atom);
1088*436bf2bcSAndroid Build Coastguard Worker 		break;
1089*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_FIELD:
1090*436bf2bcSAndroid Build Coastguard Worker 		free(arg->field.name);
1091*436bf2bcSAndroid Build Coastguard Worker 		break;
1092*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_FLAGS:
1093*436bf2bcSAndroid Build Coastguard Worker 		free_arg(arg->flags.field);
1094*436bf2bcSAndroid Build Coastguard Worker 		free(arg->flags.delim);
1095*436bf2bcSAndroid Build Coastguard Worker 		free_flag_sym(arg->flags.flags);
1096*436bf2bcSAndroid Build Coastguard Worker 		break;
1097*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_SYMBOL:
1098*436bf2bcSAndroid Build Coastguard Worker 		free_arg(arg->symbol.field);
1099*436bf2bcSAndroid Build Coastguard Worker 		free_flag_sym(arg->symbol.symbols);
1100*436bf2bcSAndroid Build Coastguard Worker 		break;
1101*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_HEX:
1102*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_HEX_STR:
1103*436bf2bcSAndroid Build Coastguard Worker 		free_arg(arg->hex.field);
1104*436bf2bcSAndroid Build Coastguard Worker 		free_arg(arg->hex.size);
1105*436bf2bcSAndroid Build Coastguard Worker 		break;
1106*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_INT_ARRAY:
1107*436bf2bcSAndroid Build Coastguard Worker 		free_arg(arg->int_array.field);
1108*436bf2bcSAndroid Build Coastguard Worker 		free_arg(arg->int_array.count);
1109*436bf2bcSAndroid Build Coastguard Worker 		free_arg(arg->int_array.el_size);
1110*436bf2bcSAndroid Build Coastguard Worker 		break;
1111*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_TYPE:
1112*436bf2bcSAndroid Build Coastguard Worker 		free(arg->typecast.type);
1113*436bf2bcSAndroid Build Coastguard Worker 		free_arg(arg->typecast.item);
1114*436bf2bcSAndroid Build Coastguard Worker 		break;
1115*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_STRING:
1116*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_BSTRING:
1117*436bf2bcSAndroid Build Coastguard Worker 		free(arg->string.string);
1118*436bf2bcSAndroid Build Coastguard Worker 		break;
1119*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_BITMASK:
1120*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_CPUMASK:
1121*436bf2bcSAndroid Build Coastguard Worker 		free(arg->bitmask.bitmask);
1122*436bf2bcSAndroid Build Coastguard Worker 		break;
1123*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_DYNAMIC_ARRAY:
1124*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_DYNAMIC_ARRAY_LEN:
1125*436bf2bcSAndroid Build Coastguard Worker 		free(arg->dynarray.index);
1126*436bf2bcSAndroid Build Coastguard Worker 		break;
1127*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_OP:
1128*436bf2bcSAndroid Build Coastguard Worker 		free(arg->op.op);
1129*436bf2bcSAndroid Build Coastguard Worker 		free_arg(arg->op.left);
1130*436bf2bcSAndroid Build Coastguard Worker 		free_arg(arg->op.right);
1131*436bf2bcSAndroid Build Coastguard Worker 		break;
1132*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_FUNC:
1133*436bf2bcSAndroid Build Coastguard Worker 		while (arg->func.args) {
1134*436bf2bcSAndroid Build Coastguard Worker 			farg = arg->func.args;
1135*436bf2bcSAndroid Build Coastguard Worker 			arg->func.args = farg->next;
1136*436bf2bcSAndroid Build Coastguard Worker 			free_arg(farg);
1137*436bf2bcSAndroid Build Coastguard Worker 		}
1138*436bf2bcSAndroid Build Coastguard Worker 		break;
1139*436bf2bcSAndroid Build Coastguard Worker 
1140*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_NULL:
1141*436bf2bcSAndroid Build Coastguard Worker 	default:
1142*436bf2bcSAndroid Build Coastguard Worker 		break;
1143*436bf2bcSAndroid Build Coastguard Worker 	}
1144*436bf2bcSAndroid Build Coastguard Worker 
1145*436bf2bcSAndroid Build Coastguard Worker 	free(arg);
1146*436bf2bcSAndroid Build Coastguard Worker }
1147*436bf2bcSAndroid Build Coastguard Worker 
get_type(int ch)1148*436bf2bcSAndroid Build Coastguard Worker static enum tep_event_type get_type(int ch)
1149*436bf2bcSAndroid Build Coastguard Worker {
1150*436bf2bcSAndroid Build Coastguard Worker 	if (ch == '\n')
1151*436bf2bcSAndroid Build Coastguard Worker 		return TEP_EVENT_NEWLINE;
1152*436bf2bcSAndroid Build Coastguard Worker 	if (isspace(ch))
1153*436bf2bcSAndroid Build Coastguard Worker 		return TEP_EVENT_SPACE;
1154*436bf2bcSAndroid Build Coastguard Worker 	if (isalnum(ch) || ch == '_')
1155*436bf2bcSAndroid Build Coastguard Worker 		return TEP_EVENT_ITEM;
1156*436bf2bcSAndroid Build Coastguard Worker 	if (ch == '\'')
1157*436bf2bcSAndroid Build Coastguard Worker 		return TEP_EVENT_SQUOTE;
1158*436bf2bcSAndroid Build Coastguard Worker 	if (ch == '"')
1159*436bf2bcSAndroid Build Coastguard Worker 		return TEP_EVENT_DQUOTE;
1160*436bf2bcSAndroid Build Coastguard Worker 	if (!isprint(ch))
1161*436bf2bcSAndroid Build Coastguard Worker 		return TEP_EVENT_NONE;
1162*436bf2bcSAndroid Build Coastguard Worker 	if (ch == '(' || ch == ')' || ch == ',')
1163*436bf2bcSAndroid Build Coastguard Worker 		return TEP_EVENT_DELIM;
1164*436bf2bcSAndroid Build Coastguard Worker 
1165*436bf2bcSAndroid Build Coastguard Worker 	return TEP_EVENT_OP;
1166*436bf2bcSAndroid Build Coastguard Worker }
1167*436bf2bcSAndroid Build Coastguard Worker 
__read_char(struct tep_handle * tep)1168*436bf2bcSAndroid Build Coastguard Worker static int __read_char(struct tep_handle *tep)
1169*436bf2bcSAndroid Build Coastguard Worker {
1170*436bf2bcSAndroid Build Coastguard Worker 	if (tep->input_buf_ptr >= tep->input_buf_siz)
1171*436bf2bcSAndroid Build Coastguard Worker 		return -1;
1172*436bf2bcSAndroid Build Coastguard Worker 
1173*436bf2bcSAndroid Build Coastguard Worker 	return tep->input_buf[tep->input_buf_ptr++];
1174*436bf2bcSAndroid Build Coastguard Worker }
1175*436bf2bcSAndroid Build Coastguard Worker 
1176*436bf2bcSAndroid Build Coastguard Worker /**
1177*436bf2bcSAndroid Build Coastguard Worker  * peek_char - peek at the next character that will be read
1178*436bf2bcSAndroid Build Coastguard Worker  *
1179*436bf2bcSAndroid Build Coastguard Worker  * Returns the next character read, or -1 if end of buffer.
1180*436bf2bcSAndroid Build Coastguard Worker  */
peek_char(struct tep_handle * tep)1181*436bf2bcSAndroid Build Coastguard Worker __hidden int peek_char(struct tep_handle *tep)
1182*436bf2bcSAndroid Build Coastguard Worker {
1183*436bf2bcSAndroid Build Coastguard Worker 	if (tep->input_buf_ptr >= tep->input_buf_siz)
1184*436bf2bcSAndroid Build Coastguard Worker 		return -1;
1185*436bf2bcSAndroid Build Coastguard Worker 
1186*436bf2bcSAndroid Build Coastguard Worker 	return tep->input_buf[tep->input_buf_ptr];
1187*436bf2bcSAndroid Build Coastguard Worker }
1188*436bf2bcSAndroid Build Coastguard Worker 
extend_token(char ** tok,char * buf,int size)1189*436bf2bcSAndroid Build Coastguard Worker static int extend_token(char **tok, char *buf, int size)
1190*436bf2bcSAndroid Build Coastguard Worker {
1191*436bf2bcSAndroid Build Coastguard Worker 	char *newtok = realloc(*tok, size);
1192*436bf2bcSAndroid Build Coastguard Worker 
1193*436bf2bcSAndroid Build Coastguard Worker 	if (!newtok) {
1194*436bf2bcSAndroid Build Coastguard Worker 		free(*tok);
1195*436bf2bcSAndroid Build Coastguard Worker 		*tok = NULL;
1196*436bf2bcSAndroid Build Coastguard Worker 		return -1;
1197*436bf2bcSAndroid Build Coastguard Worker 	}
1198*436bf2bcSAndroid Build Coastguard Worker 
1199*436bf2bcSAndroid Build Coastguard Worker 	if (!*tok)
1200*436bf2bcSAndroid Build Coastguard Worker 		strcpy(newtok, buf);
1201*436bf2bcSAndroid Build Coastguard Worker 	else
1202*436bf2bcSAndroid Build Coastguard Worker 		strcat(newtok, buf);
1203*436bf2bcSAndroid Build Coastguard Worker 	*tok = newtok;
1204*436bf2bcSAndroid Build Coastguard Worker 
1205*436bf2bcSAndroid Build Coastguard Worker 	return 0;
1206*436bf2bcSAndroid Build Coastguard Worker }
1207*436bf2bcSAndroid Build Coastguard Worker 
1208*436bf2bcSAndroid Build Coastguard Worker static enum tep_event_type force_token(struct tep_handle *tep, const char *str,
1209*436bf2bcSAndroid Build Coastguard Worker 		char **tok);
1210*436bf2bcSAndroid Build Coastguard Worker 
__read_token(struct tep_handle * tep,char ** tok)1211*436bf2bcSAndroid Build Coastguard Worker static enum tep_event_type __read_token(struct tep_handle *tep, char **tok)
1212*436bf2bcSAndroid Build Coastguard Worker {
1213*436bf2bcSAndroid Build Coastguard Worker 	char buf[BUFSIZ];
1214*436bf2bcSAndroid Build Coastguard Worker 	int ch, last_ch, quote_ch, next_ch;
1215*436bf2bcSAndroid Build Coastguard Worker 	int i = 0;
1216*436bf2bcSAndroid Build Coastguard Worker 	int tok_size = 0;
1217*436bf2bcSAndroid Build Coastguard Worker 	enum tep_event_type type;
1218*436bf2bcSAndroid Build Coastguard Worker 
1219*436bf2bcSAndroid Build Coastguard Worker 	*tok = NULL;
1220*436bf2bcSAndroid Build Coastguard Worker 
1221*436bf2bcSAndroid Build Coastguard Worker 
1222*436bf2bcSAndroid Build Coastguard Worker 	ch = __read_char(tep);
1223*436bf2bcSAndroid Build Coastguard Worker 	if (ch < 0)
1224*436bf2bcSAndroid Build Coastguard Worker 		return TEP_EVENT_NONE;
1225*436bf2bcSAndroid Build Coastguard Worker 
1226*436bf2bcSAndroid Build Coastguard Worker 	type = get_type(ch);
1227*436bf2bcSAndroid Build Coastguard Worker 	if (type == TEP_EVENT_NONE)
1228*436bf2bcSAndroid Build Coastguard Worker 		return type;
1229*436bf2bcSAndroid Build Coastguard Worker 
1230*436bf2bcSAndroid Build Coastguard Worker 	buf[i++] = ch;
1231*436bf2bcSAndroid Build Coastguard Worker 
1232*436bf2bcSAndroid Build Coastguard Worker 	switch (type) {
1233*436bf2bcSAndroid Build Coastguard Worker 	case TEP_EVENT_NEWLINE:
1234*436bf2bcSAndroid Build Coastguard Worker 	case TEP_EVENT_DELIM:
1235*436bf2bcSAndroid Build Coastguard Worker 		*tok = malloc(2);
1236*436bf2bcSAndroid Build Coastguard Worker 		if (!*tok)
1237*436bf2bcSAndroid Build Coastguard Worker 			return TEP_EVENT_ERROR;
1238*436bf2bcSAndroid Build Coastguard Worker 		(*tok)[0] = ch;
1239*436bf2bcSAndroid Build Coastguard Worker 		(*tok)[1] = '\0';
1240*436bf2bcSAndroid Build Coastguard Worker 		return type;
1241*436bf2bcSAndroid Build Coastguard Worker 
1242*436bf2bcSAndroid Build Coastguard Worker 	case TEP_EVENT_OP:
1243*436bf2bcSAndroid Build Coastguard Worker 		switch (ch) {
1244*436bf2bcSAndroid Build Coastguard Worker 		case '-':
1245*436bf2bcSAndroid Build Coastguard Worker 			next_ch = peek_char(tep);
1246*436bf2bcSAndroid Build Coastguard Worker 			if (next_ch == '>') {
1247*436bf2bcSAndroid Build Coastguard Worker 				buf[i++] = __read_char(tep);
1248*436bf2bcSAndroid Build Coastguard Worker 				break;
1249*436bf2bcSAndroid Build Coastguard Worker 			}
1250*436bf2bcSAndroid Build Coastguard Worker 			/* fall through */
1251*436bf2bcSAndroid Build Coastguard Worker 		case '+':
1252*436bf2bcSAndroid Build Coastguard Worker 		case '|':
1253*436bf2bcSAndroid Build Coastguard Worker 		case '&':
1254*436bf2bcSAndroid Build Coastguard Worker 		case '>':
1255*436bf2bcSAndroid Build Coastguard Worker 		case '<':
1256*436bf2bcSAndroid Build Coastguard Worker 			last_ch = ch;
1257*436bf2bcSAndroid Build Coastguard Worker 			ch = peek_char(tep);
1258*436bf2bcSAndroid Build Coastguard Worker 			if (ch != last_ch)
1259*436bf2bcSAndroid Build Coastguard Worker 				goto test_equal;
1260*436bf2bcSAndroid Build Coastguard Worker 			buf[i++] = __read_char(tep);
1261*436bf2bcSAndroid Build Coastguard Worker 			switch (last_ch) {
1262*436bf2bcSAndroid Build Coastguard Worker 			case '>':
1263*436bf2bcSAndroid Build Coastguard Worker 			case '<':
1264*436bf2bcSAndroid Build Coastguard Worker 				goto test_equal;
1265*436bf2bcSAndroid Build Coastguard Worker 			default:
1266*436bf2bcSAndroid Build Coastguard Worker 				break;
1267*436bf2bcSAndroid Build Coastguard Worker 			}
1268*436bf2bcSAndroid Build Coastguard Worker 			break;
1269*436bf2bcSAndroid Build Coastguard Worker 		case '!':
1270*436bf2bcSAndroid Build Coastguard Worker 		case '=':
1271*436bf2bcSAndroid Build Coastguard Worker 			goto test_equal;
1272*436bf2bcSAndroid Build Coastguard Worker 		default: /* what should we do instead? */
1273*436bf2bcSAndroid Build Coastguard Worker 			break;
1274*436bf2bcSAndroid Build Coastguard Worker 		}
1275*436bf2bcSAndroid Build Coastguard Worker 		buf[i] = 0;
1276*436bf2bcSAndroid Build Coastguard Worker 		*tok = strdup(buf);
1277*436bf2bcSAndroid Build Coastguard Worker 		return type;
1278*436bf2bcSAndroid Build Coastguard Worker 
1279*436bf2bcSAndroid Build Coastguard Worker  test_equal:
1280*436bf2bcSAndroid Build Coastguard Worker 		ch = peek_char(tep);
1281*436bf2bcSAndroid Build Coastguard Worker 		if (ch == '=')
1282*436bf2bcSAndroid Build Coastguard Worker 			buf[i++] = __read_char(tep);
1283*436bf2bcSAndroid Build Coastguard Worker 		goto out;
1284*436bf2bcSAndroid Build Coastguard Worker 
1285*436bf2bcSAndroid Build Coastguard Worker 	case TEP_EVENT_DQUOTE:
1286*436bf2bcSAndroid Build Coastguard Worker 	case TEP_EVENT_SQUOTE:
1287*436bf2bcSAndroid Build Coastguard Worker 		/* don't keep quotes */
1288*436bf2bcSAndroid Build Coastguard Worker 		i--;
1289*436bf2bcSAndroid Build Coastguard Worker 		quote_ch = ch;
1290*436bf2bcSAndroid Build Coastguard Worker 		last_ch = 0;
1291*436bf2bcSAndroid Build Coastguard Worker  concat:
1292*436bf2bcSAndroid Build Coastguard Worker 		do {
1293*436bf2bcSAndroid Build Coastguard Worker 			if (i == (BUFSIZ - 1)) {
1294*436bf2bcSAndroid Build Coastguard Worker 				buf[i] = 0;
1295*436bf2bcSAndroid Build Coastguard Worker 				tok_size += BUFSIZ;
1296*436bf2bcSAndroid Build Coastguard Worker 
1297*436bf2bcSAndroid Build Coastguard Worker 				if (extend_token(tok, buf, tok_size) < 0)
1298*436bf2bcSAndroid Build Coastguard Worker 					return TEP_EVENT_NONE;
1299*436bf2bcSAndroid Build Coastguard Worker 				i = 0;
1300*436bf2bcSAndroid Build Coastguard Worker 			}
1301*436bf2bcSAndroid Build Coastguard Worker 			last_ch = ch;
1302*436bf2bcSAndroid Build Coastguard Worker 			ch = __read_char(tep);
1303*436bf2bcSAndroid Build Coastguard Worker 			buf[i++] = ch;
1304*436bf2bcSAndroid Build Coastguard Worker 			/* the '\' '\' will cancel itself */
1305*436bf2bcSAndroid Build Coastguard Worker 			if (ch == '\\' && last_ch == '\\')
1306*436bf2bcSAndroid Build Coastguard Worker 				last_ch = 0;
1307*436bf2bcSAndroid Build Coastguard Worker 			/* Break out if the file is corrupted and giving non print chars */
1308*436bf2bcSAndroid Build Coastguard Worker 			if (ch <= 0)
1309*436bf2bcSAndroid Build Coastguard Worker 				break;
1310*436bf2bcSAndroid Build Coastguard Worker 		} while ((ch != quote_ch && isprint(ch)) || last_ch == '\\' || ch == '\n');
1311*436bf2bcSAndroid Build Coastguard Worker 		/* remove the last quote */
1312*436bf2bcSAndroid Build Coastguard Worker 		i--;
1313*436bf2bcSAndroid Build Coastguard Worker 
1314*436bf2bcSAndroid Build Coastguard Worker 		if (ch <= 0)
1315*436bf2bcSAndroid Build Coastguard Worker 			type = TEP_EVENT_NONE;
1316*436bf2bcSAndroid Build Coastguard Worker 
1317*436bf2bcSAndroid Build Coastguard Worker 		/*
1318*436bf2bcSAndroid Build Coastguard Worker 		 * For strings (double quotes) check the next token.
1319*436bf2bcSAndroid Build Coastguard Worker 		 * If it is another string, concatinate the two.
1320*436bf2bcSAndroid Build Coastguard Worker 		 */
1321*436bf2bcSAndroid Build Coastguard Worker 		if (type == TEP_EVENT_DQUOTE) {
1322*436bf2bcSAndroid Build Coastguard Worker 			unsigned long long save_input_buf_ptr = tep->input_buf_ptr;
1323*436bf2bcSAndroid Build Coastguard Worker 
1324*436bf2bcSAndroid Build Coastguard Worker 			do {
1325*436bf2bcSAndroid Build Coastguard Worker 				ch = __read_char(tep);
1326*436bf2bcSAndroid Build Coastguard Worker 			} while (isspace(ch));
1327*436bf2bcSAndroid Build Coastguard Worker 			if (ch == '"')
1328*436bf2bcSAndroid Build Coastguard Worker 				goto concat;
1329*436bf2bcSAndroid Build Coastguard Worker 			tep->input_buf_ptr = save_input_buf_ptr;
1330*436bf2bcSAndroid Build Coastguard Worker 		}
1331*436bf2bcSAndroid Build Coastguard Worker 
1332*436bf2bcSAndroid Build Coastguard Worker 		goto out;
1333*436bf2bcSAndroid Build Coastguard Worker 
1334*436bf2bcSAndroid Build Coastguard Worker 	case TEP_EVENT_ERROR ... TEP_EVENT_SPACE:
1335*436bf2bcSAndroid Build Coastguard Worker 	case TEP_EVENT_ITEM:
1336*436bf2bcSAndroid Build Coastguard Worker 	default:
1337*436bf2bcSAndroid Build Coastguard Worker 		break;
1338*436bf2bcSAndroid Build Coastguard Worker 	}
1339*436bf2bcSAndroid Build Coastguard Worker 
1340*436bf2bcSAndroid Build Coastguard Worker 	while (get_type(peek_char(tep)) == type) {
1341*436bf2bcSAndroid Build Coastguard Worker 		if (i == (BUFSIZ - 1)) {
1342*436bf2bcSAndroid Build Coastguard Worker 			buf[i] = 0;
1343*436bf2bcSAndroid Build Coastguard Worker 			tok_size += BUFSIZ;
1344*436bf2bcSAndroid Build Coastguard Worker 
1345*436bf2bcSAndroid Build Coastguard Worker 			if (extend_token(tok, buf, tok_size) < 0)
1346*436bf2bcSAndroid Build Coastguard Worker 				return TEP_EVENT_NONE;
1347*436bf2bcSAndroid Build Coastguard Worker 			i = 0;
1348*436bf2bcSAndroid Build Coastguard Worker 		}
1349*436bf2bcSAndroid Build Coastguard Worker 		ch = __read_char(tep);
1350*436bf2bcSAndroid Build Coastguard Worker 		buf[i++] = ch;
1351*436bf2bcSAndroid Build Coastguard Worker 	}
1352*436bf2bcSAndroid Build Coastguard Worker 
1353*436bf2bcSAndroid Build Coastguard Worker  out:
1354*436bf2bcSAndroid Build Coastguard Worker 	buf[i] = 0;
1355*436bf2bcSAndroid Build Coastguard Worker 	if (extend_token(tok, buf, tok_size + i + 1) < 0)
1356*436bf2bcSAndroid Build Coastguard Worker 		return TEP_EVENT_NONE;
1357*436bf2bcSAndroid Build Coastguard Worker 
1358*436bf2bcSAndroid Build Coastguard Worker 	if (type == TEP_EVENT_ITEM) {
1359*436bf2bcSAndroid Build Coastguard Worker 		/*
1360*436bf2bcSAndroid Build Coastguard Worker 		 * Older versions of the kernel has a bug that
1361*436bf2bcSAndroid Build Coastguard Worker 		 * creates invalid symbols and will break the mac80211
1362*436bf2bcSAndroid Build Coastguard Worker 		 * parsing. This is a work around to that bug.
1363*436bf2bcSAndroid Build Coastguard Worker 		 *
1364*436bf2bcSAndroid Build Coastguard Worker 		 * See Linux kernel commit:
1365*436bf2bcSAndroid Build Coastguard Worker 		 *  811cb50baf63461ce0bdb234927046131fc7fa8b
1366*436bf2bcSAndroid Build Coastguard Worker 		 */
1367*436bf2bcSAndroid Build Coastguard Worker 		if (strcmp(*tok, "LOCAL_PR_FMT") == 0) {
1368*436bf2bcSAndroid Build Coastguard Worker 			free(*tok);
1369*436bf2bcSAndroid Build Coastguard Worker 			*tok = NULL;
1370*436bf2bcSAndroid Build Coastguard Worker 			return force_token(tep, "\"%s\" ", tok);
1371*436bf2bcSAndroid Build Coastguard Worker 		} else if (strcmp(*tok, "STA_PR_FMT") == 0) {
1372*436bf2bcSAndroid Build Coastguard Worker 			free(*tok);
1373*436bf2bcSAndroid Build Coastguard Worker 			*tok = NULL;
1374*436bf2bcSAndroid Build Coastguard Worker 			return force_token(tep, "\" sta:%pM\" ", tok);
1375*436bf2bcSAndroid Build Coastguard Worker 		} else if (strcmp(*tok, "VIF_PR_FMT") == 0) {
1376*436bf2bcSAndroid Build Coastguard Worker 			free(*tok);
1377*436bf2bcSAndroid Build Coastguard Worker 			*tok = NULL;
1378*436bf2bcSAndroid Build Coastguard Worker 			return force_token(tep, "\" vif:%p(%d)\" ", tok);
1379*436bf2bcSAndroid Build Coastguard Worker 		}
1380*436bf2bcSAndroid Build Coastguard Worker 	}
1381*436bf2bcSAndroid Build Coastguard Worker 
1382*436bf2bcSAndroid Build Coastguard Worker 	return type;
1383*436bf2bcSAndroid Build Coastguard Worker }
1384*436bf2bcSAndroid Build Coastguard Worker 
force_token(struct tep_handle * tep,const char * str,char ** tok)1385*436bf2bcSAndroid Build Coastguard Worker static enum tep_event_type force_token(struct tep_handle *tep, const char *str,
1386*436bf2bcSAndroid Build Coastguard Worker 		char **tok)
1387*436bf2bcSAndroid Build Coastguard Worker {
1388*436bf2bcSAndroid Build Coastguard Worker 	const char *save_input_buf;
1389*436bf2bcSAndroid Build Coastguard Worker 	unsigned long long save_input_buf_ptr;
1390*436bf2bcSAndroid Build Coastguard Worker 	unsigned long long save_input_buf_siz;
1391*436bf2bcSAndroid Build Coastguard Worker 	enum tep_event_type type;
1392*436bf2bcSAndroid Build Coastguard Worker 
1393*436bf2bcSAndroid Build Coastguard Worker 	/* save off the current input pointers */
1394*436bf2bcSAndroid Build Coastguard Worker 	save_input_buf = tep->input_buf;
1395*436bf2bcSAndroid Build Coastguard Worker 	save_input_buf_ptr = tep->input_buf_ptr;
1396*436bf2bcSAndroid Build Coastguard Worker 	save_input_buf_siz = tep->input_buf_siz;
1397*436bf2bcSAndroid Build Coastguard Worker 
1398*436bf2bcSAndroid Build Coastguard Worker 	init_input_buf(tep, str, strlen(str));
1399*436bf2bcSAndroid Build Coastguard Worker 
1400*436bf2bcSAndroid Build Coastguard Worker 	type = __read_token(tep, tok);
1401*436bf2bcSAndroid Build Coastguard Worker 
1402*436bf2bcSAndroid Build Coastguard Worker 	/* reset back to original token */
1403*436bf2bcSAndroid Build Coastguard Worker 	tep->input_buf = save_input_buf;
1404*436bf2bcSAndroid Build Coastguard Worker 	tep->input_buf_ptr = save_input_buf_ptr;
1405*436bf2bcSAndroid Build Coastguard Worker 	tep->input_buf_siz = save_input_buf_siz;
1406*436bf2bcSAndroid Build Coastguard Worker 
1407*436bf2bcSAndroid Build Coastguard Worker 	return type;
1408*436bf2bcSAndroid Build Coastguard Worker }
1409*436bf2bcSAndroid Build Coastguard Worker 
1410*436bf2bcSAndroid Build Coastguard Worker /**
1411*436bf2bcSAndroid Build Coastguard Worker  * free_token - free a token returned by tep_read_token
1412*436bf2bcSAndroid Build Coastguard Worker  * @token: the token to free
1413*436bf2bcSAndroid Build Coastguard Worker  */
free_token(char * tok)1414*436bf2bcSAndroid Build Coastguard Worker __hidden void free_token(char *tok)
1415*436bf2bcSAndroid Build Coastguard Worker {
1416*436bf2bcSAndroid Build Coastguard Worker 	if (tok)
1417*436bf2bcSAndroid Build Coastguard Worker 		free(tok);
1418*436bf2bcSAndroid Build Coastguard Worker }
1419*436bf2bcSAndroid Build Coastguard Worker 
1420*436bf2bcSAndroid Build Coastguard Worker /**
1421*436bf2bcSAndroid Build Coastguard Worker  * read_token - access to utilities to use the tep parser
1422*436bf2bcSAndroid Build Coastguard Worker  * @tok: The token to return
1423*436bf2bcSAndroid Build Coastguard Worker  *
1424*436bf2bcSAndroid Build Coastguard Worker  * This will parse tokens from the string given by
1425*436bf2bcSAndroid Build Coastguard Worker  * tep_init_data().
1426*436bf2bcSAndroid Build Coastguard Worker  *
1427*436bf2bcSAndroid Build Coastguard Worker  * Returns the token type.
1428*436bf2bcSAndroid Build Coastguard Worker  */
read_token(struct tep_handle * tep,char ** tok)1429*436bf2bcSAndroid Build Coastguard Worker __hidden enum tep_event_type read_token(struct tep_handle *tep, char **tok)
1430*436bf2bcSAndroid Build Coastguard Worker {
1431*436bf2bcSAndroid Build Coastguard Worker 	enum tep_event_type type;
1432*436bf2bcSAndroid Build Coastguard Worker 
1433*436bf2bcSAndroid Build Coastguard Worker 	for (;;) {
1434*436bf2bcSAndroid Build Coastguard Worker 		type = __read_token(tep, tok);
1435*436bf2bcSAndroid Build Coastguard Worker 		if (type != TEP_EVENT_SPACE)
1436*436bf2bcSAndroid Build Coastguard Worker 			return type;
1437*436bf2bcSAndroid Build Coastguard Worker 
1438*436bf2bcSAndroid Build Coastguard Worker 		free_token(*tok);
1439*436bf2bcSAndroid Build Coastguard Worker 	}
1440*436bf2bcSAndroid Build Coastguard Worker 
1441*436bf2bcSAndroid Build Coastguard Worker 	/* not reached */
1442*436bf2bcSAndroid Build Coastguard Worker 	*tok = NULL;
1443*436bf2bcSAndroid Build Coastguard Worker 	return TEP_EVENT_NONE;
1444*436bf2bcSAndroid Build Coastguard Worker }
1445*436bf2bcSAndroid Build Coastguard Worker 
1446*436bf2bcSAndroid Build Coastguard Worker /* no newline */
read_token_item(struct tep_handle * tep,char ** tok)1447*436bf2bcSAndroid Build Coastguard Worker static enum tep_event_type read_token_item(struct tep_handle *tep, char **tok)
1448*436bf2bcSAndroid Build Coastguard Worker {
1449*436bf2bcSAndroid Build Coastguard Worker 	enum tep_event_type type;
1450*436bf2bcSAndroid Build Coastguard Worker 
1451*436bf2bcSAndroid Build Coastguard Worker 	for (;;) {
1452*436bf2bcSAndroid Build Coastguard Worker 		type = __read_token(tep, tok);
1453*436bf2bcSAndroid Build Coastguard Worker 		if (type != TEP_EVENT_SPACE && type != TEP_EVENT_NEWLINE)
1454*436bf2bcSAndroid Build Coastguard Worker 			return type;
1455*436bf2bcSAndroid Build Coastguard Worker 		free_token(*tok);
1456*436bf2bcSAndroid Build Coastguard Worker 		*tok = NULL;
1457*436bf2bcSAndroid Build Coastguard Worker 	}
1458*436bf2bcSAndroid Build Coastguard Worker 
1459*436bf2bcSAndroid Build Coastguard Worker 	/* not reached */
1460*436bf2bcSAndroid Build Coastguard Worker 	*tok = NULL;
1461*436bf2bcSAndroid Build Coastguard Worker 	return TEP_EVENT_NONE;
1462*436bf2bcSAndroid Build Coastguard Worker }
1463*436bf2bcSAndroid Build Coastguard Worker 
test_type(enum tep_event_type type,enum tep_event_type expect)1464*436bf2bcSAndroid Build Coastguard Worker static int test_type(enum tep_event_type type, enum tep_event_type expect)
1465*436bf2bcSAndroid Build Coastguard Worker {
1466*436bf2bcSAndroid Build Coastguard Worker 	if (type != expect) {
1467*436bf2bcSAndroid Build Coastguard Worker 		do_warning("Error: expected type %d (%s) but read %d (%s)",
1468*436bf2bcSAndroid Build Coastguard Worker 			   expect, get_event_type(expect),
1469*436bf2bcSAndroid Build Coastguard Worker 			   type, get_event_type(type));
1470*436bf2bcSAndroid Build Coastguard Worker 		return -1;
1471*436bf2bcSAndroid Build Coastguard Worker 	}
1472*436bf2bcSAndroid Build Coastguard Worker 	return 0;
1473*436bf2bcSAndroid Build Coastguard Worker }
1474*436bf2bcSAndroid Build Coastguard Worker 
test_type_token(enum tep_event_type type,const char * token,enum tep_event_type expect,const char * expect_tok)1475*436bf2bcSAndroid Build Coastguard Worker static int test_type_token(enum tep_event_type type, const char *token,
1476*436bf2bcSAndroid Build Coastguard Worker 		    enum tep_event_type expect, const char *expect_tok)
1477*436bf2bcSAndroid Build Coastguard Worker {
1478*436bf2bcSAndroid Build Coastguard Worker 	if (type != expect) {
1479*436bf2bcSAndroid Build Coastguard Worker 		do_warning("Error: expected type %d (%s) but read %d (%s)",
1480*436bf2bcSAndroid Build Coastguard Worker 			   expect, get_event_type(expect),
1481*436bf2bcSAndroid Build Coastguard Worker 			   type, get_event_type(type));
1482*436bf2bcSAndroid Build Coastguard Worker 		return -1;
1483*436bf2bcSAndroid Build Coastguard Worker 	}
1484*436bf2bcSAndroid Build Coastguard Worker 
1485*436bf2bcSAndroid Build Coastguard Worker 	if (strcmp(token, expect_tok) != 0) {
1486*436bf2bcSAndroid Build Coastguard Worker 		do_warning("Error: expected '%s' but read '%s'",
1487*436bf2bcSAndroid Build Coastguard Worker 		    expect_tok, token);
1488*436bf2bcSAndroid Build Coastguard Worker 		return -1;
1489*436bf2bcSAndroid Build Coastguard Worker 	}
1490*436bf2bcSAndroid Build Coastguard Worker 	return 0;
1491*436bf2bcSAndroid Build Coastguard Worker }
1492*436bf2bcSAndroid Build Coastguard Worker 
__read_expect_type(struct tep_handle * tep,enum tep_event_type expect,char ** tok,int newline_ok)1493*436bf2bcSAndroid Build Coastguard Worker static int __read_expect_type(struct tep_handle *tep, enum tep_event_type expect,
1494*436bf2bcSAndroid Build Coastguard Worker 		char **tok, int newline_ok)
1495*436bf2bcSAndroid Build Coastguard Worker {
1496*436bf2bcSAndroid Build Coastguard Worker 	enum tep_event_type type;
1497*436bf2bcSAndroid Build Coastguard Worker 
1498*436bf2bcSAndroid Build Coastguard Worker 	if (newline_ok)
1499*436bf2bcSAndroid Build Coastguard Worker 		type = read_token(tep, tok);
1500*436bf2bcSAndroid Build Coastguard Worker 	else
1501*436bf2bcSAndroid Build Coastguard Worker 		type = read_token_item(tep, tok);
1502*436bf2bcSAndroid Build Coastguard Worker 	return test_type(type, expect);
1503*436bf2bcSAndroid Build Coastguard Worker }
1504*436bf2bcSAndroid Build Coastguard Worker 
read_expect_type(struct tep_handle * tep,enum tep_event_type expect,char ** tok)1505*436bf2bcSAndroid Build Coastguard Worker static int read_expect_type(struct tep_handle *tep, enum tep_event_type expect,
1506*436bf2bcSAndroid Build Coastguard Worker 		char **tok)
1507*436bf2bcSAndroid Build Coastguard Worker {
1508*436bf2bcSAndroid Build Coastguard Worker 	return __read_expect_type(tep, expect, tok, 1);
1509*436bf2bcSAndroid Build Coastguard Worker }
1510*436bf2bcSAndroid Build Coastguard Worker 
__read_expected(struct tep_handle * tep,enum tep_event_type expect,const char * str,int newline_ok)1511*436bf2bcSAndroid Build Coastguard Worker static int __read_expected(struct tep_handle *tep, enum tep_event_type expect,
1512*436bf2bcSAndroid Build Coastguard Worker 		const char *str, int newline_ok)
1513*436bf2bcSAndroid Build Coastguard Worker {
1514*436bf2bcSAndroid Build Coastguard Worker 	enum tep_event_type type;
1515*436bf2bcSAndroid Build Coastguard Worker 	char *token;
1516*436bf2bcSAndroid Build Coastguard Worker 	int ret;
1517*436bf2bcSAndroid Build Coastguard Worker 
1518*436bf2bcSAndroid Build Coastguard Worker 	if (newline_ok)
1519*436bf2bcSAndroid Build Coastguard Worker 		type = read_token(tep, &token);
1520*436bf2bcSAndroid Build Coastguard Worker 	else
1521*436bf2bcSAndroid Build Coastguard Worker 		type = read_token_item(tep, &token);
1522*436bf2bcSAndroid Build Coastguard Worker 
1523*436bf2bcSAndroid Build Coastguard Worker 	ret = test_type_token(type, token, expect, str);
1524*436bf2bcSAndroid Build Coastguard Worker 
1525*436bf2bcSAndroid Build Coastguard Worker 	free_token(token);
1526*436bf2bcSAndroid Build Coastguard Worker 
1527*436bf2bcSAndroid Build Coastguard Worker 	return ret;
1528*436bf2bcSAndroid Build Coastguard Worker }
1529*436bf2bcSAndroid Build Coastguard Worker 
read_expected(struct tep_handle * tep,enum tep_event_type expect,const char * str)1530*436bf2bcSAndroid Build Coastguard Worker static int read_expected(struct tep_handle *tep, enum tep_event_type expect,
1531*436bf2bcSAndroid Build Coastguard Worker 		const char *str)
1532*436bf2bcSAndroid Build Coastguard Worker {
1533*436bf2bcSAndroid Build Coastguard Worker 	return __read_expected(tep, expect, str, 1);
1534*436bf2bcSAndroid Build Coastguard Worker }
1535*436bf2bcSAndroid Build Coastguard Worker 
read_expected_item(struct tep_handle * tep,enum tep_event_type expect,const char * str)1536*436bf2bcSAndroid Build Coastguard Worker static int read_expected_item(struct tep_handle *tep, enum tep_event_type expect,
1537*436bf2bcSAndroid Build Coastguard Worker 		const char *str)
1538*436bf2bcSAndroid Build Coastguard Worker {
1539*436bf2bcSAndroid Build Coastguard Worker 	return __read_expected(tep, expect, str, 0);
1540*436bf2bcSAndroid Build Coastguard Worker }
1541*436bf2bcSAndroid Build Coastguard Worker 
event_read_name(struct tep_handle * tep)1542*436bf2bcSAndroid Build Coastguard Worker static char *event_read_name(struct tep_handle *tep)
1543*436bf2bcSAndroid Build Coastguard Worker {
1544*436bf2bcSAndroid Build Coastguard Worker 	char *token;
1545*436bf2bcSAndroid Build Coastguard Worker 
1546*436bf2bcSAndroid Build Coastguard Worker 	if (read_expected(tep, TEP_EVENT_ITEM, "name") < 0)
1547*436bf2bcSAndroid Build Coastguard Worker 		return NULL;
1548*436bf2bcSAndroid Build Coastguard Worker 
1549*436bf2bcSAndroid Build Coastguard Worker 	if (read_expected(tep, TEP_EVENT_OP, ":") < 0)
1550*436bf2bcSAndroid Build Coastguard Worker 		return NULL;
1551*436bf2bcSAndroid Build Coastguard Worker 
1552*436bf2bcSAndroid Build Coastguard Worker 	if (read_expect_type(tep, TEP_EVENT_ITEM, &token) < 0)
1553*436bf2bcSAndroid Build Coastguard Worker 		goto fail;
1554*436bf2bcSAndroid Build Coastguard Worker 
1555*436bf2bcSAndroid Build Coastguard Worker 	return token;
1556*436bf2bcSAndroid Build Coastguard Worker 
1557*436bf2bcSAndroid Build Coastguard Worker  fail:
1558*436bf2bcSAndroid Build Coastguard Worker 	free_token(token);
1559*436bf2bcSAndroid Build Coastguard Worker 	return NULL;
1560*436bf2bcSAndroid Build Coastguard Worker }
1561*436bf2bcSAndroid Build Coastguard Worker 
event_read_id(struct tep_handle * tep)1562*436bf2bcSAndroid Build Coastguard Worker static int event_read_id(struct tep_handle *tep)
1563*436bf2bcSAndroid Build Coastguard Worker {
1564*436bf2bcSAndroid Build Coastguard Worker 	char *token;
1565*436bf2bcSAndroid Build Coastguard Worker 	int id;
1566*436bf2bcSAndroid Build Coastguard Worker 
1567*436bf2bcSAndroid Build Coastguard Worker 	if (read_expected_item(tep, TEP_EVENT_ITEM, "ID") < 0)
1568*436bf2bcSAndroid Build Coastguard Worker 		return -1;
1569*436bf2bcSAndroid Build Coastguard Worker 
1570*436bf2bcSAndroid Build Coastguard Worker 	if (read_expected(tep, TEP_EVENT_OP, ":") < 0)
1571*436bf2bcSAndroid Build Coastguard Worker 		return -1;
1572*436bf2bcSAndroid Build Coastguard Worker 
1573*436bf2bcSAndroid Build Coastguard Worker 	if (read_expect_type(tep, TEP_EVENT_ITEM, &token) < 0)
1574*436bf2bcSAndroid Build Coastguard Worker 		goto fail;
1575*436bf2bcSAndroid Build Coastguard Worker 
1576*436bf2bcSAndroid Build Coastguard Worker 	id = strtoul(token, NULL, 0);
1577*436bf2bcSAndroid Build Coastguard Worker 	free_token(token);
1578*436bf2bcSAndroid Build Coastguard Worker 	return id;
1579*436bf2bcSAndroid Build Coastguard Worker 
1580*436bf2bcSAndroid Build Coastguard Worker  fail:
1581*436bf2bcSAndroid Build Coastguard Worker 	free_token(token);
1582*436bf2bcSAndroid Build Coastguard Worker 	return -1;
1583*436bf2bcSAndroid Build Coastguard Worker }
1584*436bf2bcSAndroid Build Coastguard Worker 
field_is_string(struct tep_format_field * field)1585*436bf2bcSAndroid Build Coastguard Worker static int field_is_string(struct tep_format_field *field)
1586*436bf2bcSAndroid Build Coastguard Worker {
1587*436bf2bcSAndroid Build Coastguard Worker 	if ((field->flags & TEP_FIELD_IS_ARRAY) &&
1588*436bf2bcSAndroid Build Coastguard Worker 	    (strstr(field->type, "char") || strstr(field->type, "u8") ||
1589*436bf2bcSAndroid Build Coastguard Worker 	     strstr(field->type, "s8")))
1590*436bf2bcSAndroid Build Coastguard Worker 		return 1;
1591*436bf2bcSAndroid Build Coastguard Worker 
1592*436bf2bcSAndroid Build Coastguard Worker 	return 0;
1593*436bf2bcSAndroid Build Coastguard Worker }
1594*436bf2bcSAndroid Build Coastguard Worker 
field_is_dynamic(struct tep_format_field * field)1595*436bf2bcSAndroid Build Coastguard Worker static int field_is_dynamic(struct tep_format_field *field)
1596*436bf2bcSAndroid Build Coastguard Worker {
1597*436bf2bcSAndroid Build Coastguard Worker 	if (strncmp(field->type, "__data_loc", 10) == 0)
1598*436bf2bcSAndroid Build Coastguard Worker 		return 1;
1599*436bf2bcSAndroid Build Coastguard Worker 
1600*436bf2bcSAndroid Build Coastguard Worker 	return 0;
1601*436bf2bcSAndroid Build Coastguard Worker }
1602*436bf2bcSAndroid Build Coastguard Worker 
field_is_relative_dynamic(struct tep_format_field * field)1603*436bf2bcSAndroid Build Coastguard Worker static int field_is_relative_dynamic(struct tep_format_field *field)
1604*436bf2bcSAndroid Build Coastguard Worker {
1605*436bf2bcSAndroid Build Coastguard Worker 	if (strncmp(field->type, "__rel_loc", 9) == 0)
1606*436bf2bcSAndroid Build Coastguard Worker 		return 1;
1607*436bf2bcSAndroid Build Coastguard Worker 
1608*436bf2bcSAndroid Build Coastguard Worker 	return 0;
1609*436bf2bcSAndroid Build Coastguard Worker }
1610*436bf2bcSAndroid Build Coastguard Worker 
field_is_long(struct tep_format_field * field)1611*436bf2bcSAndroid Build Coastguard Worker static int field_is_long(struct tep_format_field *field)
1612*436bf2bcSAndroid Build Coastguard Worker {
1613*436bf2bcSAndroid Build Coastguard Worker 	/* includes long long */
1614*436bf2bcSAndroid Build Coastguard Worker 	if (strstr(field->type, "long"))
1615*436bf2bcSAndroid Build Coastguard Worker 		return 1;
1616*436bf2bcSAndroid Build Coastguard Worker 
1617*436bf2bcSAndroid Build Coastguard Worker 	return 0;
1618*436bf2bcSAndroid Build Coastguard Worker }
1619*436bf2bcSAndroid Build Coastguard Worker 
type_size(const char * name)1620*436bf2bcSAndroid Build Coastguard Worker static unsigned int type_size(const char *name)
1621*436bf2bcSAndroid Build Coastguard Worker {
1622*436bf2bcSAndroid Build Coastguard Worker 	/* This covers all TEP_FIELD_IS_STRING types. */
1623*436bf2bcSAndroid Build Coastguard Worker 	static struct {
1624*436bf2bcSAndroid Build Coastguard Worker 		const char *type;
1625*436bf2bcSAndroid Build Coastguard Worker 		unsigned int size;
1626*436bf2bcSAndroid Build Coastguard Worker 	} table[] = {
1627*436bf2bcSAndroid Build Coastguard Worker 		{ "u8",   1 },
1628*436bf2bcSAndroid Build Coastguard Worker 		{ "u16",  2 },
1629*436bf2bcSAndroid Build Coastguard Worker 		{ "u32",  4 },
1630*436bf2bcSAndroid Build Coastguard Worker 		{ "u64",  8 },
1631*436bf2bcSAndroid Build Coastguard Worker 		{ "s8",   1 },
1632*436bf2bcSAndroid Build Coastguard Worker 		{ "s16",  2 },
1633*436bf2bcSAndroid Build Coastguard Worker 		{ "s32",  4 },
1634*436bf2bcSAndroid Build Coastguard Worker 		{ "s64",  8 },
1635*436bf2bcSAndroid Build Coastguard Worker 		{ "char", 1 },
1636*436bf2bcSAndroid Build Coastguard Worker 		{ },
1637*436bf2bcSAndroid Build Coastguard Worker 	};
1638*436bf2bcSAndroid Build Coastguard Worker 	int i;
1639*436bf2bcSAndroid Build Coastguard Worker 
1640*436bf2bcSAndroid Build Coastguard Worker 	for (i = 0; table[i].type; i++) {
1641*436bf2bcSAndroid Build Coastguard Worker 		if (!strcmp(table[i].type, name))
1642*436bf2bcSAndroid Build Coastguard Worker 			return table[i].size;
1643*436bf2bcSAndroid Build Coastguard Worker 	}
1644*436bf2bcSAndroid Build Coastguard Worker 
1645*436bf2bcSAndroid Build Coastguard Worker 	return 0;
1646*436bf2bcSAndroid Build Coastguard Worker }
1647*436bf2bcSAndroid Build Coastguard Worker 
append(char ** buf,const char * delim,const char * str)1648*436bf2bcSAndroid Build Coastguard Worker static int append(char **buf, const char *delim, const char *str)
1649*436bf2bcSAndroid Build Coastguard Worker {
1650*436bf2bcSAndroid Build Coastguard Worker 	char *new_buf;
1651*436bf2bcSAndroid Build Coastguard Worker 
1652*436bf2bcSAndroid Build Coastguard Worker 	new_buf = realloc(*buf, strlen(*buf) + strlen(delim) + strlen(str) + 1);
1653*436bf2bcSAndroid Build Coastguard Worker 	if (!new_buf)
1654*436bf2bcSAndroid Build Coastguard Worker 		return -1;
1655*436bf2bcSAndroid Build Coastguard Worker 	strcat(new_buf, delim);
1656*436bf2bcSAndroid Build Coastguard Worker 	strcat(new_buf, str);
1657*436bf2bcSAndroid Build Coastguard Worker 	*buf = new_buf;
1658*436bf2bcSAndroid Build Coastguard Worker 	return 0;
1659*436bf2bcSAndroid Build Coastguard Worker }
1660*436bf2bcSAndroid Build Coastguard Worker 
event_read_fields(struct tep_handle * tep,struct tep_event * event,struct tep_format_field ** fields)1661*436bf2bcSAndroid Build Coastguard Worker static int event_read_fields(struct tep_handle *tep, struct tep_event *event,
1662*436bf2bcSAndroid Build Coastguard Worker 		struct tep_format_field **fields)
1663*436bf2bcSAndroid Build Coastguard Worker {
1664*436bf2bcSAndroid Build Coastguard Worker 	struct tep_format_field *field = NULL;
1665*436bf2bcSAndroid Build Coastguard Worker 	enum tep_event_type type;
1666*436bf2bcSAndroid Build Coastguard Worker 	char *token;
1667*436bf2bcSAndroid Build Coastguard Worker 	char *last_token;
1668*436bf2bcSAndroid Build Coastguard Worker 	char *delim = " ";
1669*436bf2bcSAndroid Build Coastguard Worker 	int count = 0;
1670*436bf2bcSAndroid Build Coastguard Worker 	int ret;
1671*436bf2bcSAndroid Build Coastguard Worker 
1672*436bf2bcSAndroid Build Coastguard Worker 	do {
1673*436bf2bcSAndroid Build Coastguard Worker 		unsigned int size_dynamic = 0;
1674*436bf2bcSAndroid Build Coastguard Worker 
1675*436bf2bcSAndroid Build Coastguard Worker 		type = read_token(tep, &token);
1676*436bf2bcSAndroid Build Coastguard Worker 		if (type == TEP_EVENT_NEWLINE) {
1677*436bf2bcSAndroid Build Coastguard Worker 			free_token(token);
1678*436bf2bcSAndroid Build Coastguard Worker 			return count;
1679*436bf2bcSAndroid Build Coastguard Worker 		}
1680*436bf2bcSAndroid Build Coastguard Worker 
1681*436bf2bcSAndroid Build Coastguard Worker 		count++;
1682*436bf2bcSAndroid Build Coastguard Worker 
1683*436bf2bcSAndroid Build Coastguard Worker 		if (test_type_token(type, token, TEP_EVENT_ITEM, "field"))
1684*436bf2bcSAndroid Build Coastguard Worker 			goto fail;
1685*436bf2bcSAndroid Build Coastguard Worker 		free_token(token);
1686*436bf2bcSAndroid Build Coastguard Worker 
1687*436bf2bcSAndroid Build Coastguard Worker 		type = read_token(tep, &token);
1688*436bf2bcSAndroid Build Coastguard Worker 		/*
1689*436bf2bcSAndroid Build Coastguard Worker 		 * The ftrace fields may still use the "special" name.
1690*436bf2bcSAndroid Build Coastguard Worker 		 * Just ignore it.
1691*436bf2bcSAndroid Build Coastguard Worker 		 */
1692*436bf2bcSAndroid Build Coastguard Worker 		if (event->flags & TEP_EVENT_FL_ISFTRACE &&
1693*436bf2bcSAndroid Build Coastguard Worker 		    type == TEP_EVENT_ITEM && strcmp(token, "special") == 0) {
1694*436bf2bcSAndroid Build Coastguard Worker 			free_token(token);
1695*436bf2bcSAndroid Build Coastguard Worker 			type = read_token(tep, &token);
1696*436bf2bcSAndroid Build Coastguard Worker 		}
1697*436bf2bcSAndroid Build Coastguard Worker 
1698*436bf2bcSAndroid Build Coastguard Worker 		if (test_type_token(type, token, TEP_EVENT_OP, ":") < 0)
1699*436bf2bcSAndroid Build Coastguard Worker 			goto fail;
1700*436bf2bcSAndroid Build Coastguard Worker 
1701*436bf2bcSAndroid Build Coastguard Worker 		free_token(token);
1702*436bf2bcSAndroid Build Coastguard Worker 		if (read_expect_type(tep, TEP_EVENT_ITEM, &token) < 0)
1703*436bf2bcSAndroid Build Coastguard Worker 			goto fail;
1704*436bf2bcSAndroid Build Coastguard Worker 
1705*436bf2bcSAndroid Build Coastguard Worker 		last_token = token;
1706*436bf2bcSAndroid Build Coastguard Worker 
1707*436bf2bcSAndroid Build Coastguard Worker 		field = calloc(1, sizeof(*field));
1708*436bf2bcSAndroid Build Coastguard Worker 		if (!field)
1709*436bf2bcSAndroid Build Coastguard Worker 			goto fail;
1710*436bf2bcSAndroid Build Coastguard Worker 
1711*436bf2bcSAndroid Build Coastguard Worker 		field->event = event;
1712*436bf2bcSAndroid Build Coastguard Worker 
1713*436bf2bcSAndroid Build Coastguard Worker 		/* read the rest of the type */
1714*436bf2bcSAndroid Build Coastguard Worker 		for (;;) {
1715*436bf2bcSAndroid Build Coastguard Worker 			type = read_token(tep, &token);
1716*436bf2bcSAndroid Build Coastguard Worker 			if (type == TEP_EVENT_ITEM ||
1717*436bf2bcSAndroid Build Coastguard Worker 			    (type == TEP_EVENT_OP && strcmp(token, "*") == 0) ||
1718*436bf2bcSAndroid Build Coastguard Worker 			    /*
1719*436bf2bcSAndroid Build Coastguard Worker 			     * Some of the ftrace fields are broken and have
1720*436bf2bcSAndroid Build Coastguard Worker 			     * an illegal "." in them.
1721*436bf2bcSAndroid Build Coastguard Worker 			     */
1722*436bf2bcSAndroid Build Coastguard Worker 			    (event->flags & TEP_EVENT_FL_ISFTRACE &&
1723*436bf2bcSAndroid Build Coastguard Worker 			     type == TEP_EVENT_OP && strcmp(token, ".") == 0)) {
1724*436bf2bcSAndroid Build Coastguard Worker 
1725*436bf2bcSAndroid Build Coastguard Worker 				if (strcmp(token, "*") == 0)
1726*436bf2bcSAndroid Build Coastguard Worker 					field->flags |= TEP_FIELD_IS_POINTER;
1727*436bf2bcSAndroid Build Coastguard Worker 
1728*436bf2bcSAndroid Build Coastguard Worker 				if (field->type) {
1729*436bf2bcSAndroid Build Coastguard Worker 					ret = append(&field->type, delim, last_token);
1730*436bf2bcSAndroid Build Coastguard Worker 					free(last_token);
1731*436bf2bcSAndroid Build Coastguard Worker 					if (ret < 0)
1732*436bf2bcSAndroid Build Coastguard Worker 						goto fail;
1733*436bf2bcSAndroid Build Coastguard Worker 				} else
1734*436bf2bcSAndroid Build Coastguard Worker 					field->type = last_token;
1735*436bf2bcSAndroid Build Coastguard Worker 				last_token = token;
1736*436bf2bcSAndroid Build Coastguard Worker 				delim = " ";
1737*436bf2bcSAndroid Build Coastguard Worker 				continue;
1738*436bf2bcSAndroid Build Coastguard Worker 			}
1739*436bf2bcSAndroid Build Coastguard Worker 
1740*436bf2bcSAndroid Build Coastguard Worker 			/* Handle __attribute__((user)) */
1741*436bf2bcSAndroid Build Coastguard Worker 			if ((type == TEP_EVENT_DELIM) &&
1742*436bf2bcSAndroid Build Coastguard Worker 			    strcmp("__attribute__", last_token) == 0 &&
1743*436bf2bcSAndroid Build Coastguard Worker 			    token[0] == '(') {
1744*436bf2bcSAndroid Build Coastguard Worker 				int depth = 1;
1745*436bf2bcSAndroid Build Coastguard Worker 				int ret;
1746*436bf2bcSAndroid Build Coastguard Worker 
1747*436bf2bcSAndroid Build Coastguard Worker 				ret = append(&field->type, " ", last_token);
1748*436bf2bcSAndroid Build Coastguard Worker 				ret |= append(&field->type, "", "(");
1749*436bf2bcSAndroid Build Coastguard Worker 				if (ret < 0)
1750*436bf2bcSAndroid Build Coastguard Worker 					goto fail;
1751*436bf2bcSAndroid Build Coastguard Worker 
1752*436bf2bcSAndroid Build Coastguard Worker 				delim = " ";
1753*436bf2bcSAndroid Build Coastguard Worker 				while ((type = read_token(tep, &token)) != TEP_EVENT_NONE) {
1754*436bf2bcSAndroid Build Coastguard Worker 					if (type == TEP_EVENT_DELIM) {
1755*436bf2bcSAndroid Build Coastguard Worker 						if (token[0] == '(')
1756*436bf2bcSAndroid Build Coastguard Worker 							depth++;
1757*436bf2bcSAndroid Build Coastguard Worker 						else if (token[0] == ')')
1758*436bf2bcSAndroid Build Coastguard Worker 							depth--;
1759*436bf2bcSAndroid Build Coastguard Worker 						if (!depth)
1760*436bf2bcSAndroid Build Coastguard Worker 							break;
1761*436bf2bcSAndroid Build Coastguard Worker 						ret = append(&field->type, "", token);
1762*436bf2bcSAndroid Build Coastguard Worker 						delim = "";
1763*436bf2bcSAndroid Build Coastguard Worker 					} else {
1764*436bf2bcSAndroid Build Coastguard Worker 						ret = append(&field->type, delim, token);
1765*436bf2bcSAndroid Build Coastguard Worker 						delim = " ";
1766*436bf2bcSAndroid Build Coastguard Worker 					}
1767*436bf2bcSAndroid Build Coastguard Worker 					if (ret < 0)
1768*436bf2bcSAndroid Build Coastguard Worker 						goto fail;
1769*436bf2bcSAndroid Build Coastguard Worker 					free(last_token);
1770*436bf2bcSAndroid Build Coastguard Worker 					last_token = token;
1771*436bf2bcSAndroid Build Coastguard Worker 				}
1772*436bf2bcSAndroid Build Coastguard Worker 				continue;
1773*436bf2bcSAndroid Build Coastguard Worker 			}
1774*436bf2bcSAndroid Build Coastguard Worker 			break;
1775*436bf2bcSAndroid Build Coastguard Worker 		}
1776*436bf2bcSAndroid Build Coastguard Worker 
1777*436bf2bcSAndroid Build Coastguard Worker 		if (!field->type) {
1778*436bf2bcSAndroid Build Coastguard Worker 			do_warning_event(event, "%s: no type found", __func__);
1779*436bf2bcSAndroid Build Coastguard Worker 			goto fail;
1780*436bf2bcSAndroid Build Coastguard Worker 		}
1781*436bf2bcSAndroid Build Coastguard Worker 		field->name = field->alias = last_token;
1782*436bf2bcSAndroid Build Coastguard Worker 
1783*436bf2bcSAndroid Build Coastguard Worker 		if (test_type(type, TEP_EVENT_OP))
1784*436bf2bcSAndroid Build Coastguard Worker 			goto fail;
1785*436bf2bcSAndroid Build Coastguard Worker 
1786*436bf2bcSAndroid Build Coastguard Worker 		if (strcmp(token, "[") == 0) {
1787*436bf2bcSAndroid Build Coastguard Worker 			enum tep_event_type last_type = type;
1788*436bf2bcSAndroid Build Coastguard Worker 			char *brackets = token;
1789*436bf2bcSAndroid Build Coastguard Worker 
1790*436bf2bcSAndroid Build Coastguard Worker 			field->flags |= TEP_FIELD_IS_ARRAY;
1791*436bf2bcSAndroid Build Coastguard Worker 
1792*436bf2bcSAndroid Build Coastguard Worker 			type = read_token(tep, &token);
1793*436bf2bcSAndroid Build Coastguard Worker 
1794*436bf2bcSAndroid Build Coastguard Worker 			if (type == TEP_EVENT_ITEM)
1795*436bf2bcSAndroid Build Coastguard Worker 				field->arraylen = strtoul(token, NULL, 0);
1796*436bf2bcSAndroid Build Coastguard Worker 			else
1797*436bf2bcSAndroid Build Coastguard Worker 				field->arraylen = 0;
1798*436bf2bcSAndroid Build Coastguard Worker 
1799*436bf2bcSAndroid Build Coastguard Worker 		        while (strcmp(token, "]") != 0) {
1800*436bf2bcSAndroid Build Coastguard Worker 				const char *delim;
1801*436bf2bcSAndroid Build Coastguard Worker 
1802*436bf2bcSAndroid Build Coastguard Worker 				if (last_type == TEP_EVENT_ITEM &&
1803*436bf2bcSAndroid Build Coastguard Worker 				    type == TEP_EVENT_ITEM)
1804*436bf2bcSAndroid Build Coastguard Worker 					delim = " ";
1805*436bf2bcSAndroid Build Coastguard Worker 				else
1806*436bf2bcSAndroid Build Coastguard Worker 					delim = "";
1807*436bf2bcSAndroid Build Coastguard Worker 
1808*436bf2bcSAndroid Build Coastguard Worker 				last_type = type;
1809*436bf2bcSAndroid Build Coastguard Worker 
1810*436bf2bcSAndroid Build Coastguard Worker 				ret = append(&brackets, delim, token);
1811*436bf2bcSAndroid Build Coastguard Worker 				if (ret < 0) {
1812*436bf2bcSAndroid Build Coastguard Worker 					free(brackets);
1813*436bf2bcSAndroid Build Coastguard Worker 					goto fail;
1814*436bf2bcSAndroid Build Coastguard Worker 				}
1815*436bf2bcSAndroid Build Coastguard Worker 				/* We only care about the last token */
1816*436bf2bcSAndroid Build Coastguard Worker 				field->arraylen = strtoul(token, NULL, 0);
1817*436bf2bcSAndroid Build Coastguard Worker 				free_token(token);
1818*436bf2bcSAndroid Build Coastguard Worker 				type = read_token(tep, &token);
1819*436bf2bcSAndroid Build Coastguard Worker 				if (type == TEP_EVENT_NONE) {
1820*436bf2bcSAndroid Build Coastguard Worker 					free(brackets);
1821*436bf2bcSAndroid Build Coastguard Worker 					do_warning_event(event, "failed to find token");
1822*436bf2bcSAndroid Build Coastguard Worker 					goto fail;
1823*436bf2bcSAndroid Build Coastguard Worker 				}
1824*436bf2bcSAndroid Build Coastguard Worker 			}
1825*436bf2bcSAndroid Build Coastguard Worker 
1826*436bf2bcSAndroid Build Coastguard Worker 			free_token(token);
1827*436bf2bcSAndroid Build Coastguard Worker 
1828*436bf2bcSAndroid Build Coastguard Worker 			ret = append(&brackets, "", "]");
1829*436bf2bcSAndroid Build Coastguard Worker 			if (ret < 0) {
1830*436bf2bcSAndroid Build Coastguard Worker 				free(brackets);
1831*436bf2bcSAndroid Build Coastguard Worker 				goto fail_expect;
1832*436bf2bcSAndroid Build Coastguard Worker 			}
1833*436bf2bcSAndroid Build Coastguard Worker 
1834*436bf2bcSAndroid Build Coastguard Worker 			/* add brackets to type */
1835*436bf2bcSAndroid Build Coastguard Worker 
1836*436bf2bcSAndroid Build Coastguard Worker 			type = read_token(tep, &token);
1837*436bf2bcSAndroid Build Coastguard Worker 			/*
1838*436bf2bcSAndroid Build Coastguard Worker 			 * If the next token is not an OP, then it is of
1839*436bf2bcSAndroid Build Coastguard Worker 			 * the format: type [] item;
1840*436bf2bcSAndroid Build Coastguard Worker 			 */
1841*436bf2bcSAndroid Build Coastguard Worker 			if (type == TEP_EVENT_ITEM) {
1842*436bf2bcSAndroid Build Coastguard Worker 				ret = append(&field->type, " ", field->name);
1843*436bf2bcSAndroid Build Coastguard Worker 				if (ret < 0) {
1844*436bf2bcSAndroid Build Coastguard Worker 					free(brackets);
1845*436bf2bcSAndroid Build Coastguard Worker 					goto fail;
1846*436bf2bcSAndroid Build Coastguard Worker 				}
1847*436bf2bcSAndroid Build Coastguard Worker 				ret = append(&field->type, "", brackets);
1848*436bf2bcSAndroid Build Coastguard Worker 
1849*436bf2bcSAndroid Build Coastguard Worker 				size_dynamic = type_size(field->name);
1850*436bf2bcSAndroid Build Coastguard Worker 				free_token(field->name);
1851*436bf2bcSAndroid Build Coastguard Worker 				field->name = field->alias = token;
1852*436bf2bcSAndroid Build Coastguard Worker 				type = read_token(tep, &token);
1853*436bf2bcSAndroid Build Coastguard Worker 			} else {
1854*436bf2bcSAndroid Build Coastguard Worker 				ret = append(&field->type, "", brackets);
1855*436bf2bcSAndroid Build Coastguard Worker 				if (ret < 0) {
1856*436bf2bcSAndroid Build Coastguard Worker 					free(brackets);
1857*436bf2bcSAndroid Build Coastguard Worker 					goto fail;
1858*436bf2bcSAndroid Build Coastguard Worker 				}
1859*436bf2bcSAndroid Build Coastguard Worker 			}
1860*436bf2bcSAndroid Build Coastguard Worker 			free(brackets);
1861*436bf2bcSAndroid Build Coastguard Worker 		}
1862*436bf2bcSAndroid Build Coastguard Worker 
1863*436bf2bcSAndroid Build Coastguard Worker 		if (field_is_string(field))
1864*436bf2bcSAndroid Build Coastguard Worker 			field->flags |= TEP_FIELD_IS_STRING;
1865*436bf2bcSAndroid Build Coastguard Worker 		if (field_is_dynamic(field))
1866*436bf2bcSAndroid Build Coastguard Worker 			field->flags |= TEP_FIELD_IS_DYNAMIC;
1867*436bf2bcSAndroid Build Coastguard Worker 		if (field_is_relative_dynamic(field))
1868*436bf2bcSAndroid Build Coastguard Worker 			field->flags |= TEP_FIELD_IS_DYNAMIC | TEP_FIELD_IS_RELATIVE;
1869*436bf2bcSAndroid Build Coastguard Worker 		if (field_is_long(field))
1870*436bf2bcSAndroid Build Coastguard Worker 			field->flags |= TEP_FIELD_IS_LONG;
1871*436bf2bcSAndroid Build Coastguard Worker 
1872*436bf2bcSAndroid Build Coastguard Worker 		if (test_type_token(type, token,  TEP_EVENT_OP, ";"))
1873*436bf2bcSAndroid Build Coastguard Worker 			goto fail;
1874*436bf2bcSAndroid Build Coastguard Worker 		free_token(token);
1875*436bf2bcSAndroid Build Coastguard Worker 
1876*436bf2bcSAndroid Build Coastguard Worker 		if (read_expected(tep, TEP_EVENT_ITEM, "offset") < 0)
1877*436bf2bcSAndroid Build Coastguard Worker 			goto fail_expect;
1878*436bf2bcSAndroid Build Coastguard Worker 
1879*436bf2bcSAndroid Build Coastguard Worker 		if (read_expected(tep, TEP_EVENT_OP, ":") < 0)
1880*436bf2bcSAndroid Build Coastguard Worker 			goto fail_expect;
1881*436bf2bcSAndroid Build Coastguard Worker 
1882*436bf2bcSAndroid Build Coastguard Worker 		if (read_expect_type(tep, TEP_EVENT_ITEM, &token))
1883*436bf2bcSAndroid Build Coastguard Worker 			goto fail;
1884*436bf2bcSAndroid Build Coastguard Worker 		field->offset = strtoul(token, NULL, 0);
1885*436bf2bcSAndroid Build Coastguard Worker 		free_token(token);
1886*436bf2bcSAndroid Build Coastguard Worker 
1887*436bf2bcSAndroid Build Coastguard Worker 		if (read_expected(tep, TEP_EVENT_OP, ";") < 0)
1888*436bf2bcSAndroid Build Coastguard Worker 			goto fail_expect;
1889*436bf2bcSAndroid Build Coastguard Worker 
1890*436bf2bcSAndroid Build Coastguard Worker 		if (read_expected(tep, TEP_EVENT_ITEM, "size") < 0)
1891*436bf2bcSAndroid Build Coastguard Worker 			goto fail_expect;
1892*436bf2bcSAndroid Build Coastguard Worker 
1893*436bf2bcSAndroid Build Coastguard Worker 		if (read_expected(tep, TEP_EVENT_OP, ":") < 0)
1894*436bf2bcSAndroid Build Coastguard Worker 			goto fail_expect;
1895*436bf2bcSAndroid Build Coastguard Worker 
1896*436bf2bcSAndroid Build Coastguard Worker 		if (read_expect_type(tep, TEP_EVENT_ITEM, &token))
1897*436bf2bcSAndroid Build Coastguard Worker 			goto fail;
1898*436bf2bcSAndroid Build Coastguard Worker 		field->size = strtoul(token, NULL, 0);
1899*436bf2bcSAndroid Build Coastguard Worker 		free_token(token);
1900*436bf2bcSAndroid Build Coastguard Worker 
1901*436bf2bcSAndroid Build Coastguard Worker 		/*
1902*436bf2bcSAndroid Build Coastguard Worker 		 * The old data format before dynamic arrays had dynamic
1903*436bf2bcSAndroid Build Coastguard Worker 		 * strings defined with just a 2 byte offset (the length
1904*436bf2bcSAndroid Build Coastguard Worker 		 * is defined by the strlen() of the string. To process them
1905*436bf2bcSAndroid Build Coastguard Worker 		 * correctly, check if the field is dynamic and has a size of
1906*436bf2bcSAndroid Build Coastguard Worker 		 * 2 bytes. All current dynamic events have a size of 4.
1907*436bf2bcSAndroid Build Coastguard Worker 		 */
1908*436bf2bcSAndroid Build Coastguard Worker 		if ((field->flags & TEP_FIELD_IS_DYNAMIC) && field->size == 2)
1909*436bf2bcSAndroid Build Coastguard Worker 			field->flags |= TEP_FIELD_IS_STRING | TEP_FIELD_IS_ARRAY;
1910*436bf2bcSAndroid Build Coastguard Worker 
1911*436bf2bcSAndroid Build Coastguard Worker 		if (read_expected(tep, TEP_EVENT_OP, ";") < 0)
1912*436bf2bcSAndroid Build Coastguard Worker 			goto fail_expect;
1913*436bf2bcSAndroid Build Coastguard Worker 
1914*436bf2bcSAndroid Build Coastguard Worker 		type = read_token(tep, &token);
1915*436bf2bcSAndroid Build Coastguard Worker 		if (type != TEP_EVENT_NEWLINE) {
1916*436bf2bcSAndroid Build Coastguard Worker 			/* newer versions of the kernel have a "signed" type */
1917*436bf2bcSAndroid Build Coastguard Worker 			if (test_type_token(type, token, TEP_EVENT_ITEM, "signed"))
1918*436bf2bcSAndroid Build Coastguard Worker 				goto fail;
1919*436bf2bcSAndroid Build Coastguard Worker 
1920*436bf2bcSAndroid Build Coastguard Worker 			free_token(token);
1921*436bf2bcSAndroid Build Coastguard Worker 
1922*436bf2bcSAndroid Build Coastguard Worker 			if (read_expected(tep, TEP_EVENT_OP, ":") < 0)
1923*436bf2bcSAndroid Build Coastguard Worker 				goto fail_expect;
1924*436bf2bcSAndroid Build Coastguard Worker 
1925*436bf2bcSAndroid Build Coastguard Worker 			if (read_expect_type(tep, TEP_EVENT_ITEM, &token))
1926*436bf2bcSAndroid Build Coastguard Worker 				goto fail;
1927*436bf2bcSAndroid Build Coastguard Worker 
1928*436bf2bcSAndroid Build Coastguard Worker 			if (strtoul(token, NULL, 0))
1929*436bf2bcSAndroid Build Coastguard Worker 				field->flags |= TEP_FIELD_IS_SIGNED;
1930*436bf2bcSAndroid Build Coastguard Worker 
1931*436bf2bcSAndroid Build Coastguard Worker 			free_token(token);
1932*436bf2bcSAndroid Build Coastguard Worker 			if (read_expected(tep, TEP_EVENT_OP, ";") < 0)
1933*436bf2bcSAndroid Build Coastguard Worker 				goto fail_expect;
1934*436bf2bcSAndroid Build Coastguard Worker 
1935*436bf2bcSAndroid Build Coastguard Worker 			if (read_expect_type(tep, TEP_EVENT_NEWLINE, &token))
1936*436bf2bcSAndroid Build Coastguard Worker 				goto fail;
1937*436bf2bcSAndroid Build Coastguard Worker 		}
1938*436bf2bcSAndroid Build Coastguard Worker 
1939*436bf2bcSAndroid Build Coastguard Worker 		free_token(token);
1940*436bf2bcSAndroid Build Coastguard Worker 
1941*436bf2bcSAndroid Build Coastguard Worker 		if (field->flags & (TEP_FIELD_IS_ARRAY | TEP_FIELD_IS_DYNAMIC)) {
1942*436bf2bcSAndroid Build Coastguard Worker 			if (field->arraylen)
1943*436bf2bcSAndroid Build Coastguard Worker 				field->elementsize = field->size / field->arraylen;
1944*436bf2bcSAndroid Build Coastguard Worker 			else if (field->flags & TEP_FIELD_IS_DYNAMIC)
1945*436bf2bcSAndroid Build Coastguard Worker 				field->elementsize = size_dynamic;
1946*436bf2bcSAndroid Build Coastguard Worker 			else if (field->flags & TEP_FIELD_IS_STRING)
1947*436bf2bcSAndroid Build Coastguard Worker 				field->elementsize = 1;
1948*436bf2bcSAndroid Build Coastguard Worker 			else if (field->flags & TEP_FIELD_IS_LONG)
1949*436bf2bcSAndroid Build Coastguard Worker 				field->elementsize = event->tep ?
1950*436bf2bcSAndroid Build Coastguard Worker 						     event->tep->long_size :
1951*436bf2bcSAndroid Build Coastguard Worker 						     sizeof(long);
1952*436bf2bcSAndroid Build Coastguard Worker 		} else
1953*436bf2bcSAndroid Build Coastguard Worker 			field->elementsize = field->size;
1954*436bf2bcSAndroid Build Coastguard Worker 
1955*436bf2bcSAndroid Build Coastguard Worker 		*fields = field;
1956*436bf2bcSAndroid Build Coastguard Worker 		fields = &field->next;
1957*436bf2bcSAndroid Build Coastguard Worker 		field = NULL;
1958*436bf2bcSAndroid Build Coastguard Worker 
1959*436bf2bcSAndroid Build Coastguard Worker 	} while (1);
1960*436bf2bcSAndroid Build Coastguard Worker 
1961*436bf2bcSAndroid Build Coastguard Worker 	return 0;
1962*436bf2bcSAndroid Build Coastguard Worker 
1963*436bf2bcSAndroid Build Coastguard Worker fail:
1964*436bf2bcSAndroid Build Coastguard Worker 	free_token(token);
1965*436bf2bcSAndroid Build Coastguard Worker fail_expect:
1966*436bf2bcSAndroid Build Coastguard Worker 	if (field) {
1967*436bf2bcSAndroid Build Coastguard Worker 		free(field->type);
1968*436bf2bcSAndroid Build Coastguard Worker 		free(field->name);
1969*436bf2bcSAndroid Build Coastguard Worker 		free(field);
1970*436bf2bcSAndroid Build Coastguard Worker 	}
1971*436bf2bcSAndroid Build Coastguard Worker 	return -1;
1972*436bf2bcSAndroid Build Coastguard Worker }
1973*436bf2bcSAndroid Build Coastguard Worker 
event_read_format(struct tep_event * event)1974*436bf2bcSAndroid Build Coastguard Worker static int event_read_format(struct tep_event *event)
1975*436bf2bcSAndroid Build Coastguard Worker {
1976*436bf2bcSAndroid Build Coastguard Worker 	char *token;
1977*436bf2bcSAndroid Build Coastguard Worker 	int ret;
1978*436bf2bcSAndroid Build Coastguard Worker 
1979*436bf2bcSAndroid Build Coastguard Worker 	if (read_expected_item(event->tep, TEP_EVENT_ITEM, "format") < 0)
1980*436bf2bcSAndroid Build Coastguard Worker 		return -1;
1981*436bf2bcSAndroid Build Coastguard Worker 
1982*436bf2bcSAndroid Build Coastguard Worker 	if (read_expected(event->tep, TEP_EVENT_OP, ":") < 0)
1983*436bf2bcSAndroid Build Coastguard Worker 		return -1;
1984*436bf2bcSAndroid Build Coastguard Worker 
1985*436bf2bcSAndroid Build Coastguard Worker 	if (read_expect_type(event->tep, TEP_EVENT_NEWLINE, &token))
1986*436bf2bcSAndroid Build Coastguard Worker 		goto fail;
1987*436bf2bcSAndroid Build Coastguard Worker 	free_token(token);
1988*436bf2bcSAndroid Build Coastguard Worker 
1989*436bf2bcSAndroid Build Coastguard Worker 	ret = event_read_fields(event->tep, event, &event->format.common_fields);
1990*436bf2bcSAndroid Build Coastguard Worker 	if (ret < 0)
1991*436bf2bcSAndroid Build Coastguard Worker 		return ret;
1992*436bf2bcSAndroid Build Coastguard Worker 	event->format.nr_common = ret;
1993*436bf2bcSAndroid Build Coastguard Worker 
1994*436bf2bcSAndroid Build Coastguard Worker 	ret = event_read_fields(event->tep, event, &event->format.fields);
1995*436bf2bcSAndroid Build Coastguard Worker 	if (ret < 0)
1996*436bf2bcSAndroid Build Coastguard Worker 		return ret;
1997*436bf2bcSAndroid Build Coastguard Worker 	event->format.nr_fields = ret;
1998*436bf2bcSAndroid Build Coastguard Worker 
1999*436bf2bcSAndroid Build Coastguard Worker 	return 0;
2000*436bf2bcSAndroid Build Coastguard Worker 
2001*436bf2bcSAndroid Build Coastguard Worker  fail:
2002*436bf2bcSAndroid Build Coastguard Worker 	free_token(token);
2003*436bf2bcSAndroid Build Coastguard Worker 	return -1;
2004*436bf2bcSAndroid Build Coastguard Worker }
2005*436bf2bcSAndroid Build Coastguard Worker 
2006*436bf2bcSAndroid Build Coastguard Worker static enum tep_event_type
2007*436bf2bcSAndroid Build Coastguard Worker process_arg_token(struct tep_event *event, struct tep_print_arg *arg,
2008*436bf2bcSAndroid Build Coastguard Worker 		  char **tok, enum tep_event_type type);
2009*436bf2bcSAndroid Build Coastguard Worker 
2010*436bf2bcSAndroid Build Coastguard Worker static enum tep_event_type
process_arg(struct tep_event * event,struct tep_print_arg * arg,char ** tok)2011*436bf2bcSAndroid Build Coastguard Worker process_arg(struct tep_event *event, struct tep_print_arg *arg, char **tok)
2012*436bf2bcSAndroid Build Coastguard Worker {
2013*436bf2bcSAndroid Build Coastguard Worker 	enum tep_event_type type;
2014*436bf2bcSAndroid Build Coastguard Worker 	char *token;
2015*436bf2bcSAndroid Build Coastguard Worker 
2016*436bf2bcSAndroid Build Coastguard Worker 	type = read_token(event->tep, &token);
2017*436bf2bcSAndroid Build Coastguard Worker 	*tok = token;
2018*436bf2bcSAndroid Build Coastguard Worker 
2019*436bf2bcSAndroid Build Coastguard Worker 	return process_arg_token(event, arg, tok, type);
2020*436bf2bcSAndroid Build Coastguard Worker }
2021*436bf2bcSAndroid Build Coastguard Worker 
2022*436bf2bcSAndroid Build Coastguard Worker static enum tep_event_type
2023*436bf2bcSAndroid Build Coastguard Worker process_op(struct tep_event *event, struct tep_print_arg *arg, char **tok);
2024*436bf2bcSAndroid Build Coastguard Worker 
2025*436bf2bcSAndroid Build Coastguard Worker /*
2026*436bf2bcSAndroid Build Coastguard Worker  * For __print_symbolic() and __print_flags, we need to completely
2027*436bf2bcSAndroid Build Coastguard Worker  * evaluate the first argument, which defines what to print next.
2028*436bf2bcSAndroid Build Coastguard Worker  */
2029*436bf2bcSAndroid Build Coastguard Worker static enum tep_event_type
process_field_arg(struct tep_event * event,struct tep_print_arg * arg,char ** tok)2030*436bf2bcSAndroid Build Coastguard Worker process_field_arg(struct tep_event *event, struct tep_print_arg *arg, char **tok)
2031*436bf2bcSAndroid Build Coastguard Worker {
2032*436bf2bcSAndroid Build Coastguard Worker 	enum tep_event_type type;
2033*436bf2bcSAndroid Build Coastguard Worker 
2034*436bf2bcSAndroid Build Coastguard Worker 	type = process_arg(event, arg, tok);
2035*436bf2bcSAndroid Build Coastguard Worker 
2036*436bf2bcSAndroid Build Coastguard Worker 	while (type == TEP_EVENT_OP) {
2037*436bf2bcSAndroid Build Coastguard Worker 		type = process_op(event, arg, tok);
2038*436bf2bcSAndroid Build Coastguard Worker 	}
2039*436bf2bcSAndroid Build Coastguard Worker 
2040*436bf2bcSAndroid Build Coastguard Worker 	return type;
2041*436bf2bcSAndroid Build Coastguard Worker }
2042*436bf2bcSAndroid Build Coastguard Worker 
2043*436bf2bcSAndroid Build Coastguard Worker static enum tep_event_type
process_cond(struct tep_event * event,struct tep_print_arg * top,char ** tok)2044*436bf2bcSAndroid Build Coastguard Worker process_cond(struct tep_event *event, struct tep_print_arg *top, char **tok)
2045*436bf2bcSAndroid Build Coastguard Worker {
2046*436bf2bcSAndroid Build Coastguard Worker 	struct tep_print_arg *arg, *left, *right;
2047*436bf2bcSAndroid Build Coastguard Worker 	enum tep_event_type type;
2048*436bf2bcSAndroid Build Coastguard Worker 	char *token = NULL;
2049*436bf2bcSAndroid Build Coastguard Worker 
2050*436bf2bcSAndroid Build Coastguard Worker 	arg = alloc_arg();
2051*436bf2bcSAndroid Build Coastguard Worker 	left = alloc_arg();
2052*436bf2bcSAndroid Build Coastguard Worker 	right = alloc_arg();
2053*436bf2bcSAndroid Build Coastguard Worker 
2054*436bf2bcSAndroid Build Coastguard Worker 	if (!arg || !left || !right) {
2055*436bf2bcSAndroid Build Coastguard Worker 		do_warning_event(event, "%s: not enough memory!", __func__);
2056*436bf2bcSAndroid Build Coastguard Worker 		/* arg will be freed at out_free */
2057*436bf2bcSAndroid Build Coastguard Worker 		free_arg(left);
2058*436bf2bcSAndroid Build Coastguard Worker 		free_arg(right);
2059*436bf2bcSAndroid Build Coastguard Worker 		goto out_free;
2060*436bf2bcSAndroid Build Coastguard Worker 	}
2061*436bf2bcSAndroid Build Coastguard Worker 
2062*436bf2bcSAndroid Build Coastguard Worker 	arg->type = TEP_PRINT_OP;
2063*436bf2bcSAndroid Build Coastguard Worker 	arg->op.left = left;
2064*436bf2bcSAndroid Build Coastguard Worker 	arg->op.right = right;
2065*436bf2bcSAndroid Build Coastguard Worker 
2066*436bf2bcSAndroid Build Coastguard Worker 	*tok = NULL;
2067*436bf2bcSAndroid Build Coastguard Worker 	type = process_arg(event, left, &token);
2068*436bf2bcSAndroid Build Coastguard Worker 
2069*436bf2bcSAndroid Build Coastguard Worker  again:
2070*436bf2bcSAndroid Build Coastguard Worker 	if (type == TEP_EVENT_ERROR)
2071*436bf2bcSAndroid Build Coastguard Worker 		goto out_free;
2072*436bf2bcSAndroid Build Coastguard Worker 
2073*436bf2bcSAndroid Build Coastguard Worker 	/* Handle other operations in the arguments */
2074*436bf2bcSAndroid Build Coastguard Worker 	if (type == TEP_EVENT_OP && strcmp(token, ":") != 0) {
2075*436bf2bcSAndroid Build Coastguard Worker 		type = process_op(event, left, &token);
2076*436bf2bcSAndroid Build Coastguard Worker 		goto again;
2077*436bf2bcSAndroid Build Coastguard Worker 	}
2078*436bf2bcSAndroid Build Coastguard Worker 
2079*436bf2bcSAndroid Build Coastguard Worker 	if (test_type_token(type, token, TEP_EVENT_OP, ":"))
2080*436bf2bcSAndroid Build Coastguard Worker 		goto out_free;
2081*436bf2bcSAndroid Build Coastguard Worker 
2082*436bf2bcSAndroid Build Coastguard Worker 	arg->op.op = token;
2083*436bf2bcSAndroid Build Coastguard Worker 
2084*436bf2bcSAndroid Build Coastguard Worker 	type = process_arg(event, right, &token);
2085*436bf2bcSAndroid Build Coastguard Worker 
2086*436bf2bcSAndroid Build Coastguard Worker 	top->op.right = arg;
2087*436bf2bcSAndroid Build Coastguard Worker 
2088*436bf2bcSAndroid Build Coastguard Worker 	*tok = token;
2089*436bf2bcSAndroid Build Coastguard Worker 	return type;
2090*436bf2bcSAndroid Build Coastguard Worker 
2091*436bf2bcSAndroid Build Coastguard Worker out_free:
2092*436bf2bcSAndroid Build Coastguard Worker 	/* Top may point to itself */
2093*436bf2bcSAndroid Build Coastguard Worker 	top->op.right = NULL;
2094*436bf2bcSAndroid Build Coastguard Worker 	free_token(token);
2095*436bf2bcSAndroid Build Coastguard Worker 	free_arg(arg);
2096*436bf2bcSAndroid Build Coastguard Worker 	return TEP_EVENT_ERROR;
2097*436bf2bcSAndroid Build Coastguard Worker }
2098*436bf2bcSAndroid Build Coastguard Worker 
2099*436bf2bcSAndroid Build Coastguard Worker static enum tep_event_type
process_array(struct tep_event * event,struct tep_print_arg * top,char ** tok)2100*436bf2bcSAndroid Build Coastguard Worker process_array(struct tep_event *event, struct tep_print_arg *top, char **tok)
2101*436bf2bcSAndroid Build Coastguard Worker {
2102*436bf2bcSAndroid Build Coastguard Worker 	struct tep_print_arg *arg;
2103*436bf2bcSAndroid Build Coastguard Worker 	enum tep_event_type type;
2104*436bf2bcSAndroid Build Coastguard Worker 	char *token = NULL;
2105*436bf2bcSAndroid Build Coastguard Worker 
2106*436bf2bcSAndroid Build Coastguard Worker 	arg = alloc_arg();
2107*436bf2bcSAndroid Build Coastguard Worker 	if (!arg) {
2108*436bf2bcSAndroid Build Coastguard Worker 		do_warning_event(event, "%s: not enough memory!", __func__);
2109*436bf2bcSAndroid Build Coastguard Worker 		/* '*tok' is set to top->op.op.  No need to free. */
2110*436bf2bcSAndroid Build Coastguard Worker 		*tok = NULL;
2111*436bf2bcSAndroid Build Coastguard Worker 		return TEP_EVENT_ERROR;
2112*436bf2bcSAndroid Build Coastguard Worker 	}
2113*436bf2bcSAndroid Build Coastguard Worker 
2114*436bf2bcSAndroid Build Coastguard Worker 	*tok = NULL;
2115*436bf2bcSAndroid Build Coastguard Worker 	type = process_arg(event, arg, &token);
2116*436bf2bcSAndroid Build Coastguard Worker 	if (test_type_token(type, token, TEP_EVENT_OP, "]"))
2117*436bf2bcSAndroid Build Coastguard Worker 		goto out_free;
2118*436bf2bcSAndroid Build Coastguard Worker 
2119*436bf2bcSAndroid Build Coastguard Worker 	top->op.right = arg;
2120*436bf2bcSAndroid Build Coastguard Worker 
2121*436bf2bcSAndroid Build Coastguard Worker 	free_token(token);
2122*436bf2bcSAndroid Build Coastguard Worker 	type = read_token_item(event->tep, &token);
2123*436bf2bcSAndroid Build Coastguard Worker 	*tok = token;
2124*436bf2bcSAndroid Build Coastguard Worker 
2125*436bf2bcSAndroid Build Coastguard Worker 	return type;
2126*436bf2bcSAndroid Build Coastguard Worker 
2127*436bf2bcSAndroid Build Coastguard Worker out_free:
2128*436bf2bcSAndroid Build Coastguard Worker 	free_token(token);
2129*436bf2bcSAndroid Build Coastguard Worker 	free_arg(arg);
2130*436bf2bcSAndroid Build Coastguard Worker 	return TEP_EVENT_ERROR;
2131*436bf2bcSAndroid Build Coastguard Worker }
2132*436bf2bcSAndroid Build Coastguard Worker 
get_op_prio(char * op)2133*436bf2bcSAndroid Build Coastguard Worker static int get_op_prio(char *op)
2134*436bf2bcSAndroid Build Coastguard Worker {
2135*436bf2bcSAndroid Build Coastguard Worker 	if (strlen(op) == 1) {
2136*436bf2bcSAndroid Build Coastguard Worker 		switch (op[0]) {
2137*436bf2bcSAndroid Build Coastguard Worker 		case '~':
2138*436bf2bcSAndroid Build Coastguard Worker 		case '!':
2139*436bf2bcSAndroid Build Coastguard Worker 			return 4;
2140*436bf2bcSAndroid Build Coastguard Worker 		case '*':
2141*436bf2bcSAndroid Build Coastguard Worker 		case '/':
2142*436bf2bcSAndroid Build Coastguard Worker 		case '%':
2143*436bf2bcSAndroid Build Coastguard Worker 			return 6;
2144*436bf2bcSAndroid Build Coastguard Worker 		case '+':
2145*436bf2bcSAndroid Build Coastguard Worker 		case '-':
2146*436bf2bcSAndroid Build Coastguard Worker 			return 7;
2147*436bf2bcSAndroid Build Coastguard Worker 			/* '>>' and '<<' are 8 */
2148*436bf2bcSAndroid Build Coastguard Worker 		case '<':
2149*436bf2bcSAndroid Build Coastguard Worker 		case '>':
2150*436bf2bcSAndroid Build Coastguard Worker 			return 9;
2151*436bf2bcSAndroid Build Coastguard Worker 			/* '==' and '!=' are 10 */
2152*436bf2bcSAndroid Build Coastguard Worker 		case '&':
2153*436bf2bcSAndroid Build Coastguard Worker 			return 11;
2154*436bf2bcSAndroid Build Coastguard Worker 		case '^':
2155*436bf2bcSAndroid Build Coastguard Worker 			return 12;
2156*436bf2bcSAndroid Build Coastguard Worker 		case '|':
2157*436bf2bcSAndroid Build Coastguard Worker 			return 13;
2158*436bf2bcSAndroid Build Coastguard Worker 		case '?':
2159*436bf2bcSAndroid Build Coastguard Worker 			return 16;
2160*436bf2bcSAndroid Build Coastguard Worker 		default:
2161*436bf2bcSAndroid Build Coastguard Worker 			do_warning("unknown op '%c'", op[0]);
2162*436bf2bcSAndroid Build Coastguard Worker 			return -1;
2163*436bf2bcSAndroid Build Coastguard Worker 		}
2164*436bf2bcSAndroid Build Coastguard Worker 	} else {
2165*436bf2bcSAndroid Build Coastguard Worker 		if (strcmp(op, "++") == 0 ||
2166*436bf2bcSAndroid Build Coastguard Worker 		    strcmp(op, "--") == 0) {
2167*436bf2bcSAndroid Build Coastguard Worker 			return 3;
2168*436bf2bcSAndroid Build Coastguard Worker 		} else if (strcmp(op, ">>") == 0 ||
2169*436bf2bcSAndroid Build Coastguard Worker 			   strcmp(op, "<<") == 0) {
2170*436bf2bcSAndroid Build Coastguard Worker 			return 8;
2171*436bf2bcSAndroid Build Coastguard Worker 		} else if (strcmp(op, ">=") == 0 ||
2172*436bf2bcSAndroid Build Coastguard Worker 			   strcmp(op, "<=") == 0) {
2173*436bf2bcSAndroid Build Coastguard Worker 			return 9;
2174*436bf2bcSAndroid Build Coastguard Worker 		} else if (strcmp(op, "==") == 0 ||
2175*436bf2bcSAndroid Build Coastguard Worker 			   strcmp(op, "!=") == 0) {
2176*436bf2bcSAndroid Build Coastguard Worker 			return 10;
2177*436bf2bcSAndroid Build Coastguard Worker 		} else if (strcmp(op, "&&") == 0) {
2178*436bf2bcSAndroid Build Coastguard Worker 			return 14;
2179*436bf2bcSAndroid Build Coastguard Worker 		} else if (strcmp(op, "||") == 0) {
2180*436bf2bcSAndroid Build Coastguard Worker 			return 15;
2181*436bf2bcSAndroid Build Coastguard Worker 		} else {
2182*436bf2bcSAndroid Build Coastguard Worker 			do_warning("unknown op '%s'", op);
2183*436bf2bcSAndroid Build Coastguard Worker 			return -1;
2184*436bf2bcSAndroid Build Coastguard Worker 		}
2185*436bf2bcSAndroid Build Coastguard Worker 	}
2186*436bf2bcSAndroid Build Coastguard Worker }
2187*436bf2bcSAndroid Build Coastguard Worker 
set_op_prio(struct tep_print_arg * arg)2188*436bf2bcSAndroid Build Coastguard Worker static int set_op_prio(struct tep_print_arg *arg)
2189*436bf2bcSAndroid Build Coastguard Worker {
2190*436bf2bcSAndroid Build Coastguard Worker 
2191*436bf2bcSAndroid Build Coastguard Worker 	/* single ops are the greatest */
2192*436bf2bcSAndroid Build Coastguard Worker 	if (!arg->op.left || arg->op.left->type == TEP_PRINT_NULL)
2193*436bf2bcSAndroid Build Coastguard Worker 		arg->op.prio = 0;
2194*436bf2bcSAndroid Build Coastguard Worker 	else
2195*436bf2bcSAndroid Build Coastguard Worker 		arg->op.prio = get_op_prio(arg->op.op);
2196*436bf2bcSAndroid Build Coastguard Worker 
2197*436bf2bcSAndroid Build Coastguard Worker 	return arg->op.prio;
2198*436bf2bcSAndroid Build Coastguard Worker }
2199*436bf2bcSAndroid Build Coastguard Worker 
consolidate_op_arg(enum tep_event_type type,struct tep_print_arg * arg)2200*436bf2bcSAndroid Build Coastguard Worker static int consolidate_op_arg(enum tep_event_type type, struct tep_print_arg *arg)
2201*436bf2bcSAndroid Build Coastguard Worker {
2202*436bf2bcSAndroid Build Coastguard Worker 	unsigned long long val, left, right;
2203*436bf2bcSAndroid Build Coastguard Worker 	int ret = 0;
2204*436bf2bcSAndroid Build Coastguard Worker 
2205*436bf2bcSAndroid Build Coastguard Worker 	if (type == TEP_EVENT_ERROR)
2206*436bf2bcSAndroid Build Coastguard Worker 		return -1;
2207*436bf2bcSAndroid Build Coastguard Worker 
2208*436bf2bcSAndroid Build Coastguard Worker 	if (arg->type != TEP_PRINT_OP)
2209*436bf2bcSAndroid Build Coastguard Worker 		return 0;
2210*436bf2bcSAndroid Build Coastguard Worker 
2211*436bf2bcSAndroid Build Coastguard Worker 	if (arg->op.left)
2212*436bf2bcSAndroid Build Coastguard Worker 		ret = consolidate_op_arg(type, arg->op.left);
2213*436bf2bcSAndroid Build Coastguard Worker 	if (ret < 0)
2214*436bf2bcSAndroid Build Coastguard Worker 		return ret;
2215*436bf2bcSAndroid Build Coastguard Worker 
2216*436bf2bcSAndroid Build Coastguard Worker 	if (arg->op.right)
2217*436bf2bcSAndroid Build Coastguard Worker 		ret = consolidate_op_arg(type, arg->op.right);
2218*436bf2bcSAndroid Build Coastguard Worker 	if (ret < 0)
2219*436bf2bcSAndroid Build Coastguard Worker 		return ret;
2220*436bf2bcSAndroid Build Coastguard Worker 
2221*436bf2bcSAndroid Build Coastguard Worker 	if (!arg->op.left || !arg->op.right)
2222*436bf2bcSAndroid Build Coastguard Worker 		return 0;
2223*436bf2bcSAndroid Build Coastguard Worker 
2224*436bf2bcSAndroid Build Coastguard Worker 	if (arg->op.left->type != TEP_PRINT_ATOM ||
2225*436bf2bcSAndroid Build Coastguard Worker 	    arg->op.right->type != TEP_PRINT_ATOM)
2226*436bf2bcSAndroid Build Coastguard Worker 		return 0;
2227*436bf2bcSAndroid Build Coastguard Worker 
2228*436bf2bcSAndroid Build Coastguard Worker 	/* Two atoms, we can do the operation now. */
2229*436bf2bcSAndroid Build Coastguard Worker 	left = strtoull(arg->op.left->atom.atom, NULL, 0);
2230*436bf2bcSAndroid Build Coastguard Worker 	right = strtoull(arg->op.right->atom.atom, NULL, 0);
2231*436bf2bcSAndroid Build Coastguard Worker 
2232*436bf2bcSAndroid Build Coastguard Worker 	switch (arg->op.op[0]) {
2233*436bf2bcSAndroid Build Coastguard Worker 	case '>':
2234*436bf2bcSAndroid Build Coastguard Worker 		switch (arg->op.op[1]) {
2235*436bf2bcSAndroid Build Coastguard Worker 		case '>':
2236*436bf2bcSAndroid Build Coastguard Worker 			val = left >> right;
2237*436bf2bcSAndroid Build Coastguard Worker 			break;
2238*436bf2bcSAndroid Build Coastguard Worker 		case '=':
2239*436bf2bcSAndroid Build Coastguard Worker 			val = left >= right;
2240*436bf2bcSAndroid Build Coastguard Worker 			break;
2241*436bf2bcSAndroid Build Coastguard Worker 		default:
2242*436bf2bcSAndroid Build Coastguard Worker 			val = left > right;
2243*436bf2bcSAndroid Build Coastguard Worker 			break;
2244*436bf2bcSAndroid Build Coastguard Worker 		}
2245*436bf2bcSAndroid Build Coastguard Worker 		break;
2246*436bf2bcSAndroid Build Coastguard Worker 	case '<':
2247*436bf2bcSAndroid Build Coastguard Worker 		switch (arg->op.op[1]) {
2248*436bf2bcSAndroid Build Coastguard Worker 		case '<':
2249*436bf2bcSAndroid Build Coastguard Worker 			val = left << right;
2250*436bf2bcSAndroid Build Coastguard Worker 			break;
2251*436bf2bcSAndroid Build Coastguard Worker 		case '=':
2252*436bf2bcSAndroid Build Coastguard Worker 			val = left <= right;
2253*436bf2bcSAndroid Build Coastguard Worker 			break;
2254*436bf2bcSAndroid Build Coastguard Worker 		default:
2255*436bf2bcSAndroid Build Coastguard Worker 			val = left < right;
2256*436bf2bcSAndroid Build Coastguard Worker 			break;
2257*436bf2bcSAndroid Build Coastguard Worker 		}
2258*436bf2bcSAndroid Build Coastguard Worker 		break;
2259*436bf2bcSAndroid Build Coastguard Worker 	case '&':
2260*436bf2bcSAndroid Build Coastguard Worker 		switch (arg->op.op[1]) {
2261*436bf2bcSAndroid Build Coastguard Worker 		case '&':
2262*436bf2bcSAndroid Build Coastguard Worker 			val = left && right;
2263*436bf2bcSAndroid Build Coastguard Worker 			break;
2264*436bf2bcSAndroid Build Coastguard Worker 		default:
2265*436bf2bcSAndroid Build Coastguard Worker 			val = left & right;
2266*436bf2bcSAndroid Build Coastguard Worker 			break;
2267*436bf2bcSAndroid Build Coastguard Worker 		}
2268*436bf2bcSAndroid Build Coastguard Worker 		break;
2269*436bf2bcSAndroid Build Coastguard Worker 	case '|':
2270*436bf2bcSAndroid Build Coastguard Worker 		switch (arg->op.op[1]) {
2271*436bf2bcSAndroid Build Coastguard Worker 		case '|':
2272*436bf2bcSAndroid Build Coastguard Worker 			val = left || right;
2273*436bf2bcSAndroid Build Coastguard Worker 			break;
2274*436bf2bcSAndroid Build Coastguard Worker 		default:
2275*436bf2bcSAndroid Build Coastguard Worker 			val = left | right;
2276*436bf2bcSAndroid Build Coastguard Worker 			break;
2277*436bf2bcSAndroid Build Coastguard Worker 		}
2278*436bf2bcSAndroid Build Coastguard Worker 		break;
2279*436bf2bcSAndroid Build Coastguard Worker 	case '-':
2280*436bf2bcSAndroid Build Coastguard Worker 		val = left - right;
2281*436bf2bcSAndroid Build Coastguard Worker 		break;
2282*436bf2bcSAndroid Build Coastguard Worker 	case '+':
2283*436bf2bcSAndroid Build Coastguard Worker 		val = left + right;
2284*436bf2bcSAndroid Build Coastguard Worker 		break;
2285*436bf2bcSAndroid Build Coastguard Worker 	case '*':
2286*436bf2bcSAndroid Build Coastguard Worker 		val = left * right;
2287*436bf2bcSAndroid Build Coastguard Worker 		break;
2288*436bf2bcSAndroid Build Coastguard Worker 	case '^':
2289*436bf2bcSAndroid Build Coastguard Worker 		val = left ^ right;
2290*436bf2bcSAndroid Build Coastguard Worker 		break;
2291*436bf2bcSAndroid Build Coastguard Worker 	case '/':
2292*436bf2bcSAndroid Build Coastguard Worker 		val = left / right;
2293*436bf2bcSAndroid Build Coastguard Worker 		break;
2294*436bf2bcSAndroid Build Coastguard Worker 	case '%':
2295*436bf2bcSAndroid Build Coastguard Worker 		val = left % right;
2296*436bf2bcSAndroid Build Coastguard Worker 		break;
2297*436bf2bcSAndroid Build Coastguard Worker 	case '=':
2298*436bf2bcSAndroid Build Coastguard Worker 		/* Only '==' is called here */
2299*436bf2bcSAndroid Build Coastguard Worker 		val = left == right;
2300*436bf2bcSAndroid Build Coastguard Worker 		break;
2301*436bf2bcSAndroid Build Coastguard Worker 	case '!':
2302*436bf2bcSAndroid Build Coastguard Worker 		/* Only '!=' is called here. */
2303*436bf2bcSAndroid Build Coastguard Worker 		val = left != right;
2304*436bf2bcSAndroid Build Coastguard Worker 		break;
2305*436bf2bcSAndroid Build Coastguard Worker 	default:
2306*436bf2bcSAndroid Build Coastguard Worker 		return 0;
2307*436bf2bcSAndroid Build Coastguard Worker 	}
2308*436bf2bcSAndroid Build Coastguard Worker 
2309*436bf2bcSAndroid Build Coastguard Worker 	free_arg(arg->op.left);
2310*436bf2bcSAndroid Build Coastguard Worker 	free_arg(arg->op.right);
2311*436bf2bcSAndroid Build Coastguard Worker 
2312*436bf2bcSAndroid Build Coastguard Worker 	arg->type = TEP_PRINT_ATOM;
2313*436bf2bcSAndroid Build Coastguard Worker 	free(arg->op.op);
2314*436bf2bcSAndroid Build Coastguard Worker 	return asprintf(&arg->atom.atom, "%lld", val) < 0 ? -1 : 0;
2315*436bf2bcSAndroid Build Coastguard Worker }
2316*436bf2bcSAndroid Build Coastguard Worker 
2317*436bf2bcSAndroid Build Coastguard Worker /* Note, *tok does not get freed, but will most likely be saved */
2318*436bf2bcSAndroid Build Coastguard Worker static enum tep_event_type
process_op(struct tep_event * event,struct tep_print_arg * arg,char ** tok)2319*436bf2bcSAndroid Build Coastguard Worker process_op(struct tep_event *event, struct tep_print_arg *arg, char **tok)
2320*436bf2bcSAndroid Build Coastguard Worker {
2321*436bf2bcSAndroid Build Coastguard Worker 	struct tep_print_arg *left, *right = NULL;
2322*436bf2bcSAndroid Build Coastguard Worker 	enum tep_event_type type;
2323*436bf2bcSAndroid Build Coastguard Worker 	char *token;
2324*436bf2bcSAndroid Build Coastguard Worker 
2325*436bf2bcSAndroid Build Coastguard Worker 	/* the op is passed in via tok */
2326*436bf2bcSAndroid Build Coastguard Worker 	token = *tok;
2327*436bf2bcSAndroid Build Coastguard Worker 
2328*436bf2bcSAndroid Build Coastguard Worker 	if (arg->type == TEP_PRINT_OP && !arg->op.left) {
2329*436bf2bcSAndroid Build Coastguard Worker 		/* handle single op */
2330*436bf2bcSAndroid Build Coastguard Worker 		switch (token[0]) {
2331*436bf2bcSAndroid Build Coastguard Worker 		case '~':
2332*436bf2bcSAndroid Build Coastguard Worker 		case '!':
2333*436bf2bcSAndroid Build Coastguard Worker 		case '+':
2334*436bf2bcSAndroid Build Coastguard Worker 		case '-':
2335*436bf2bcSAndroid Build Coastguard Worker 			break;
2336*436bf2bcSAndroid Build Coastguard Worker 		default:
2337*436bf2bcSAndroid Build Coastguard Worker 			do_warning_event(event, "bad op token %s", token);
2338*436bf2bcSAndroid Build Coastguard Worker 			goto out_free;
2339*436bf2bcSAndroid Build Coastguard Worker 
2340*436bf2bcSAndroid Build Coastguard Worker 		}
2341*436bf2bcSAndroid Build Coastguard Worker 		if (token[1]) {
2342*436bf2bcSAndroid Build Coastguard Worker 			do_warning_event(event, "bad op token %s", token);
2343*436bf2bcSAndroid Build Coastguard Worker 			goto out_free;
2344*436bf2bcSAndroid Build Coastguard Worker 		}
2345*436bf2bcSAndroid Build Coastguard Worker 
2346*436bf2bcSAndroid Build Coastguard Worker 		/* make an empty left */
2347*436bf2bcSAndroid Build Coastguard Worker 		left = alloc_arg();
2348*436bf2bcSAndroid Build Coastguard Worker 		if (!left)
2349*436bf2bcSAndroid Build Coastguard Worker 			goto out_warn_free;
2350*436bf2bcSAndroid Build Coastguard Worker 
2351*436bf2bcSAndroid Build Coastguard Worker 		left->type = TEP_PRINT_NULL;
2352*436bf2bcSAndroid Build Coastguard Worker 		arg->op.left = left;
2353*436bf2bcSAndroid Build Coastguard Worker 
2354*436bf2bcSAndroid Build Coastguard Worker 		right = alloc_arg();
2355*436bf2bcSAndroid Build Coastguard Worker 		if (!right)
2356*436bf2bcSAndroid Build Coastguard Worker 			goto out_warn_free;
2357*436bf2bcSAndroid Build Coastguard Worker 
2358*436bf2bcSAndroid Build Coastguard Worker 		arg->op.right = right;
2359*436bf2bcSAndroid Build Coastguard Worker 
2360*436bf2bcSAndroid Build Coastguard Worker 		/* do not free the token, it belongs to an op */
2361*436bf2bcSAndroid Build Coastguard Worker 		*tok = NULL;
2362*436bf2bcSAndroid Build Coastguard Worker 		type = process_arg(event, right, tok);
2363*436bf2bcSAndroid Build Coastguard Worker 
2364*436bf2bcSAndroid Build Coastguard Worker 	} else if (strcmp(token, "?") == 0) {
2365*436bf2bcSAndroid Build Coastguard Worker 
2366*436bf2bcSAndroid Build Coastguard Worker 		left = alloc_arg();
2367*436bf2bcSAndroid Build Coastguard Worker 		if (!left)
2368*436bf2bcSAndroid Build Coastguard Worker 			goto out_warn_free;
2369*436bf2bcSAndroid Build Coastguard Worker 
2370*436bf2bcSAndroid Build Coastguard Worker 		/* copy the top arg to the left */
2371*436bf2bcSAndroid Build Coastguard Worker 		*left = *arg;
2372*436bf2bcSAndroid Build Coastguard Worker 
2373*436bf2bcSAndroid Build Coastguard Worker 		arg->type = TEP_PRINT_OP;
2374*436bf2bcSAndroid Build Coastguard Worker 		arg->op.op = token;
2375*436bf2bcSAndroid Build Coastguard Worker 		arg->op.left = left;
2376*436bf2bcSAndroid Build Coastguard Worker 		arg->op.right = NULL;
2377*436bf2bcSAndroid Build Coastguard Worker 		arg->op.prio = 0;
2378*436bf2bcSAndroid Build Coastguard Worker 
2379*436bf2bcSAndroid Build Coastguard Worker 		/* it will set arg->op.right */
2380*436bf2bcSAndroid Build Coastguard Worker 		type = process_cond(event, arg, tok);
2381*436bf2bcSAndroid Build Coastguard Worker 
2382*436bf2bcSAndroid Build Coastguard Worker 	} else if (strcmp(token, ">>") == 0 ||
2383*436bf2bcSAndroid Build Coastguard Worker 		   strcmp(token, "<<") == 0 ||
2384*436bf2bcSAndroid Build Coastguard Worker 		   strcmp(token, "&") == 0 ||
2385*436bf2bcSAndroid Build Coastguard Worker 		   strcmp(token, "|") == 0 ||
2386*436bf2bcSAndroid Build Coastguard Worker 		   strcmp(token, "&&") == 0 ||
2387*436bf2bcSAndroid Build Coastguard Worker 		   strcmp(token, "||") == 0 ||
2388*436bf2bcSAndroid Build Coastguard Worker 		   strcmp(token, "-") == 0 ||
2389*436bf2bcSAndroid Build Coastguard Worker 		   strcmp(token, "+") == 0 ||
2390*436bf2bcSAndroid Build Coastguard Worker 		   strcmp(token, "*") == 0 ||
2391*436bf2bcSAndroid Build Coastguard Worker 		   strcmp(token, "^") == 0 ||
2392*436bf2bcSAndroid Build Coastguard Worker 		   strcmp(token, "/") == 0 ||
2393*436bf2bcSAndroid Build Coastguard Worker 		   strcmp(token, "%") == 0 ||
2394*436bf2bcSAndroid Build Coastguard Worker 		   strcmp(token, "<") == 0 ||
2395*436bf2bcSAndroid Build Coastguard Worker 		   strcmp(token, ">") == 0 ||
2396*436bf2bcSAndroid Build Coastguard Worker 		   strcmp(token, "<=") == 0 ||
2397*436bf2bcSAndroid Build Coastguard Worker 		   strcmp(token, ">=") == 0 ||
2398*436bf2bcSAndroid Build Coastguard Worker 		   strcmp(token, "==") == 0 ||
2399*436bf2bcSAndroid Build Coastguard Worker 		   strcmp(token, "!=") == 0) {
2400*436bf2bcSAndroid Build Coastguard Worker 
2401*436bf2bcSAndroid Build Coastguard Worker 		left = alloc_arg();
2402*436bf2bcSAndroid Build Coastguard Worker 		if (!left)
2403*436bf2bcSAndroid Build Coastguard Worker 			goto out_warn_free;
2404*436bf2bcSAndroid Build Coastguard Worker 
2405*436bf2bcSAndroid Build Coastguard Worker 		/* copy the top arg to the left */
2406*436bf2bcSAndroid Build Coastguard Worker 		*left = *arg;
2407*436bf2bcSAndroid Build Coastguard Worker 
2408*436bf2bcSAndroid Build Coastguard Worker 		arg->type = TEP_PRINT_OP;
2409*436bf2bcSAndroid Build Coastguard Worker 		arg->op.op = token;
2410*436bf2bcSAndroid Build Coastguard Worker 		arg->op.left = left;
2411*436bf2bcSAndroid Build Coastguard Worker 		arg->op.right = NULL;
2412*436bf2bcSAndroid Build Coastguard Worker 
2413*436bf2bcSAndroid Build Coastguard Worker 		if (set_op_prio(arg) == -1) {
2414*436bf2bcSAndroid Build Coastguard Worker 			event->flags |= TEP_EVENT_FL_FAILED;
2415*436bf2bcSAndroid Build Coastguard Worker 			/* arg->op.op (= token) will be freed at out_free */
2416*436bf2bcSAndroid Build Coastguard Worker 			arg->op.op = NULL;
2417*436bf2bcSAndroid Build Coastguard Worker 			goto out_free;
2418*436bf2bcSAndroid Build Coastguard Worker 		}
2419*436bf2bcSAndroid Build Coastguard Worker 
2420*436bf2bcSAndroid Build Coastguard Worker 		type = read_token_item(event->tep, &token);
2421*436bf2bcSAndroid Build Coastguard Worker 		*tok = token;
2422*436bf2bcSAndroid Build Coastguard Worker 
2423*436bf2bcSAndroid Build Coastguard Worker 		/* could just be a type pointer */
2424*436bf2bcSAndroid Build Coastguard Worker 		if ((strcmp(arg->op.op, "*") == 0) &&
2425*436bf2bcSAndroid Build Coastguard Worker 		    type == TEP_EVENT_DELIM && (strcmp(token, ")") == 0)) {
2426*436bf2bcSAndroid Build Coastguard Worker 			int ret;
2427*436bf2bcSAndroid Build Coastguard Worker 
2428*436bf2bcSAndroid Build Coastguard Worker 			if (left->type != TEP_PRINT_ATOM) {
2429*436bf2bcSAndroid Build Coastguard Worker 				do_warning_event(event, "bad pointer type");
2430*436bf2bcSAndroid Build Coastguard Worker 				goto out_free;
2431*436bf2bcSAndroid Build Coastguard Worker 			}
2432*436bf2bcSAndroid Build Coastguard Worker 			ret = append(&left->atom.atom, " ", "*");
2433*436bf2bcSAndroid Build Coastguard Worker 			if (ret < 0)
2434*436bf2bcSAndroid Build Coastguard Worker 				goto out_warn_free;
2435*436bf2bcSAndroid Build Coastguard Worker 
2436*436bf2bcSAndroid Build Coastguard Worker 			free(arg->op.op);
2437*436bf2bcSAndroid Build Coastguard Worker 			*arg = *left;
2438*436bf2bcSAndroid Build Coastguard Worker 			free(left);
2439*436bf2bcSAndroid Build Coastguard Worker 
2440*436bf2bcSAndroid Build Coastguard Worker 			return type;
2441*436bf2bcSAndroid Build Coastguard Worker 		}
2442*436bf2bcSAndroid Build Coastguard Worker 
2443*436bf2bcSAndroid Build Coastguard Worker 		right = alloc_arg();
2444*436bf2bcSAndroid Build Coastguard Worker 		if (!right)
2445*436bf2bcSAndroid Build Coastguard Worker 			goto out_warn_free;
2446*436bf2bcSAndroid Build Coastguard Worker 
2447*436bf2bcSAndroid Build Coastguard Worker 		type = process_arg_token(event, right, tok, type);
2448*436bf2bcSAndroid Build Coastguard Worker 		if (type == TEP_EVENT_ERROR) {
2449*436bf2bcSAndroid Build Coastguard Worker 			free_arg(right);
2450*436bf2bcSAndroid Build Coastguard Worker 			/* token was freed in process_arg_token() via *tok */
2451*436bf2bcSAndroid Build Coastguard Worker 			token = NULL;
2452*436bf2bcSAndroid Build Coastguard Worker 			goto out_free;
2453*436bf2bcSAndroid Build Coastguard Worker 		}
2454*436bf2bcSAndroid Build Coastguard Worker 
2455*436bf2bcSAndroid Build Coastguard Worker 		if (right->type == TEP_PRINT_OP &&
2456*436bf2bcSAndroid Build Coastguard Worker 		    get_op_prio(arg->op.op) < get_op_prio(right->op.op)) {
2457*436bf2bcSAndroid Build Coastguard Worker 			struct tep_print_arg tmp;
2458*436bf2bcSAndroid Build Coastguard Worker 
2459*436bf2bcSAndroid Build Coastguard Worker 			/* rotate ops according to the priority */
2460*436bf2bcSAndroid Build Coastguard Worker 			arg->op.right = right->op.left;
2461*436bf2bcSAndroid Build Coastguard Worker 
2462*436bf2bcSAndroid Build Coastguard Worker 			tmp = *arg;
2463*436bf2bcSAndroid Build Coastguard Worker 			*arg = *right;
2464*436bf2bcSAndroid Build Coastguard Worker 			*right = tmp;
2465*436bf2bcSAndroid Build Coastguard Worker 
2466*436bf2bcSAndroid Build Coastguard Worker 			arg->op.left = right;
2467*436bf2bcSAndroid Build Coastguard Worker 		} else {
2468*436bf2bcSAndroid Build Coastguard Worker 			arg->op.right = right;
2469*436bf2bcSAndroid Build Coastguard Worker 		}
2470*436bf2bcSAndroid Build Coastguard Worker 
2471*436bf2bcSAndroid Build Coastguard Worker 	} else if (strcmp(token, "[") == 0) {
2472*436bf2bcSAndroid Build Coastguard Worker 
2473*436bf2bcSAndroid Build Coastguard Worker 		left = alloc_arg();
2474*436bf2bcSAndroid Build Coastguard Worker 		if (!left)
2475*436bf2bcSAndroid Build Coastguard Worker 			goto out_warn_free;
2476*436bf2bcSAndroid Build Coastguard Worker 
2477*436bf2bcSAndroid Build Coastguard Worker 		*left = *arg;
2478*436bf2bcSAndroid Build Coastguard Worker 
2479*436bf2bcSAndroid Build Coastguard Worker 		arg->type = TEP_PRINT_OP;
2480*436bf2bcSAndroid Build Coastguard Worker 		arg->op.op = token;
2481*436bf2bcSAndroid Build Coastguard Worker 		arg->op.left = left;
2482*436bf2bcSAndroid Build Coastguard Worker 		arg->op.right = NULL;
2483*436bf2bcSAndroid Build Coastguard Worker 
2484*436bf2bcSAndroid Build Coastguard Worker 		arg->op.prio = 0;
2485*436bf2bcSAndroid Build Coastguard Worker 
2486*436bf2bcSAndroid Build Coastguard Worker 		/* it will set arg->op.right */
2487*436bf2bcSAndroid Build Coastguard Worker 		type = process_array(event, arg, tok);
2488*436bf2bcSAndroid Build Coastguard Worker 
2489*436bf2bcSAndroid Build Coastguard Worker 	} else {
2490*436bf2bcSAndroid Build Coastguard Worker 		do_warning_event(event, "unknown op '%s'", token);
2491*436bf2bcSAndroid Build Coastguard Worker 		event->flags |= TEP_EVENT_FL_FAILED;
2492*436bf2bcSAndroid Build Coastguard Worker 		/* the arg is now the left side */
2493*436bf2bcSAndroid Build Coastguard Worker 		goto out_free;
2494*436bf2bcSAndroid Build Coastguard Worker 	}
2495*436bf2bcSAndroid Build Coastguard Worker 
2496*436bf2bcSAndroid Build Coastguard Worker 	if (type == TEP_EVENT_OP && strcmp(*tok, ":") != 0) {
2497*436bf2bcSAndroid Build Coastguard Worker 		int prio;
2498*436bf2bcSAndroid Build Coastguard Worker 
2499*436bf2bcSAndroid Build Coastguard Worker 		/* higher prios need to be closer to the root */
2500*436bf2bcSAndroid Build Coastguard Worker 		prio = get_op_prio(*tok);
2501*436bf2bcSAndroid Build Coastguard Worker 
2502*436bf2bcSAndroid Build Coastguard Worker 		if (prio > arg->op.prio)
2503*436bf2bcSAndroid Build Coastguard Worker 			return process_op(event, arg, tok);
2504*436bf2bcSAndroid Build Coastguard Worker 
2505*436bf2bcSAndroid Build Coastguard Worker 		return process_op(event, right, tok);
2506*436bf2bcSAndroid Build Coastguard Worker 	}
2507*436bf2bcSAndroid Build Coastguard Worker 
2508*436bf2bcSAndroid Build Coastguard Worker 	return type;
2509*436bf2bcSAndroid Build Coastguard Worker 
2510*436bf2bcSAndroid Build Coastguard Worker out_warn_free:
2511*436bf2bcSAndroid Build Coastguard Worker 	do_warning_event(event, "%s: not enough memory!", __func__);
2512*436bf2bcSAndroid Build Coastguard Worker out_free:
2513*436bf2bcSAndroid Build Coastguard Worker 	free_token(token);
2514*436bf2bcSAndroid Build Coastguard Worker 	*tok = NULL;
2515*436bf2bcSAndroid Build Coastguard Worker 	return TEP_EVENT_ERROR;
2516*436bf2bcSAndroid Build Coastguard Worker }
2517*436bf2bcSAndroid Build Coastguard Worker 
2518*436bf2bcSAndroid Build Coastguard Worker static enum tep_event_type
process_entry(struct tep_event * event __maybe_unused,struct tep_print_arg * arg,char ** tok)2519*436bf2bcSAndroid Build Coastguard Worker process_entry(struct tep_event *event __maybe_unused, struct tep_print_arg *arg,
2520*436bf2bcSAndroid Build Coastguard Worker 	      char **tok)
2521*436bf2bcSAndroid Build Coastguard Worker {
2522*436bf2bcSAndroid Build Coastguard Worker 	enum tep_event_type type;
2523*436bf2bcSAndroid Build Coastguard Worker 	char *field;
2524*436bf2bcSAndroid Build Coastguard Worker 	char *token;
2525*436bf2bcSAndroid Build Coastguard Worker 
2526*436bf2bcSAndroid Build Coastguard Worker 	type = read_token_item(event->tep, &token);
2527*436bf2bcSAndroid Build Coastguard Worker 	/*
2528*436bf2bcSAndroid Build Coastguard Worker 	 * Check if REC happens to be surrounded by parenthesis, and
2529*436bf2bcSAndroid Build Coastguard Worker 	 * return if that's the case, as "(REC)->" is valid.
2530*436bf2bcSAndroid Build Coastguard Worker 	 * but return TEP_EVENT_ITEM.
2531*436bf2bcSAndroid Build Coastguard Worker 	 */
2532*436bf2bcSAndroid Build Coastguard Worker 	if (type == TEP_EVENT_DELIM && strcmp(token, ")") == 0) {
2533*436bf2bcSAndroid Build Coastguard Worker 		*tok = token;
2534*436bf2bcSAndroid Build Coastguard Worker 		return TEP_EVENT_ITEM;
2535*436bf2bcSAndroid Build Coastguard Worker 	}
2536*436bf2bcSAndroid Build Coastguard Worker 
2537*436bf2bcSAndroid Build Coastguard Worker 	if (test_type_token(type, token,  TEP_EVENT_OP, "->"))
2538*436bf2bcSAndroid Build Coastguard Worker 		goto out_free;
2539*436bf2bcSAndroid Build Coastguard Worker 
2540*436bf2bcSAndroid Build Coastguard Worker 	free_token(token);
2541*436bf2bcSAndroid Build Coastguard Worker 
2542*436bf2bcSAndroid Build Coastguard Worker 	if (read_expect_type(event->tep, TEP_EVENT_ITEM, &token) < 0)
2543*436bf2bcSAndroid Build Coastguard Worker 		goto out_free;
2544*436bf2bcSAndroid Build Coastguard Worker 	field = token;
2545*436bf2bcSAndroid Build Coastguard Worker 
2546*436bf2bcSAndroid Build Coastguard Worker 	arg->type = TEP_PRINT_FIELD;
2547*436bf2bcSAndroid Build Coastguard Worker 	arg->field.name = field;
2548*436bf2bcSAndroid Build Coastguard Worker 
2549*436bf2bcSAndroid Build Coastguard Worker 	arg->field.field = tep_find_any_field(event, arg->field.name);
2550*436bf2bcSAndroid Build Coastguard Worker 
2551*436bf2bcSAndroid Build Coastguard Worker 	if (is_flag_field) {
2552*436bf2bcSAndroid Build Coastguard Worker 		arg->field.field->flags |= TEP_FIELD_IS_FLAG;
2553*436bf2bcSAndroid Build Coastguard Worker 		is_flag_field = 0;
2554*436bf2bcSAndroid Build Coastguard Worker 	} else if (is_symbolic_field) {
2555*436bf2bcSAndroid Build Coastguard Worker 		arg->field.field->flags |= TEP_FIELD_IS_SYMBOLIC;
2556*436bf2bcSAndroid Build Coastguard Worker 		is_symbolic_field = 0;
2557*436bf2bcSAndroid Build Coastguard Worker 	}
2558*436bf2bcSAndroid Build Coastguard Worker 
2559*436bf2bcSAndroid Build Coastguard Worker 	type = read_token(event->tep, &token);
2560*436bf2bcSAndroid Build Coastguard Worker 	*tok = token;
2561*436bf2bcSAndroid Build Coastguard Worker 
2562*436bf2bcSAndroid Build Coastguard Worker 	return type;
2563*436bf2bcSAndroid Build Coastguard Worker 
2564*436bf2bcSAndroid Build Coastguard Worker  out_free:
2565*436bf2bcSAndroid Build Coastguard Worker 	free_token(token);
2566*436bf2bcSAndroid Build Coastguard Worker 	*tok = NULL;
2567*436bf2bcSAndroid Build Coastguard Worker 	return TEP_EVENT_ERROR;
2568*436bf2bcSAndroid Build Coastguard Worker }
2569*436bf2bcSAndroid Build Coastguard Worker 
alloc_and_process_delim(struct tep_event * event,char * next_token,struct tep_print_arg ** print_arg)2570*436bf2bcSAndroid Build Coastguard Worker static int alloc_and_process_delim(struct tep_event *event, char *next_token,
2571*436bf2bcSAndroid Build Coastguard Worker 				   struct tep_print_arg **print_arg)
2572*436bf2bcSAndroid Build Coastguard Worker {
2573*436bf2bcSAndroid Build Coastguard Worker 	struct tep_print_arg *field;
2574*436bf2bcSAndroid Build Coastguard Worker 	enum tep_event_type type;
2575*436bf2bcSAndroid Build Coastguard Worker 	char *token;
2576*436bf2bcSAndroid Build Coastguard Worker 	int ret = 0;
2577*436bf2bcSAndroid Build Coastguard Worker 
2578*436bf2bcSAndroid Build Coastguard Worker 	field = alloc_arg();
2579*436bf2bcSAndroid Build Coastguard Worker 	if (!field) {
2580*436bf2bcSAndroid Build Coastguard Worker 		do_warning_event(event, "%s: not enough memory!", __func__);
2581*436bf2bcSAndroid Build Coastguard Worker 		errno = ENOMEM;
2582*436bf2bcSAndroid Build Coastguard Worker 		return -1;
2583*436bf2bcSAndroid Build Coastguard Worker 	}
2584*436bf2bcSAndroid Build Coastguard Worker 
2585*436bf2bcSAndroid Build Coastguard Worker 	type = process_arg(event, field, &token);
2586*436bf2bcSAndroid Build Coastguard Worker 
2587*436bf2bcSAndroid Build Coastguard Worker 	/* We do allow operators */
2588*436bf2bcSAndroid Build Coastguard Worker 	if (type == TEP_EVENT_OP) {
2589*436bf2bcSAndroid Build Coastguard Worker 		type = process_op(event, field, &token);
2590*436bf2bcSAndroid Build Coastguard Worker 
2591*436bf2bcSAndroid Build Coastguard Worker 		if (consolidate_op_arg(type, field) < 0)
2592*436bf2bcSAndroid Build Coastguard Worker 			type = TEP_EVENT_ERROR;
2593*436bf2bcSAndroid Build Coastguard Worker 
2594*436bf2bcSAndroid Build Coastguard Worker 		if (type == TEP_EVENT_ERROR)
2595*436bf2bcSAndroid Build Coastguard Worker 			goto out_error;
2596*436bf2bcSAndroid Build Coastguard Worker 	}
2597*436bf2bcSAndroid Build Coastguard Worker 
2598*436bf2bcSAndroid Build Coastguard Worker 	if (test_type_token(type, token, TEP_EVENT_DELIM, next_token))
2599*436bf2bcSAndroid Build Coastguard Worker 		goto out_error;
2600*436bf2bcSAndroid Build Coastguard Worker 
2601*436bf2bcSAndroid Build Coastguard Worker 	*print_arg = field;
2602*436bf2bcSAndroid Build Coastguard Worker 
2603*436bf2bcSAndroid Build Coastguard Worker out_free_token:
2604*436bf2bcSAndroid Build Coastguard Worker 	free_token(token);
2605*436bf2bcSAndroid Build Coastguard Worker 
2606*436bf2bcSAndroid Build Coastguard Worker 	return ret;
2607*436bf2bcSAndroid Build Coastguard Worker out_error:
2608*436bf2bcSAndroid Build Coastguard Worker 	errno = EINVAL;
2609*436bf2bcSAndroid Build Coastguard Worker 	ret = -1;
2610*436bf2bcSAndroid Build Coastguard Worker 	free_arg(field);
2611*436bf2bcSAndroid Build Coastguard Worker 	goto out_free_token;
2612*436bf2bcSAndroid Build Coastguard Worker }
2613*436bf2bcSAndroid Build Coastguard Worker 
2614*436bf2bcSAndroid Build Coastguard Worker static char *arg_eval (struct tep_print_arg *arg);
2615*436bf2bcSAndroid Build Coastguard Worker 
2616*436bf2bcSAndroid Build Coastguard Worker static unsigned long long
eval_type_str(unsigned long long val,const char * type,int pointer)2617*436bf2bcSAndroid Build Coastguard Worker eval_type_str(unsigned long long val, const char *type, int pointer)
2618*436bf2bcSAndroid Build Coastguard Worker {
2619*436bf2bcSAndroid Build Coastguard Worker 	int sign = 0;
2620*436bf2bcSAndroid Build Coastguard Worker 	char *ref;
2621*436bf2bcSAndroid Build Coastguard Worker 	int len;
2622*436bf2bcSAndroid Build Coastguard Worker 
2623*436bf2bcSAndroid Build Coastguard Worker 	len = strlen(type);
2624*436bf2bcSAndroid Build Coastguard Worker 	if (len < 2) {
2625*436bf2bcSAndroid Build Coastguard Worker 		do_warning("invalid type: %s", type);
2626*436bf2bcSAndroid Build Coastguard Worker 		return val;
2627*436bf2bcSAndroid Build Coastguard Worker 	}
2628*436bf2bcSAndroid Build Coastguard Worker 
2629*436bf2bcSAndroid Build Coastguard Worker 	if (pointer) {
2630*436bf2bcSAndroid Build Coastguard Worker 
2631*436bf2bcSAndroid Build Coastguard Worker 		if (type[len-1] != '*') {
2632*436bf2bcSAndroid Build Coastguard Worker 			do_warning("pointer expected with non pointer type");
2633*436bf2bcSAndroid Build Coastguard Worker 			return val;
2634*436bf2bcSAndroid Build Coastguard Worker 		}
2635*436bf2bcSAndroid Build Coastguard Worker 
2636*436bf2bcSAndroid Build Coastguard Worker 		ref = malloc(len);
2637*436bf2bcSAndroid Build Coastguard Worker 		if (!ref) {
2638*436bf2bcSAndroid Build Coastguard Worker 			do_warning("%s: not enough memory!", __func__);
2639*436bf2bcSAndroid Build Coastguard Worker 			return val;
2640*436bf2bcSAndroid Build Coastguard Worker 		}
2641*436bf2bcSAndroid Build Coastguard Worker 		memcpy(ref, type, len);
2642*436bf2bcSAndroid Build Coastguard Worker 
2643*436bf2bcSAndroid Build Coastguard Worker 		/* chop off the " *" */
2644*436bf2bcSAndroid Build Coastguard Worker 		ref[len - 2] = 0;
2645*436bf2bcSAndroid Build Coastguard Worker 
2646*436bf2bcSAndroid Build Coastguard Worker 		val = eval_type_str(val, ref, 0);
2647*436bf2bcSAndroid Build Coastguard Worker 		free(ref);
2648*436bf2bcSAndroid Build Coastguard Worker 		return val;
2649*436bf2bcSAndroid Build Coastguard Worker 	}
2650*436bf2bcSAndroid Build Coastguard Worker 
2651*436bf2bcSAndroid Build Coastguard Worker 	/* check if this is a pointer */
2652*436bf2bcSAndroid Build Coastguard Worker 	if (type[len - 1] == '*')
2653*436bf2bcSAndroid Build Coastguard Worker 		return val;
2654*436bf2bcSAndroid Build Coastguard Worker 
2655*436bf2bcSAndroid Build Coastguard Worker 	/* Try to figure out the arg size*/
2656*436bf2bcSAndroid Build Coastguard Worker 	if (strncmp(type, "struct", 6) == 0)
2657*436bf2bcSAndroid Build Coastguard Worker 		/* all bets off */
2658*436bf2bcSAndroid Build Coastguard Worker 		return val;
2659*436bf2bcSAndroid Build Coastguard Worker 
2660*436bf2bcSAndroid Build Coastguard Worker 	if (strcmp(type, "u8") == 0)
2661*436bf2bcSAndroid Build Coastguard Worker 		return val & 0xff;
2662*436bf2bcSAndroid Build Coastguard Worker 
2663*436bf2bcSAndroid Build Coastguard Worker 	if (strcmp(type, "u16") == 0)
2664*436bf2bcSAndroid Build Coastguard Worker 		return val & 0xffff;
2665*436bf2bcSAndroid Build Coastguard Worker 
2666*436bf2bcSAndroid Build Coastguard Worker 	if (strcmp(type, "u32") == 0)
2667*436bf2bcSAndroid Build Coastguard Worker 		return val & 0xffffffff;
2668*436bf2bcSAndroid Build Coastguard Worker 
2669*436bf2bcSAndroid Build Coastguard Worker 	if (strcmp(type, "u64") == 0 ||
2670*436bf2bcSAndroid Build Coastguard Worker 	    strcmp(type, "s64") == 0)
2671*436bf2bcSAndroid Build Coastguard Worker 		return val;
2672*436bf2bcSAndroid Build Coastguard Worker 
2673*436bf2bcSAndroid Build Coastguard Worker 	if (strcmp(type, "s8") == 0)
2674*436bf2bcSAndroid Build Coastguard Worker 		return (unsigned long long)(char)val & 0xff;
2675*436bf2bcSAndroid Build Coastguard Worker 
2676*436bf2bcSAndroid Build Coastguard Worker 	if (strcmp(type, "s16") == 0)
2677*436bf2bcSAndroid Build Coastguard Worker 		return (unsigned long long)(short)val & 0xffff;
2678*436bf2bcSAndroid Build Coastguard Worker 
2679*436bf2bcSAndroid Build Coastguard Worker 	if (strcmp(type, "s32") == 0)
2680*436bf2bcSAndroid Build Coastguard Worker 		return (unsigned long long)(int)val & 0xffffffff;
2681*436bf2bcSAndroid Build Coastguard Worker 
2682*436bf2bcSAndroid Build Coastguard Worker 	if (strncmp(type, "unsigned ", 9) == 0) {
2683*436bf2bcSAndroid Build Coastguard Worker 		sign = 0;
2684*436bf2bcSAndroid Build Coastguard Worker 		type += 9;
2685*436bf2bcSAndroid Build Coastguard Worker 	}
2686*436bf2bcSAndroid Build Coastguard Worker 
2687*436bf2bcSAndroid Build Coastguard Worker 	if (strcmp(type, "char") == 0) {
2688*436bf2bcSAndroid Build Coastguard Worker 		if (sign)
2689*436bf2bcSAndroid Build Coastguard Worker 			return (unsigned long long)(char)val & 0xff;
2690*436bf2bcSAndroid Build Coastguard Worker 		else
2691*436bf2bcSAndroid Build Coastguard Worker 			return val & 0xff;
2692*436bf2bcSAndroid Build Coastguard Worker 	}
2693*436bf2bcSAndroid Build Coastguard Worker 
2694*436bf2bcSAndroid Build Coastguard Worker 	if (strcmp(type, "short") == 0) {
2695*436bf2bcSAndroid Build Coastguard Worker 		if (sign)
2696*436bf2bcSAndroid Build Coastguard Worker 			return (unsigned long long)(short)val & 0xffff;
2697*436bf2bcSAndroid Build Coastguard Worker 		else
2698*436bf2bcSAndroid Build Coastguard Worker 			return val & 0xffff;
2699*436bf2bcSAndroid Build Coastguard Worker 	}
2700*436bf2bcSAndroid Build Coastguard Worker 
2701*436bf2bcSAndroid Build Coastguard Worker 	if (strcmp(type, "int") == 0) {
2702*436bf2bcSAndroid Build Coastguard Worker 		if (sign)
2703*436bf2bcSAndroid Build Coastguard Worker 			return (unsigned long long)(int)val & 0xffffffff;
2704*436bf2bcSAndroid Build Coastguard Worker 		else
2705*436bf2bcSAndroid Build Coastguard Worker 			return val & 0xffffffff;
2706*436bf2bcSAndroid Build Coastguard Worker 	}
2707*436bf2bcSAndroid Build Coastguard Worker 
2708*436bf2bcSAndroid Build Coastguard Worker 	return val;
2709*436bf2bcSAndroid Build Coastguard Worker }
2710*436bf2bcSAndroid Build Coastguard Worker 
2711*436bf2bcSAndroid Build Coastguard Worker /*
2712*436bf2bcSAndroid Build Coastguard Worker  * Try to figure out the type.
2713*436bf2bcSAndroid Build Coastguard Worker  */
2714*436bf2bcSAndroid Build Coastguard Worker static unsigned long long
eval_type(unsigned long long val,struct tep_print_arg * arg,int pointer)2715*436bf2bcSAndroid Build Coastguard Worker eval_type(unsigned long long val, struct tep_print_arg *arg, int pointer)
2716*436bf2bcSAndroid Build Coastguard Worker {
2717*436bf2bcSAndroid Build Coastguard Worker 	if (arg->type != TEP_PRINT_TYPE) {
2718*436bf2bcSAndroid Build Coastguard Worker 		do_warning("expected type argument");
2719*436bf2bcSAndroid Build Coastguard Worker 		return 0;
2720*436bf2bcSAndroid Build Coastguard Worker 	}
2721*436bf2bcSAndroid Build Coastguard Worker 
2722*436bf2bcSAndroid Build Coastguard Worker 	return eval_type_str(val, arg->typecast.type, pointer);
2723*436bf2bcSAndroid Build Coastguard Worker }
2724*436bf2bcSAndroid Build Coastguard Worker 
arg_num_eval(struct tep_print_arg * arg,long long * val)2725*436bf2bcSAndroid Build Coastguard Worker static int arg_num_eval(struct tep_print_arg *arg, long long *val)
2726*436bf2bcSAndroid Build Coastguard Worker {
2727*436bf2bcSAndroid Build Coastguard Worker 	long long left, right;
2728*436bf2bcSAndroid Build Coastguard Worker 	int ret = 1;
2729*436bf2bcSAndroid Build Coastguard Worker 
2730*436bf2bcSAndroid Build Coastguard Worker 	switch (arg->type) {
2731*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_ATOM:
2732*436bf2bcSAndroid Build Coastguard Worker 		*val = strtoll(arg->atom.atom, NULL, 0);
2733*436bf2bcSAndroid Build Coastguard Worker 		break;
2734*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_TYPE:
2735*436bf2bcSAndroid Build Coastguard Worker 		ret = arg_num_eval(arg->typecast.item, val);
2736*436bf2bcSAndroid Build Coastguard Worker 		if (!ret)
2737*436bf2bcSAndroid Build Coastguard Worker 			break;
2738*436bf2bcSAndroid Build Coastguard Worker 		*val = eval_type(*val, arg, 0);
2739*436bf2bcSAndroid Build Coastguard Worker 		break;
2740*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_OP:
2741*436bf2bcSAndroid Build Coastguard Worker 		switch (arg->op.op[0]) {
2742*436bf2bcSAndroid Build Coastguard Worker 		case '|':
2743*436bf2bcSAndroid Build Coastguard Worker 			ret = arg_num_eval(arg->op.left, &left);
2744*436bf2bcSAndroid Build Coastguard Worker 			if (!ret)
2745*436bf2bcSAndroid Build Coastguard Worker 				break;
2746*436bf2bcSAndroid Build Coastguard Worker 			ret = arg_num_eval(arg->op.right, &right);
2747*436bf2bcSAndroid Build Coastguard Worker 			if (!ret)
2748*436bf2bcSAndroid Build Coastguard Worker 				break;
2749*436bf2bcSAndroid Build Coastguard Worker 			if (arg->op.op[1])
2750*436bf2bcSAndroid Build Coastguard Worker 				*val = left || right;
2751*436bf2bcSAndroid Build Coastguard Worker 			else
2752*436bf2bcSAndroid Build Coastguard Worker 				*val = left | right;
2753*436bf2bcSAndroid Build Coastguard Worker 			break;
2754*436bf2bcSAndroid Build Coastguard Worker 		case '&':
2755*436bf2bcSAndroid Build Coastguard Worker 			ret = arg_num_eval(arg->op.left, &left);
2756*436bf2bcSAndroid Build Coastguard Worker 			if (!ret)
2757*436bf2bcSAndroid Build Coastguard Worker 				break;
2758*436bf2bcSAndroid Build Coastguard Worker 			ret = arg_num_eval(arg->op.right, &right);
2759*436bf2bcSAndroid Build Coastguard Worker 			if (!ret)
2760*436bf2bcSAndroid Build Coastguard Worker 				break;
2761*436bf2bcSAndroid Build Coastguard Worker 			if (arg->op.op[1])
2762*436bf2bcSAndroid Build Coastguard Worker 				*val = left && right;
2763*436bf2bcSAndroid Build Coastguard Worker 			else
2764*436bf2bcSAndroid Build Coastguard Worker 				*val = left & right;
2765*436bf2bcSAndroid Build Coastguard Worker 			break;
2766*436bf2bcSAndroid Build Coastguard Worker 		case '<':
2767*436bf2bcSAndroid Build Coastguard Worker 			ret = arg_num_eval(arg->op.left, &left);
2768*436bf2bcSAndroid Build Coastguard Worker 			if (!ret)
2769*436bf2bcSAndroid Build Coastguard Worker 				break;
2770*436bf2bcSAndroid Build Coastguard Worker 			ret = arg_num_eval(arg->op.right, &right);
2771*436bf2bcSAndroid Build Coastguard Worker 			if (!ret)
2772*436bf2bcSAndroid Build Coastguard Worker 				break;
2773*436bf2bcSAndroid Build Coastguard Worker 			switch (arg->op.op[1]) {
2774*436bf2bcSAndroid Build Coastguard Worker 			case 0:
2775*436bf2bcSAndroid Build Coastguard Worker 				*val = left < right;
2776*436bf2bcSAndroid Build Coastguard Worker 				break;
2777*436bf2bcSAndroid Build Coastguard Worker 			case '<':
2778*436bf2bcSAndroid Build Coastguard Worker 				*val = left << right;
2779*436bf2bcSAndroid Build Coastguard Worker 				break;
2780*436bf2bcSAndroid Build Coastguard Worker 			case '=':
2781*436bf2bcSAndroid Build Coastguard Worker 				*val = left <= right;
2782*436bf2bcSAndroid Build Coastguard Worker 				break;
2783*436bf2bcSAndroid Build Coastguard Worker 			default:
2784*436bf2bcSAndroid Build Coastguard Worker 				do_warning("unknown op '%s'", arg->op.op);
2785*436bf2bcSAndroid Build Coastguard Worker 				ret = 0;
2786*436bf2bcSAndroid Build Coastguard Worker 			}
2787*436bf2bcSAndroid Build Coastguard Worker 			break;
2788*436bf2bcSAndroid Build Coastguard Worker 		case '>':
2789*436bf2bcSAndroid Build Coastguard Worker 			ret = arg_num_eval(arg->op.left, &left);
2790*436bf2bcSAndroid Build Coastguard Worker 			if (!ret)
2791*436bf2bcSAndroid Build Coastguard Worker 				break;
2792*436bf2bcSAndroid Build Coastguard Worker 			ret = arg_num_eval(arg->op.right, &right);
2793*436bf2bcSAndroid Build Coastguard Worker 			if (!ret)
2794*436bf2bcSAndroid Build Coastguard Worker 				break;
2795*436bf2bcSAndroid Build Coastguard Worker 			switch (arg->op.op[1]) {
2796*436bf2bcSAndroid Build Coastguard Worker 			case 0:
2797*436bf2bcSAndroid Build Coastguard Worker 				*val = left > right;
2798*436bf2bcSAndroid Build Coastguard Worker 				break;
2799*436bf2bcSAndroid Build Coastguard Worker 			case '>':
2800*436bf2bcSAndroid Build Coastguard Worker 				*val = left >> right;
2801*436bf2bcSAndroid Build Coastguard Worker 				break;
2802*436bf2bcSAndroid Build Coastguard Worker 			case '=':
2803*436bf2bcSAndroid Build Coastguard Worker 				*val = left >= right;
2804*436bf2bcSAndroid Build Coastguard Worker 				break;
2805*436bf2bcSAndroid Build Coastguard Worker 			default:
2806*436bf2bcSAndroid Build Coastguard Worker 				do_warning("unknown op '%s'", arg->op.op);
2807*436bf2bcSAndroid Build Coastguard Worker 				ret = 0;
2808*436bf2bcSAndroid Build Coastguard Worker 			}
2809*436bf2bcSAndroid Build Coastguard Worker 			break;
2810*436bf2bcSAndroid Build Coastguard Worker 		case '=':
2811*436bf2bcSAndroid Build Coastguard Worker 			ret = arg_num_eval(arg->op.left, &left);
2812*436bf2bcSAndroid Build Coastguard Worker 			if (!ret)
2813*436bf2bcSAndroid Build Coastguard Worker 				break;
2814*436bf2bcSAndroid Build Coastguard Worker 			ret = arg_num_eval(arg->op.right, &right);
2815*436bf2bcSAndroid Build Coastguard Worker 			if (!ret)
2816*436bf2bcSAndroid Build Coastguard Worker 				break;
2817*436bf2bcSAndroid Build Coastguard Worker 
2818*436bf2bcSAndroid Build Coastguard Worker 			if (arg->op.op[1] != '=') {
2819*436bf2bcSAndroid Build Coastguard Worker 				do_warning("unknown op '%s'", arg->op.op);
2820*436bf2bcSAndroid Build Coastguard Worker 				ret = 0;
2821*436bf2bcSAndroid Build Coastguard Worker 			} else
2822*436bf2bcSAndroid Build Coastguard Worker 				*val = left == right;
2823*436bf2bcSAndroid Build Coastguard Worker 			break;
2824*436bf2bcSAndroid Build Coastguard Worker 		case '!':
2825*436bf2bcSAndroid Build Coastguard Worker 			ret = arg_num_eval(arg->op.left, &left);
2826*436bf2bcSAndroid Build Coastguard Worker 			if (!ret)
2827*436bf2bcSAndroid Build Coastguard Worker 				break;
2828*436bf2bcSAndroid Build Coastguard Worker 			ret = arg_num_eval(arg->op.right, &right);
2829*436bf2bcSAndroid Build Coastguard Worker 			if (!ret)
2830*436bf2bcSAndroid Build Coastguard Worker 				break;
2831*436bf2bcSAndroid Build Coastguard Worker 
2832*436bf2bcSAndroid Build Coastguard Worker 			switch (arg->op.op[1]) {
2833*436bf2bcSAndroid Build Coastguard Worker 			case '=':
2834*436bf2bcSAndroid Build Coastguard Worker 				*val = left != right;
2835*436bf2bcSAndroid Build Coastguard Worker 				break;
2836*436bf2bcSAndroid Build Coastguard Worker 			default:
2837*436bf2bcSAndroid Build Coastguard Worker 				do_warning("unknown op '%s'", arg->op.op);
2838*436bf2bcSAndroid Build Coastguard Worker 				ret = 0;
2839*436bf2bcSAndroid Build Coastguard Worker 			}
2840*436bf2bcSAndroid Build Coastguard Worker 			break;
2841*436bf2bcSAndroid Build Coastguard Worker 		case '-':
2842*436bf2bcSAndroid Build Coastguard Worker 			/* check for negative */
2843*436bf2bcSAndroid Build Coastguard Worker 			if (arg->op.left->type == TEP_PRINT_NULL)
2844*436bf2bcSAndroid Build Coastguard Worker 				left = 0;
2845*436bf2bcSAndroid Build Coastguard Worker 			else
2846*436bf2bcSAndroid Build Coastguard Worker 				ret = arg_num_eval(arg->op.left, &left);
2847*436bf2bcSAndroid Build Coastguard Worker 			if (!ret)
2848*436bf2bcSAndroid Build Coastguard Worker 				break;
2849*436bf2bcSAndroid Build Coastguard Worker 			ret = arg_num_eval(arg->op.right, &right);
2850*436bf2bcSAndroid Build Coastguard Worker 			if (!ret)
2851*436bf2bcSAndroid Build Coastguard Worker 				break;
2852*436bf2bcSAndroid Build Coastguard Worker 			*val = left - right;
2853*436bf2bcSAndroid Build Coastguard Worker 			break;
2854*436bf2bcSAndroid Build Coastguard Worker 		case '+':
2855*436bf2bcSAndroid Build Coastguard Worker 			if (arg->op.left->type == TEP_PRINT_NULL)
2856*436bf2bcSAndroid Build Coastguard Worker 				left = 0;
2857*436bf2bcSAndroid Build Coastguard Worker 			else
2858*436bf2bcSAndroid Build Coastguard Worker 				ret = arg_num_eval(arg->op.left, &left);
2859*436bf2bcSAndroid Build Coastguard Worker 			if (!ret)
2860*436bf2bcSAndroid Build Coastguard Worker 				break;
2861*436bf2bcSAndroid Build Coastguard Worker 			ret = arg_num_eval(arg->op.right, &right);
2862*436bf2bcSAndroid Build Coastguard Worker 			if (!ret)
2863*436bf2bcSAndroid Build Coastguard Worker 				break;
2864*436bf2bcSAndroid Build Coastguard Worker 			*val = left + right;
2865*436bf2bcSAndroid Build Coastguard Worker 			break;
2866*436bf2bcSAndroid Build Coastguard Worker 		case '~':
2867*436bf2bcSAndroid Build Coastguard Worker 			ret = arg_num_eval(arg->op.right, &right);
2868*436bf2bcSAndroid Build Coastguard Worker 			if (!ret)
2869*436bf2bcSAndroid Build Coastguard Worker 				break;
2870*436bf2bcSAndroid Build Coastguard Worker 			*val = ~right;
2871*436bf2bcSAndroid Build Coastguard Worker 			break;
2872*436bf2bcSAndroid Build Coastguard Worker 		default:
2873*436bf2bcSAndroid Build Coastguard Worker 			do_warning("unknown op '%s'", arg->op.op);
2874*436bf2bcSAndroid Build Coastguard Worker 			ret = 0;
2875*436bf2bcSAndroid Build Coastguard Worker 		}
2876*436bf2bcSAndroid Build Coastguard Worker 		break;
2877*436bf2bcSAndroid Build Coastguard Worker 
2878*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_NULL:
2879*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_FIELD ... TEP_PRINT_SYMBOL:
2880*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_STRING:
2881*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_BSTRING:
2882*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_BITMASK:
2883*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_CPUMASK:
2884*436bf2bcSAndroid Build Coastguard Worker 	default:
2885*436bf2bcSAndroid Build Coastguard Worker 		do_warning("invalid eval type %d", arg->type);
2886*436bf2bcSAndroid Build Coastguard Worker 		ret = 0;
2887*436bf2bcSAndroid Build Coastguard Worker 
2888*436bf2bcSAndroid Build Coastguard Worker 	}
2889*436bf2bcSAndroid Build Coastguard Worker 	return ret;
2890*436bf2bcSAndroid Build Coastguard Worker }
2891*436bf2bcSAndroid Build Coastguard Worker 
arg_eval(struct tep_print_arg * arg)2892*436bf2bcSAndroid Build Coastguard Worker static char *arg_eval (struct tep_print_arg *arg)
2893*436bf2bcSAndroid Build Coastguard Worker {
2894*436bf2bcSAndroid Build Coastguard Worker 	long long val;
2895*436bf2bcSAndroid Build Coastguard Worker 	static char buf[24];
2896*436bf2bcSAndroid Build Coastguard Worker 
2897*436bf2bcSAndroid Build Coastguard Worker 	switch (arg->type) {
2898*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_ATOM:
2899*436bf2bcSAndroid Build Coastguard Worker 		return arg->atom.atom;
2900*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_TYPE:
2901*436bf2bcSAndroid Build Coastguard Worker 		return arg_eval(arg->typecast.item);
2902*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_OP:
2903*436bf2bcSAndroid Build Coastguard Worker 		if (!arg_num_eval(arg, &val))
2904*436bf2bcSAndroid Build Coastguard Worker 			break;
2905*436bf2bcSAndroid Build Coastguard Worker 		sprintf(buf, "%lld", val);
2906*436bf2bcSAndroid Build Coastguard Worker 		return buf;
2907*436bf2bcSAndroid Build Coastguard Worker 
2908*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_NULL:
2909*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_FIELD ... TEP_PRINT_SYMBOL:
2910*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_STRING:
2911*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_BSTRING:
2912*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_BITMASK:
2913*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_CPUMASK:
2914*436bf2bcSAndroid Build Coastguard Worker 	default:
2915*436bf2bcSAndroid Build Coastguard Worker 		do_warning("invalid eval type %d", arg->type);
2916*436bf2bcSAndroid Build Coastguard Worker 		break;
2917*436bf2bcSAndroid Build Coastguard Worker 	}
2918*436bf2bcSAndroid Build Coastguard Worker 
2919*436bf2bcSAndroid Build Coastguard Worker 	return NULL;
2920*436bf2bcSAndroid Build Coastguard Worker }
2921*436bf2bcSAndroid Build Coastguard Worker 
2922*436bf2bcSAndroid Build Coastguard Worker static enum tep_event_type
process_fields(struct tep_event * event,struct tep_print_flag_sym ** list,char ** tok)2923*436bf2bcSAndroid Build Coastguard Worker process_fields(struct tep_event *event, struct tep_print_flag_sym **list, char **tok)
2924*436bf2bcSAndroid Build Coastguard Worker {
2925*436bf2bcSAndroid Build Coastguard Worker 	enum tep_event_type type;
2926*436bf2bcSAndroid Build Coastguard Worker 	struct tep_print_arg *arg = NULL;
2927*436bf2bcSAndroid Build Coastguard Worker 	struct tep_print_flag_sym *field;
2928*436bf2bcSAndroid Build Coastguard Worker 	char *token = *tok;
2929*436bf2bcSAndroid Build Coastguard Worker 	char *value;
2930*436bf2bcSAndroid Build Coastguard Worker 
2931*436bf2bcSAndroid Build Coastguard Worker 	do {
2932*436bf2bcSAndroid Build Coastguard Worker 		free_token(token);
2933*436bf2bcSAndroid Build Coastguard Worker 		type = read_token_item(event->tep, &token);
2934*436bf2bcSAndroid Build Coastguard Worker 		if (test_type_token(type, token, TEP_EVENT_OP, "{"))
2935*436bf2bcSAndroid Build Coastguard Worker 			break;
2936*436bf2bcSAndroid Build Coastguard Worker 
2937*436bf2bcSAndroid Build Coastguard Worker 		arg = alloc_arg();
2938*436bf2bcSAndroid Build Coastguard Worker 		if (!arg)
2939*436bf2bcSAndroid Build Coastguard Worker 			goto out_free;
2940*436bf2bcSAndroid Build Coastguard Worker 
2941*436bf2bcSAndroid Build Coastguard Worker 		free_token(token);
2942*436bf2bcSAndroid Build Coastguard Worker 		type = process_arg(event, arg, &token);
2943*436bf2bcSAndroid Build Coastguard Worker 
2944*436bf2bcSAndroid Build Coastguard Worker 		if (type == TEP_EVENT_OP)
2945*436bf2bcSAndroid Build Coastguard Worker 			type = process_op(event, arg, &token);
2946*436bf2bcSAndroid Build Coastguard Worker 
2947*436bf2bcSAndroid Build Coastguard Worker 		if (type == TEP_EVENT_ERROR)
2948*436bf2bcSAndroid Build Coastguard Worker 			goto out_free;
2949*436bf2bcSAndroid Build Coastguard Worker 
2950*436bf2bcSAndroid Build Coastguard Worker 		if (test_type_token(type, token, TEP_EVENT_DELIM, ","))
2951*436bf2bcSAndroid Build Coastguard Worker 			goto out_free;
2952*436bf2bcSAndroid Build Coastguard Worker 
2953*436bf2bcSAndroid Build Coastguard Worker 		field = calloc(1, sizeof(*field));
2954*436bf2bcSAndroid Build Coastguard Worker 		if (!field)
2955*436bf2bcSAndroid Build Coastguard Worker 			goto out_free;
2956*436bf2bcSAndroid Build Coastguard Worker 
2957*436bf2bcSAndroid Build Coastguard Worker 		value = arg_eval(arg);
2958*436bf2bcSAndroid Build Coastguard Worker 		if (value == NULL)
2959*436bf2bcSAndroid Build Coastguard Worker 			goto out_free_field;
2960*436bf2bcSAndroid Build Coastguard Worker 		field->value = strdup(value);
2961*436bf2bcSAndroid Build Coastguard Worker 		if (field->value == NULL)
2962*436bf2bcSAndroid Build Coastguard Worker 			goto out_free_field;
2963*436bf2bcSAndroid Build Coastguard Worker 
2964*436bf2bcSAndroid Build Coastguard Worker 		free_arg(arg);
2965*436bf2bcSAndroid Build Coastguard Worker 		arg = alloc_arg();
2966*436bf2bcSAndroid Build Coastguard Worker 		if (!arg)
2967*436bf2bcSAndroid Build Coastguard Worker 			goto out_free_field;
2968*436bf2bcSAndroid Build Coastguard Worker 
2969*436bf2bcSAndroid Build Coastguard Worker 		free_token(token);
2970*436bf2bcSAndroid Build Coastguard Worker 		type = process_arg(event, arg, &token);
2971*436bf2bcSAndroid Build Coastguard Worker 		if (test_type_token(type, token, TEP_EVENT_OP, "}"))
2972*436bf2bcSAndroid Build Coastguard Worker 			goto out_free_field;
2973*436bf2bcSAndroid Build Coastguard Worker 
2974*436bf2bcSAndroid Build Coastguard Worker 		value = arg_eval(arg);
2975*436bf2bcSAndroid Build Coastguard Worker 		if (value == NULL)
2976*436bf2bcSAndroid Build Coastguard Worker 			goto out_free_field;
2977*436bf2bcSAndroid Build Coastguard Worker 		field->str = strdup(value);
2978*436bf2bcSAndroid Build Coastguard Worker 		if (field->str == NULL)
2979*436bf2bcSAndroid Build Coastguard Worker 			goto out_free_field;
2980*436bf2bcSAndroid Build Coastguard Worker 		free_arg(arg);
2981*436bf2bcSAndroid Build Coastguard Worker 		arg = NULL;
2982*436bf2bcSAndroid Build Coastguard Worker 
2983*436bf2bcSAndroid Build Coastguard Worker 		*list = field;
2984*436bf2bcSAndroid Build Coastguard Worker 		list = &field->next;
2985*436bf2bcSAndroid Build Coastguard Worker 
2986*436bf2bcSAndroid Build Coastguard Worker 		free_token(token);
2987*436bf2bcSAndroid Build Coastguard Worker 		type = read_token_item(event->tep, &token);
2988*436bf2bcSAndroid Build Coastguard Worker 	} while (type == TEP_EVENT_DELIM && strcmp(token, ",") == 0);
2989*436bf2bcSAndroid Build Coastguard Worker 
2990*436bf2bcSAndroid Build Coastguard Worker 	*tok = token;
2991*436bf2bcSAndroid Build Coastguard Worker 	return type;
2992*436bf2bcSAndroid Build Coastguard Worker 
2993*436bf2bcSAndroid Build Coastguard Worker out_free_field:
2994*436bf2bcSAndroid Build Coastguard Worker 	free_flag_sym(field);
2995*436bf2bcSAndroid Build Coastguard Worker out_free:
2996*436bf2bcSAndroid Build Coastguard Worker 	free_arg(arg);
2997*436bf2bcSAndroid Build Coastguard Worker 	free_token(token);
2998*436bf2bcSAndroid Build Coastguard Worker 	*tok = NULL;
2999*436bf2bcSAndroid Build Coastguard Worker 
3000*436bf2bcSAndroid Build Coastguard Worker 	return TEP_EVENT_ERROR;
3001*436bf2bcSAndroid Build Coastguard Worker }
3002*436bf2bcSAndroid Build Coastguard Worker 
3003*436bf2bcSAndroid Build Coastguard Worker static enum tep_event_type
process_flags(struct tep_event * event,struct tep_print_arg * arg,char ** tok)3004*436bf2bcSAndroid Build Coastguard Worker process_flags(struct tep_event *event, struct tep_print_arg *arg, char **tok)
3005*436bf2bcSAndroid Build Coastguard Worker {
3006*436bf2bcSAndroid Build Coastguard Worker 	struct tep_print_arg *field;
3007*436bf2bcSAndroid Build Coastguard Worker 	enum tep_event_type type;
3008*436bf2bcSAndroid Build Coastguard Worker 	char *token = NULL;
3009*436bf2bcSAndroid Build Coastguard Worker 
3010*436bf2bcSAndroid Build Coastguard Worker 	memset(arg, 0, sizeof(*arg));
3011*436bf2bcSAndroid Build Coastguard Worker 	arg->type = TEP_PRINT_FLAGS;
3012*436bf2bcSAndroid Build Coastguard Worker 
3013*436bf2bcSAndroid Build Coastguard Worker 	field = alloc_arg();
3014*436bf2bcSAndroid Build Coastguard Worker 	if (!field) {
3015*436bf2bcSAndroid Build Coastguard Worker 		do_warning_event(event, "%s: not enough memory!", __func__);
3016*436bf2bcSAndroid Build Coastguard Worker 		goto out_free;
3017*436bf2bcSAndroid Build Coastguard Worker 	}
3018*436bf2bcSAndroid Build Coastguard Worker 
3019*436bf2bcSAndroid Build Coastguard Worker 	type = process_field_arg(event, field, &token);
3020*436bf2bcSAndroid Build Coastguard Worker 
3021*436bf2bcSAndroid Build Coastguard Worker 	/* Handle operations in the first argument */
3022*436bf2bcSAndroid Build Coastguard Worker 	while (type == TEP_EVENT_OP)
3023*436bf2bcSAndroid Build Coastguard Worker 		type = process_op(event, field, &token);
3024*436bf2bcSAndroid Build Coastguard Worker 
3025*436bf2bcSAndroid Build Coastguard Worker 	if (test_type_token(type, token, TEP_EVENT_DELIM, ","))
3026*436bf2bcSAndroid Build Coastguard Worker 		goto out_free_field;
3027*436bf2bcSAndroid Build Coastguard Worker 	free_token(token);
3028*436bf2bcSAndroid Build Coastguard Worker 
3029*436bf2bcSAndroid Build Coastguard Worker 	arg->flags.field = field;
3030*436bf2bcSAndroid Build Coastguard Worker 
3031*436bf2bcSAndroid Build Coastguard Worker 	type = read_token_item(event->tep, &token);
3032*436bf2bcSAndroid Build Coastguard Worker 	if (event_item_type(type)) {
3033*436bf2bcSAndroid Build Coastguard Worker 		arg->flags.delim = token;
3034*436bf2bcSAndroid Build Coastguard Worker 		type = read_token_item(event->tep, &token);
3035*436bf2bcSAndroid Build Coastguard Worker 	}
3036*436bf2bcSAndroid Build Coastguard Worker 
3037*436bf2bcSAndroid Build Coastguard Worker 	if (test_type_token(type, token, TEP_EVENT_DELIM, ","))
3038*436bf2bcSAndroid Build Coastguard Worker 		goto out_free;
3039*436bf2bcSAndroid Build Coastguard Worker 
3040*436bf2bcSAndroid Build Coastguard Worker 	type = process_fields(event, &arg->flags.flags, &token);
3041*436bf2bcSAndroid Build Coastguard Worker 	if (test_type_token(type, token, TEP_EVENT_DELIM, ")"))
3042*436bf2bcSAndroid Build Coastguard Worker 		goto out_free;
3043*436bf2bcSAndroid Build Coastguard Worker 
3044*436bf2bcSAndroid Build Coastguard Worker 	free_token(token);
3045*436bf2bcSAndroid Build Coastguard Worker 	type = read_token_item(event->tep, tok);
3046*436bf2bcSAndroid Build Coastguard Worker 	return type;
3047*436bf2bcSAndroid Build Coastguard Worker 
3048*436bf2bcSAndroid Build Coastguard Worker out_free_field:
3049*436bf2bcSAndroid Build Coastguard Worker 	free_arg(field);
3050*436bf2bcSAndroid Build Coastguard Worker out_free:
3051*436bf2bcSAndroid Build Coastguard Worker 	free_token(token);
3052*436bf2bcSAndroid Build Coastguard Worker 	*tok = NULL;
3053*436bf2bcSAndroid Build Coastguard Worker 	return TEP_EVENT_ERROR;
3054*436bf2bcSAndroid Build Coastguard Worker }
3055*436bf2bcSAndroid Build Coastguard Worker 
3056*436bf2bcSAndroid Build Coastguard Worker static enum tep_event_type
process_symbols(struct tep_event * event,struct tep_print_arg * arg,char ** tok)3057*436bf2bcSAndroid Build Coastguard Worker process_symbols(struct tep_event *event, struct tep_print_arg *arg, char **tok)
3058*436bf2bcSAndroid Build Coastguard Worker {
3059*436bf2bcSAndroid Build Coastguard Worker 	struct tep_print_arg *field;
3060*436bf2bcSAndroid Build Coastguard Worker 	enum tep_event_type type;
3061*436bf2bcSAndroid Build Coastguard Worker 	char *token = NULL;
3062*436bf2bcSAndroid Build Coastguard Worker 
3063*436bf2bcSAndroid Build Coastguard Worker 	memset(arg, 0, sizeof(*arg));
3064*436bf2bcSAndroid Build Coastguard Worker 	arg->type = TEP_PRINT_SYMBOL;
3065*436bf2bcSAndroid Build Coastguard Worker 
3066*436bf2bcSAndroid Build Coastguard Worker 	field = alloc_arg();
3067*436bf2bcSAndroid Build Coastguard Worker 	if (!field) {
3068*436bf2bcSAndroid Build Coastguard Worker 		do_warning_event(event, "%s: not enough memory!", __func__);
3069*436bf2bcSAndroid Build Coastguard Worker 		goto out_free;
3070*436bf2bcSAndroid Build Coastguard Worker 	}
3071*436bf2bcSAndroid Build Coastguard Worker 
3072*436bf2bcSAndroid Build Coastguard Worker 	type = process_field_arg(event, field, &token);
3073*436bf2bcSAndroid Build Coastguard Worker 
3074*436bf2bcSAndroid Build Coastguard Worker 	if (test_type_token(type, token, TEP_EVENT_DELIM, ","))
3075*436bf2bcSAndroid Build Coastguard Worker 		goto out_free_field;
3076*436bf2bcSAndroid Build Coastguard Worker 
3077*436bf2bcSAndroid Build Coastguard Worker 	arg->symbol.field = field;
3078*436bf2bcSAndroid Build Coastguard Worker 
3079*436bf2bcSAndroid Build Coastguard Worker 	type = process_fields(event, &arg->symbol.symbols, &token);
3080*436bf2bcSAndroid Build Coastguard Worker 	if (test_type_token(type, token, TEP_EVENT_DELIM, ")"))
3081*436bf2bcSAndroid Build Coastguard Worker 		goto out_free;
3082*436bf2bcSAndroid Build Coastguard Worker 
3083*436bf2bcSAndroid Build Coastguard Worker 	free_token(token);
3084*436bf2bcSAndroid Build Coastguard Worker 	type = read_token_item(event->tep, tok);
3085*436bf2bcSAndroid Build Coastguard Worker 	return type;
3086*436bf2bcSAndroid Build Coastguard Worker 
3087*436bf2bcSAndroid Build Coastguard Worker out_free_field:
3088*436bf2bcSAndroid Build Coastguard Worker 	free_arg(field);
3089*436bf2bcSAndroid Build Coastguard Worker out_free:
3090*436bf2bcSAndroid Build Coastguard Worker 	free_token(token);
3091*436bf2bcSAndroid Build Coastguard Worker 	*tok = NULL;
3092*436bf2bcSAndroid Build Coastguard Worker 	return TEP_EVENT_ERROR;
3093*436bf2bcSAndroid Build Coastguard Worker }
3094*436bf2bcSAndroid Build Coastguard Worker 
3095*436bf2bcSAndroid Build Coastguard Worker static enum tep_event_type
process_hex_common(struct tep_event * event,struct tep_print_arg * arg,char ** tok,enum tep_print_arg_type type)3096*436bf2bcSAndroid Build Coastguard Worker process_hex_common(struct tep_event *event, struct tep_print_arg *arg,
3097*436bf2bcSAndroid Build Coastguard Worker 		   char **tok, enum tep_print_arg_type type)
3098*436bf2bcSAndroid Build Coastguard Worker {
3099*436bf2bcSAndroid Build Coastguard Worker 	memset(arg, 0, sizeof(*arg));
3100*436bf2bcSAndroid Build Coastguard Worker 	arg->type = type;
3101*436bf2bcSAndroid Build Coastguard Worker 
3102*436bf2bcSAndroid Build Coastguard Worker 	if (alloc_and_process_delim(event, ",", &arg->hex.field))
3103*436bf2bcSAndroid Build Coastguard Worker 		goto out;
3104*436bf2bcSAndroid Build Coastguard Worker 
3105*436bf2bcSAndroid Build Coastguard Worker 	if (alloc_and_process_delim(event, ")", &arg->hex.size))
3106*436bf2bcSAndroid Build Coastguard Worker 		goto free_field;
3107*436bf2bcSAndroid Build Coastguard Worker 
3108*436bf2bcSAndroid Build Coastguard Worker 	return read_token_item(event->tep, tok);
3109*436bf2bcSAndroid Build Coastguard Worker 
3110*436bf2bcSAndroid Build Coastguard Worker free_field:
3111*436bf2bcSAndroid Build Coastguard Worker 	free_arg(arg->hex.field);
3112*436bf2bcSAndroid Build Coastguard Worker 	arg->hex.field = NULL;
3113*436bf2bcSAndroid Build Coastguard Worker out:
3114*436bf2bcSAndroid Build Coastguard Worker 	*tok = NULL;
3115*436bf2bcSAndroid Build Coastguard Worker 	return TEP_EVENT_ERROR;
3116*436bf2bcSAndroid Build Coastguard Worker }
3117*436bf2bcSAndroid Build Coastguard Worker 
3118*436bf2bcSAndroid Build Coastguard Worker static enum tep_event_type
process_hex(struct tep_event * event,struct tep_print_arg * arg,char ** tok)3119*436bf2bcSAndroid Build Coastguard Worker process_hex(struct tep_event *event, struct tep_print_arg *arg, char **tok)
3120*436bf2bcSAndroid Build Coastguard Worker {
3121*436bf2bcSAndroid Build Coastguard Worker 	return process_hex_common(event, arg, tok, TEP_PRINT_HEX);
3122*436bf2bcSAndroid Build Coastguard Worker }
3123*436bf2bcSAndroid Build Coastguard Worker 
3124*436bf2bcSAndroid Build Coastguard Worker static enum tep_event_type
process_hex_str(struct tep_event * event,struct tep_print_arg * arg,char ** tok)3125*436bf2bcSAndroid Build Coastguard Worker process_hex_str(struct tep_event *event, struct tep_print_arg *arg,
3126*436bf2bcSAndroid Build Coastguard Worker 		char **tok)
3127*436bf2bcSAndroid Build Coastguard Worker {
3128*436bf2bcSAndroid Build Coastguard Worker 	return process_hex_common(event, arg, tok, TEP_PRINT_HEX_STR);
3129*436bf2bcSAndroid Build Coastguard Worker }
3130*436bf2bcSAndroid Build Coastguard Worker 
3131*436bf2bcSAndroid Build Coastguard Worker static enum tep_event_type
process_int_array(struct tep_event * event,struct tep_print_arg * arg,char ** tok)3132*436bf2bcSAndroid Build Coastguard Worker process_int_array(struct tep_event *event, struct tep_print_arg *arg, char **tok)
3133*436bf2bcSAndroid Build Coastguard Worker {
3134*436bf2bcSAndroid Build Coastguard Worker 	memset(arg, 0, sizeof(*arg));
3135*436bf2bcSAndroid Build Coastguard Worker 	arg->type = TEP_PRINT_INT_ARRAY;
3136*436bf2bcSAndroid Build Coastguard Worker 
3137*436bf2bcSAndroid Build Coastguard Worker 	if (alloc_and_process_delim(event, ",", &arg->int_array.field))
3138*436bf2bcSAndroid Build Coastguard Worker 		goto out;
3139*436bf2bcSAndroid Build Coastguard Worker 
3140*436bf2bcSAndroid Build Coastguard Worker 	if (alloc_and_process_delim(event, ",", &arg->int_array.count))
3141*436bf2bcSAndroid Build Coastguard Worker 		goto free_field;
3142*436bf2bcSAndroid Build Coastguard Worker 
3143*436bf2bcSAndroid Build Coastguard Worker 	if (alloc_and_process_delim(event, ")", &arg->int_array.el_size))
3144*436bf2bcSAndroid Build Coastguard Worker 		goto free_size;
3145*436bf2bcSAndroid Build Coastguard Worker 
3146*436bf2bcSAndroid Build Coastguard Worker 	return read_token_item(event->tep, tok);
3147*436bf2bcSAndroid Build Coastguard Worker 
3148*436bf2bcSAndroid Build Coastguard Worker free_size:
3149*436bf2bcSAndroid Build Coastguard Worker 	free_arg(arg->int_array.count);
3150*436bf2bcSAndroid Build Coastguard Worker 	arg->int_array.count = NULL;
3151*436bf2bcSAndroid Build Coastguard Worker free_field:
3152*436bf2bcSAndroid Build Coastguard Worker 	free_arg(arg->int_array.field);
3153*436bf2bcSAndroid Build Coastguard Worker 	arg->int_array.field = NULL;
3154*436bf2bcSAndroid Build Coastguard Worker out:
3155*436bf2bcSAndroid Build Coastguard Worker 	*tok = NULL;
3156*436bf2bcSAndroid Build Coastguard Worker 	return TEP_EVENT_ERROR;
3157*436bf2bcSAndroid Build Coastguard Worker }
3158*436bf2bcSAndroid Build Coastguard Worker 
3159*436bf2bcSAndroid Build Coastguard Worker static enum tep_event_type
process_dynamic_array(struct tep_event * event,struct tep_print_arg * arg,char ** tok)3160*436bf2bcSAndroid Build Coastguard Worker process_dynamic_array(struct tep_event *event, struct tep_print_arg *arg, char **tok)
3161*436bf2bcSAndroid Build Coastguard Worker {
3162*436bf2bcSAndroid Build Coastguard Worker 	struct tep_format_field *field;
3163*436bf2bcSAndroid Build Coastguard Worker 	enum tep_event_type type;
3164*436bf2bcSAndroid Build Coastguard Worker 	char *token;
3165*436bf2bcSAndroid Build Coastguard Worker 
3166*436bf2bcSAndroid Build Coastguard Worker 	memset(arg, 0, sizeof(*arg));
3167*436bf2bcSAndroid Build Coastguard Worker 	arg->type = TEP_PRINT_DYNAMIC_ARRAY;
3168*436bf2bcSAndroid Build Coastguard Worker 
3169*436bf2bcSAndroid Build Coastguard Worker 	/*
3170*436bf2bcSAndroid Build Coastguard Worker 	 * The item within the parenthesis is another field that holds
3171*436bf2bcSAndroid Build Coastguard Worker 	 * the index into where the array starts.
3172*436bf2bcSAndroid Build Coastguard Worker 	 */
3173*436bf2bcSAndroid Build Coastguard Worker 	type = read_token(event->tep, &token);
3174*436bf2bcSAndroid Build Coastguard Worker 	*tok = token;
3175*436bf2bcSAndroid Build Coastguard Worker 	if (type != TEP_EVENT_ITEM)
3176*436bf2bcSAndroid Build Coastguard Worker 		goto out_free;
3177*436bf2bcSAndroid Build Coastguard Worker 
3178*436bf2bcSAndroid Build Coastguard Worker 	/* Find the field */
3179*436bf2bcSAndroid Build Coastguard Worker 
3180*436bf2bcSAndroid Build Coastguard Worker 	field = tep_find_field(event, token);
3181*436bf2bcSAndroid Build Coastguard Worker 	if (!field)
3182*436bf2bcSAndroid Build Coastguard Worker 		goto out_free;
3183*436bf2bcSAndroid Build Coastguard Worker 
3184*436bf2bcSAndroid Build Coastguard Worker 	arg->dynarray.field = field;
3185*436bf2bcSAndroid Build Coastguard Worker 	arg->dynarray.index = 0;
3186*436bf2bcSAndroid Build Coastguard Worker 
3187*436bf2bcSAndroid Build Coastguard Worker 	if (read_expected(event->tep, TEP_EVENT_DELIM, ")") < 0)
3188*436bf2bcSAndroid Build Coastguard Worker 		goto out_free;
3189*436bf2bcSAndroid Build Coastguard Worker 
3190*436bf2bcSAndroid Build Coastguard Worker 	free_token(token);
3191*436bf2bcSAndroid Build Coastguard Worker 	type = read_token_item(event->tep, &token);
3192*436bf2bcSAndroid Build Coastguard Worker 	*tok = token;
3193*436bf2bcSAndroid Build Coastguard Worker 	if (type != TEP_EVENT_OP || strcmp(token, "[") != 0)
3194*436bf2bcSAndroid Build Coastguard Worker 		return type;
3195*436bf2bcSAndroid Build Coastguard Worker 
3196*436bf2bcSAndroid Build Coastguard Worker 	free_token(token);
3197*436bf2bcSAndroid Build Coastguard Worker 	arg = alloc_arg();
3198*436bf2bcSAndroid Build Coastguard Worker 	if (!arg) {
3199*436bf2bcSAndroid Build Coastguard Worker 		do_warning_event(event, "%s: not enough memory!", __func__);
3200*436bf2bcSAndroid Build Coastguard Worker 		*tok = NULL;
3201*436bf2bcSAndroid Build Coastguard Worker 		return TEP_EVENT_ERROR;
3202*436bf2bcSAndroid Build Coastguard Worker 	}
3203*436bf2bcSAndroid Build Coastguard Worker 
3204*436bf2bcSAndroid Build Coastguard Worker 	type = process_arg(event, arg, &token);
3205*436bf2bcSAndroid Build Coastguard Worker 	if (type == TEP_EVENT_ERROR)
3206*436bf2bcSAndroid Build Coastguard Worker 		goto out_free_arg;
3207*436bf2bcSAndroid Build Coastguard Worker 
3208*436bf2bcSAndroid Build Coastguard Worker 	if (!test_type_token(type, token, TEP_EVENT_OP, "]"))
3209*436bf2bcSAndroid Build Coastguard Worker 		goto out_free_arg;
3210*436bf2bcSAndroid Build Coastguard Worker 
3211*436bf2bcSAndroid Build Coastguard Worker 	free_token(token);
3212*436bf2bcSAndroid Build Coastguard Worker 	type = read_token_item(event->tep, tok);
3213*436bf2bcSAndroid Build Coastguard Worker 	return type;
3214*436bf2bcSAndroid Build Coastguard Worker 
3215*436bf2bcSAndroid Build Coastguard Worker  out_free_arg:
3216*436bf2bcSAndroid Build Coastguard Worker 	free_arg(arg);
3217*436bf2bcSAndroid Build Coastguard Worker  out_free:
3218*436bf2bcSAndroid Build Coastguard Worker 	free_token(token);
3219*436bf2bcSAndroid Build Coastguard Worker 	*tok = NULL;
3220*436bf2bcSAndroid Build Coastguard Worker 	return TEP_EVENT_ERROR;
3221*436bf2bcSAndroid Build Coastguard Worker }
3222*436bf2bcSAndroid Build Coastguard Worker 
3223*436bf2bcSAndroid Build Coastguard Worker static enum tep_event_type
process_dynamic_array_len(struct tep_event * event,struct tep_print_arg * arg,char ** tok)3224*436bf2bcSAndroid Build Coastguard Worker process_dynamic_array_len(struct tep_event *event, struct tep_print_arg *arg,
3225*436bf2bcSAndroid Build Coastguard Worker 			  char **tok)
3226*436bf2bcSAndroid Build Coastguard Worker {
3227*436bf2bcSAndroid Build Coastguard Worker 	struct tep_format_field *field;
3228*436bf2bcSAndroid Build Coastguard Worker 	enum tep_event_type type;
3229*436bf2bcSAndroid Build Coastguard Worker 	char *token;
3230*436bf2bcSAndroid Build Coastguard Worker 
3231*436bf2bcSAndroid Build Coastguard Worker 	if (read_expect_type(event->tep, TEP_EVENT_ITEM, &token) < 0)
3232*436bf2bcSAndroid Build Coastguard Worker 		goto out_free;
3233*436bf2bcSAndroid Build Coastguard Worker 
3234*436bf2bcSAndroid Build Coastguard Worker 	arg->type = TEP_PRINT_DYNAMIC_ARRAY_LEN;
3235*436bf2bcSAndroid Build Coastguard Worker 
3236*436bf2bcSAndroid Build Coastguard Worker 	/* Find the field */
3237*436bf2bcSAndroid Build Coastguard Worker 	field = tep_find_field(event, token);
3238*436bf2bcSAndroid Build Coastguard Worker 	if (!field)
3239*436bf2bcSAndroid Build Coastguard Worker 		goto out_free;
3240*436bf2bcSAndroid Build Coastguard Worker 
3241*436bf2bcSAndroid Build Coastguard Worker 	arg->dynarray.field = field;
3242*436bf2bcSAndroid Build Coastguard Worker 	arg->dynarray.index = 0;
3243*436bf2bcSAndroid Build Coastguard Worker 
3244*436bf2bcSAndroid Build Coastguard Worker 	if (read_expected(event->tep, TEP_EVENT_DELIM, ")") < 0)
3245*436bf2bcSAndroid Build Coastguard Worker 		goto out_err;
3246*436bf2bcSAndroid Build Coastguard Worker 
3247*436bf2bcSAndroid Build Coastguard Worker 	free_token(token);
3248*436bf2bcSAndroid Build Coastguard Worker 	type = read_token(event->tep, &token);
3249*436bf2bcSAndroid Build Coastguard Worker 	*tok = token;
3250*436bf2bcSAndroid Build Coastguard Worker 
3251*436bf2bcSAndroid Build Coastguard Worker 	return type;
3252*436bf2bcSAndroid Build Coastguard Worker 
3253*436bf2bcSAndroid Build Coastguard Worker  out_free:
3254*436bf2bcSAndroid Build Coastguard Worker 	free_token(token);
3255*436bf2bcSAndroid Build Coastguard Worker  out_err:
3256*436bf2bcSAndroid Build Coastguard Worker 	*tok = NULL;
3257*436bf2bcSAndroid Build Coastguard Worker 	return TEP_EVENT_ERROR;
3258*436bf2bcSAndroid Build Coastguard Worker }
3259*436bf2bcSAndroid Build Coastguard Worker 
3260*436bf2bcSAndroid Build Coastguard Worker static enum tep_event_type
process_paren(struct tep_event * event,struct tep_print_arg * arg,char ** tok)3261*436bf2bcSAndroid Build Coastguard Worker process_paren(struct tep_event *event, struct tep_print_arg *arg, char **tok)
3262*436bf2bcSAndroid Build Coastguard Worker {
3263*436bf2bcSAndroid Build Coastguard Worker 	struct tep_print_arg *item_arg;
3264*436bf2bcSAndroid Build Coastguard Worker 	enum tep_event_type type;
3265*436bf2bcSAndroid Build Coastguard Worker 	char *token;
3266*436bf2bcSAndroid Build Coastguard Worker 
3267*436bf2bcSAndroid Build Coastguard Worker 	type = process_arg(event, arg, &token);
3268*436bf2bcSAndroid Build Coastguard Worker 
3269*436bf2bcSAndroid Build Coastguard Worker 	if (type == TEP_EVENT_ERROR)
3270*436bf2bcSAndroid Build Coastguard Worker 		goto out_free;
3271*436bf2bcSAndroid Build Coastguard Worker 
3272*436bf2bcSAndroid Build Coastguard Worker 	if (type == TEP_EVENT_OP)
3273*436bf2bcSAndroid Build Coastguard Worker 		type = process_op(event, arg, &token);
3274*436bf2bcSAndroid Build Coastguard Worker 
3275*436bf2bcSAndroid Build Coastguard Worker 	if (type == TEP_EVENT_ERROR)
3276*436bf2bcSAndroid Build Coastguard Worker 		goto out_free;
3277*436bf2bcSAndroid Build Coastguard Worker 
3278*436bf2bcSAndroid Build Coastguard Worker 	/*
3279*436bf2bcSAndroid Build Coastguard Worker 	 * If REC is surrounded by parenthesis, the process_arg()
3280*436bf2bcSAndroid Build Coastguard Worker 	 * will return TEP_EVENT_ITEM with token == ")". In
3281*436bf2bcSAndroid Build Coastguard Worker 	 * this case, we need to continue processing the item
3282*436bf2bcSAndroid Build Coastguard Worker 	 * and return.
3283*436bf2bcSAndroid Build Coastguard Worker 	 */
3284*436bf2bcSAndroid Build Coastguard Worker 	if (type == TEP_EVENT_ITEM && strcmp(token, ")") == 0) {
3285*436bf2bcSAndroid Build Coastguard Worker 		free_token(token);
3286*436bf2bcSAndroid Build Coastguard Worker 		return process_entry(event, arg, tok);
3287*436bf2bcSAndroid Build Coastguard Worker 	}
3288*436bf2bcSAndroid Build Coastguard Worker 
3289*436bf2bcSAndroid Build Coastguard Worker 	if (test_type_token(type, token, TEP_EVENT_DELIM, ")"))
3290*436bf2bcSAndroid Build Coastguard Worker 		goto out_free;
3291*436bf2bcSAndroid Build Coastguard Worker 
3292*436bf2bcSAndroid Build Coastguard Worker 	free_token(token);
3293*436bf2bcSAndroid Build Coastguard Worker 	type = read_token_item(event->tep, &token);
3294*436bf2bcSAndroid Build Coastguard Worker 
3295*436bf2bcSAndroid Build Coastguard Worker 	/*
3296*436bf2bcSAndroid Build Coastguard Worker 	 * If the next token is an item or another open paren, then
3297*436bf2bcSAndroid Build Coastguard Worker 	 * this was a typecast.
3298*436bf2bcSAndroid Build Coastguard Worker 	 */
3299*436bf2bcSAndroid Build Coastguard Worker 	if (event_item_type(type) ||
3300*436bf2bcSAndroid Build Coastguard Worker 	    (type == TEP_EVENT_DELIM && strcmp(token, "(") == 0)) {
3301*436bf2bcSAndroid Build Coastguard Worker 
3302*436bf2bcSAndroid Build Coastguard Worker 		/* make this a typecast and contine */
3303*436bf2bcSAndroid Build Coastguard Worker 
3304*436bf2bcSAndroid Build Coastguard Worker 		/* prevous must be an atom */
3305*436bf2bcSAndroid Build Coastguard Worker 		if (arg->type != TEP_PRINT_ATOM) {
3306*436bf2bcSAndroid Build Coastguard Worker 			do_warning_event(event, "previous needed to be TEP_PRINT_ATOM");
3307*436bf2bcSAndroid Build Coastguard Worker 			goto out_free;
3308*436bf2bcSAndroid Build Coastguard Worker 		}
3309*436bf2bcSAndroid Build Coastguard Worker 
3310*436bf2bcSAndroid Build Coastguard Worker 		item_arg = alloc_arg();
3311*436bf2bcSAndroid Build Coastguard Worker 		if (!item_arg) {
3312*436bf2bcSAndroid Build Coastguard Worker 			do_warning_event(event, "%s: not enough memory!",
3313*436bf2bcSAndroid Build Coastguard Worker 					 __func__);
3314*436bf2bcSAndroid Build Coastguard Worker 			goto out_free;
3315*436bf2bcSAndroid Build Coastguard Worker 		}
3316*436bf2bcSAndroid Build Coastguard Worker 
3317*436bf2bcSAndroid Build Coastguard Worker 		arg->type = TEP_PRINT_TYPE;
3318*436bf2bcSAndroid Build Coastguard Worker 		arg->typecast.type = arg->atom.atom;
3319*436bf2bcSAndroid Build Coastguard Worker 		arg->typecast.item = item_arg;
3320*436bf2bcSAndroid Build Coastguard Worker 		type = process_arg_token(event, item_arg, &token, type);
3321*436bf2bcSAndroid Build Coastguard Worker 
3322*436bf2bcSAndroid Build Coastguard Worker 	}
3323*436bf2bcSAndroid Build Coastguard Worker 
3324*436bf2bcSAndroid Build Coastguard Worker 	*tok = token;
3325*436bf2bcSAndroid Build Coastguard Worker 	return type;
3326*436bf2bcSAndroid Build Coastguard Worker 
3327*436bf2bcSAndroid Build Coastguard Worker  out_free:
3328*436bf2bcSAndroid Build Coastguard Worker 	free_token(token);
3329*436bf2bcSAndroid Build Coastguard Worker 	*tok = NULL;
3330*436bf2bcSAndroid Build Coastguard Worker 	return TEP_EVENT_ERROR;
3331*436bf2bcSAndroid Build Coastguard Worker }
3332*436bf2bcSAndroid Build Coastguard Worker 
3333*436bf2bcSAndroid Build Coastguard Worker 
3334*436bf2bcSAndroid Build Coastguard Worker static enum tep_event_type
process_str(struct tep_event * event,struct tep_print_arg * arg,char ** tok)3335*436bf2bcSAndroid Build Coastguard Worker process_str(struct tep_event *event, struct tep_print_arg *arg, char **tok)
3336*436bf2bcSAndroid Build Coastguard Worker {
3337*436bf2bcSAndroid Build Coastguard Worker 	enum tep_event_type type;
3338*436bf2bcSAndroid Build Coastguard Worker 	char *token;
3339*436bf2bcSAndroid Build Coastguard Worker 
3340*436bf2bcSAndroid Build Coastguard Worker 	if (read_expect_type(event->tep, TEP_EVENT_ITEM, &token) < 0)
3341*436bf2bcSAndroid Build Coastguard Worker 		goto out_free;
3342*436bf2bcSAndroid Build Coastguard Worker 
3343*436bf2bcSAndroid Build Coastguard Worker 	arg->type = TEP_PRINT_STRING;
3344*436bf2bcSAndroid Build Coastguard Worker 	arg->string.string = token;
3345*436bf2bcSAndroid Build Coastguard Worker 	arg->string.offset = -1;
3346*436bf2bcSAndroid Build Coastguard Worker 	arg->string.field = NULL;
3347*436bf2bcSAndroid Build Coastguard Worker 
3348*436bf2bcSAndroid Build Coastguard Worker 	if (read_expected(event->tep, TEP_EVENT_DELIM, ")") < 0)
3349*436bf2bcSAndroid Build Coastguard Worker 		goto out_err;
3350*436bf2bcSAndroid Build Coastguard Worker 
3351*436bf2bcSAndroid Build Coastguard Worker 	type = read_token(event->tep, &token);
3352*436bf2bcSAndroid Build Coastguard Worker 	*tok = token;
3353*436bf2bcSAndroid Build Coastguard Worker 
3354*436bf2bcSAndroid Build Coastguard Worker 	return type;
3355*436bf2bcSAndroid Build Coastguard Worker 
3356*436bf2bcSAndroid Build Coastguard Worker  out_free:
3357*436bf2bcSAndroid Build Coastguard Worker 	free_token(token);
3358*436bf2bcSAndroid Build Coastguard Worker  out_err:
3359*436bf2bcSAndroid Build Coastguard Worker 	*tok = NULL;
3360*436bf2bcSAndroid Build Coastguard Worker 	return TEP_EVENT_ERROR;
3361*436bf2bcSAndroid Build Coastguard Worker }
3362*436bf2bcSAndroid Build Coastguard Worker 
3363*436bf2bcSAndroid Build Coastguard Worker static enum tep_event_type
process_bitmask(struct tep_event * event,struct tep_print_arg * arg,char ** tok)3364*436bf2bcSAndroid Build Coastguard Worker process_bitmask(struct tep_event *event, struct tep_print_arg *arg, char **tok)
3365*436bf2bcSAndroid Build Coastguard Worker {
3366*436bf2bcSAndroid Build Coastguard Worker 	enum tep_event_type type;
3367*436bf2bcSAndroid Build Coastguard Worker 	char *token;
3368*436bf2bcSAndroid Build Coastguard Worker 
3369*436bf2bcSAndroid Build Coastguard Worker 	if (read_expect_type(event->tep, TEP_EVENT_ITEM, &token) < 0)
3370*436bf2bcSAndroid Build Coastguard Worker 		goto out_free;
3371*436bf2bcSAndroid Build Coastguard Worker 
3372*436bf2bcSAndroid Build Coastguard Worker 	arg->type = TEP_PRINT_BITMASK;
3373*436bf2bcSAndroid Build Coastguard Worker 	arg->bitmask.bitmask = token;
3374*436bf2bcSAndroid Build Coastguard Worker 	arg->bitmask.offset = -1;
3375*436bf2bcSAndroid Build Coastguard Worker 	arg->bitmask.field = NULL;
3376*436bf2bcSAndroid Build Coastguard Worker 
3377*436bf2bcSAndroid Build Coastguard Worker 	if (read_expected(event->tep, TEP_EVENT_DELIM, ")") < 0)
3378*436bf2bcSAndroid Build Coastguard Worker 		goto out_err;
3379*436bf2bcSAndroid Build Coastguard Worker 
3380*436bf2bcSAndroid Build Coastguard Worker 	type = read_token(event->tep, &token);
3381*436bf2bcSAndroid Build Coastguard Worker 	*tok = token;
3382*436bf2bcSAndroid Build Coastguard Worker 
3383*436bf2bcSAndroid Build Coastguard Worker 	return type;
3384*436bf2bcSAndroid Build Coastguard Worker 
3385*436bf2bcSAndroid Build Coastguard Worker  out_free:
3386*436bf2bcSAndroid Build Coastguard Worker 	free_token(token);
3387*436bf2bcSAndroid Build Coastguard Worker  out_err:
3388*436bf2bcSAndroid Build Coastguard Worker 	*tok = NULL;
3389*436bf2bcSAndroid Build Coastguard Worker 	return TEP_EVENT_ERROR;
3390*436bf2bcSAndroid Build Coastguard Worker }
3391*436bf2bcSAndroid Build Coastguard Worker 
3392*436bf2bcSAndroid Build Coastguard Worker static enum tep_event_type
process_cpumask(struct tep_event * event __maybe_unused,struct tep_print_arg * arg,char ** tok)3393*436bf2bcSAndroid Build Coastguard Worker process_cpumask(struct tep_event *event __maybe_unused, struct tep_print_arg *arg,
3394*436bf2bcSAndroid Build Coastguard Worker 		char **tok)
3395*436bf2bcSAndroid Build Coastguard Worker {
3396*436bf2bcSAndroid Build Coastguard Worker 	enum tep_event_type type = process_bitmask(event, arg, tok);
3397*436bf2bcSAndroid Build Coastguard Worker 	if (type != TEP_EVENT_ERROR)
3398*436bf2bcSAndroid Build Coastguard Worker 		arg->type = TEP_PRINT_CPUMASK;
3399*436bf2bcSAndroid Build Coastguard Worker 
3400*436bf2bcSAndroid Build Coastguard Worker 	return type;
3401*436bf2bcSAndroid Build Coastguard Worker }
3402*436bf2bcSAndroid Build Coastguard Worker 
3403*436bf2bcSAndroid Build Coastguard Worker static struct tep_function_handler *
find_func_handler(struct tep_handle * tep,char * func_name)3404*436bf2bcSAndroid Build Coastguard Worker find_func_handler(struct tep_handle *tep, char *func_name)
3405*436bf2bcSAndroid Build Coastguard Worker {
3406*436bf2bcSAndroid Build Coastguard Worker 	struct tep_function_handler *func;
3407*436bf2bcSAndroid Build Coastguard Worker 
3408*436bf2bcSAndroid Build Coastguard Worker 	if (!tep)
3409*436bf2bcSAndroid Build Coastguard Worker 		return NULL;
3410*436bf2bcSAndroid Build Coastguard Worker 
3411*436bf2bcSAndroid Build Coastguard Worker 	for (func = tep->func_handlers; func; func = func->next) {
3412*436bf2bcSAndroid Build Coastguard Worker 		if (strcmp(func->name, func_name) == 0)
3413*436bf2bcSAndroid Build Coastguard Worker 			break;
3414*436bf2bcSAndroid Build Coastguard Worker 	}
3415*436bf2bcSAndroid Build Coastguard Worker 
3416*436bf2bcSAndroid Build Coastguard Worker 	return func;
3417*436bf2bcSAndroid Build Coastguard Worker }
3418*436bf2bcSAndroid Build Coastguard Worker 
remove_func_handler(struct tep_handle * tep,char * func_name)3419*436bf2bcSAndroid Build Coastguard Worker static void remove_func_handler(struct tep_handle *tep, char *func_name)
3420*436bf2bcSAndroid Build Coastguard Worker {
3421*436bf2bcSAndroid Build Coastguard Worker 	struct tep_function_handler *func;
3422*436bf2bcSAndroid Build Coastguard Worker 	struct tep_function_handler **next;
3423*436bf2bcSAndroid Build Coastguard Worker 
3424*436bf2bcSAndroid Build Coastguard Worker 	next = &tep->func_handlers;
3425*436bf2bcSAndroid Build Coastguard Worker 	while ((func = *next)) {
3426*436bf2bcSAndroid Build Coastguard Worker 		if (strcmp(func->name, func_name) == 0) {
3427*436bf2bcSAndroid Build Coastguard Worker 			*next = func->next;
3428*436bf2bcSAndroid Build Coastguard Worker 			free_func_handle(func);
3429*436bf2bcSAndroid Build Coastguard Worker 			break;
3430*436bf2bcSAndroid Build Coastguard Worker 		}
3431*436bf2bcSAndroid Build Coastguard Worker 		next = &func->next;
3432*436bf2bcSAndroid Build Coastguard Worker 	}
3433*436bf2bcSAndroid Build Coastguard Worker }
3434*436bf2bcSAndroid Build Coastguard Worker 
3435*436bf2bcSAndroid Build Coastguard Worker static enum tep_event_type
process_func_handler(struct tep_event * event,struct tep_function_handler * func,struct tep_print_arg * arg,char ** tok)3436*436bf2bcSAndroid Build Coastguard Worker process_func_handler(struct tep_event *event, struct tep_function_handler *func,
3437*436bf2bcSAndroid Build Coastguard Worker 		     struct tep_print_arg *arg, char **tok)
3438*436bf2bcSAndroid Build Coastguard Worker {
3439*436bf2bcSAndroid Build Coastguard Worker 	struct tep_print_arg **next_arg;
3440*436bf2bcSAndroid Build Coastguard Worker 	struct tep_print_arg *farg;
3441*436bf2bcSAndroid Build Coastguard Worker 	enum tep_event_type type;
3442*436bf2bcSAndroid Build Coastguard Worker 	char *token;
3443*436bf2bcSAndroid Build Coastguard Worker 	int i;
3444*436bf2bcSAndroid Build Coastguard Worker 
3445*436bf2bcSAndroid Build Coastguard Worker 	arg->type = TEP_PRINT_FUNC;
3446*436bf2bcSAndroid Build Coastguard Worker 	arg->func.func = func;
3447*436bf2bcSAndroid Build Coastguard Worker 
3448*436bf2bcSAndroid Build Coastguard Worker 	*tok = NULL;
3449*436bf2bcSAndroid Build Coastguard Worker 
3450*436bf2bcSAndroid Build Coastguard Worker 	next_arg = &(arg->func.args);
3451*436bf2bcSAndroid Build Coastguard Worker 	for (i = 0; i < func->nr_args; i++) {
3452*436bf2bcSAndroid Build Coastguard Worker 		farg = alloc_arg();
3453*436bf2bcSAndroid Build Coastguard Worker 		if (!farg) {
3454*436bf2bcSAndroid Build Coastguard Worker 			do_warning_event(event, "%s: not enough memory!",
3455*436bf2bcSAndroid Build Coastguard Worker 					 __func__);
3456*436bf2bcSAndroid Build Coastguard Worker 			return TEP_EVENT_ERROR;
3457*436bf2bcSAndroid Build Coastguard Worker 		}
3458*436bf2bcSAndroid Build Coastguard Worker 
3459*436bf2bcSAndroid Build Coastguard Worker 		type = process_arg(event, farg, &token);
3460*436bf2bcSAndroid Build Coastguard Worker 		if (i < (func->nr_args - 1)) {
3461*436bf2bcSAndroid Build Coastguard Worker 			if (type != TEP_EVENT_DELIM || strcmp(token, ",") != 0) {
3462*436bf2bcSAndroid Build Coastguard Worker 				do_warning_event(event,
3463*436bf2bcSAndroid Build Coastguard Worker 					"Error: function '%s()' expects %d arguments but event %s only uses %d",
3464*436bf2bcSAndroid Build Coastguard Worker 					func->name, func->nr_args,
3465*436bf2bcSAndroid Build Coastguard Worker 					event->name, i + 1);
3466*436bf2bcSAndroid Build Coastguard Worker 				goto err;
3467*436bf2bcSAndroid Build Coastguard Worker 			}
3468*436bf2bcSAndroid Build Coastguard Worker 		} else {
3469*436bf2bcSAndroid Build Coastguard Worker 			if (type != TEP_EVENT_DELIM || strcmp(token, ")") != 0) {
3470*436bf2bcSAndroid Build Coastguard Worker 				do_warning_event(event,
3471*436bf2bcSAndroid Build Coastguard Worker 					"Error: function '%s()' only expects %d arguments but event %s has more",
3472*436bf2bcSAndroid Build Coastguard Worker 					func->name, func->nr_args, event->name);
3473*436bf2bcSAndroid Build Coastguard Worker 				goto err;
3474*436bf2bcSAndroid Build Coastguard Worker 			}
3475*436bf2bcSAndroid Build Coastguard Worker 		}
3476*436bf2bcSAndroid Build Coastguard Worker 
3477*436bf2bcSAndroid Build Coastguard Worker 		*next_arg = farg;
3478*436bf2bcSAndroid Build Coastguard Worker 		next_arg = &(farg->next);
3479*436bf2bcSAndroid Build Coastguard Worker 		free_token(token);
3480*436bf2bcSAndroid Build Coastguard Worker 	}
3481*436bf2bcSAndroid Build Coastguard Worker 
3482*436bf2bcSAndroid Build Coastguard Worker 	type = read_token(event->tep, &token);
3483*436bf2bcSAndroid Build Coastguard Worker 	*tok = token;
3484*436bf2bcSAndroid Build Coastguard Worker 
3485*436bf2bcSAndroid Build Coastguard Worker 	return type;
3486*436bf2bcSAndroid Build Coastguard Worker 
3487*436bf2bcSAndroid Build Coastguard Worker err:
3488*436bf2bcSAndroid Build Coastguard Worker 	free_arg(farg);
3489*436bf2bcSAndroid Build Coastguard Worker 	free_token(token);
3490*436bf2bcSAndroid Build Coastguard Worker 	return TEP_EVENT_ERROR;
3491*436bf2bcSAndroid Build Coastguard Worker }
3492*436bf2bcSAndroid Build Coastguard Worker 
3493*436bf2bcSAndroid Build Coastguard Worker static enum tep_event_type
process_builtin_expect(struct tep_event * event,struct tep_print_arg * arg,char ** tok)3494*436bf2bcSAndroid Build Coastguard Worker process_builtin_expect(struct tep_event *event, struct tep_print_arg *arg, char **tok)
3495*436bf2bcSAndroid Build Coastguard Worker {
3496*436bf2bcSAndroid Build Coastguard Worker 	enum tep_event_type type;
3497*436bf2bcSAndroid Build Coastguard Worker 	char *token = NULL;
3498*436bf2bcSAndroid Build Coastguard Worker 
3499*436bf2bcSAndroid Build Coastguard Worker 	/* Handle __builtin_expect( cond, #) */
3500*436bf2bcSAndroid Build Coastguard Worker 	type = process_arg(event, arg, &token);
3501*436bf2bcSAndroid Build Coastguard Worker 
3502*436bf2bcSAndroid Build Coastguard Worker 	if (type != TEP_EVENT_DELIM || token[0] != ',')
3503*436bf2bcSAndroid Build Coastguard Worker 		goto out_free;
3504*436bf2bcSAndroid Build Coastguard Worker 
3505*436bf2bcSAndroid Build Coastguard Worker 	free_token(token);
3506*436bf2bcSAndroid Build Coastguard Worker 
3507*436bf2bcSAndroid Build Coastguard Worker 	/* We don't care what the second parameter is of the __builtin_expect() */
3508*436bf2bcSAndroid Build Coastguard Worker 	if (read_expect_type(event->tep, TEP_EVENT_ITEM, &token) < 0)
3509*436bf2bcSAndroid Build Coastguard Worker 		goto out_free;
3510*436bf2bcSAndroid Build Coastguard Worker 
3511*436bf2bcSAndroid Build Coastguard Worker 	if (read_expected(event->tep, TEP_EVENT_DELIM, ")") < 0)
3512*436bf2bcSAndroid Build Coastguard Worker 		goto out_free;
3513*436bf2bcSAndroid Build Coastguard Worker 
3514*436bf2bcSAndroid Build Coastguard Worker 	free_token(token);
3515*436bf2bcSAndroid Build Coastguard Worker 	type = read_token_item(event->tep, tok);
3516*436bf2bcSAndroid Build Coastguard Worker 	return type;
3517*436bf2bcSAndroid Build Coastguard Worker 
3518*436bf2bcSAndroid Build Coastguard Worker out_free:
3519*436bf2bcSAndroid Build Coastguard Worker 	free_token(token);
3520*436bf2bcSAndroid Build Coastguard Worker 	*tok = NULL;
3521*436bf2bcSAndroid Build Coastguard Worker 	return TEP_EVENT_ERROR;
3522*436bf2bcSAndroid Build Coastguard Worker }
3523*436bf2bcSAndroid Build Coastguard Worker 
3524*436bf2bcSAndroid Build Coastguard Worker static enum tep_event_type
process_sizeof(struct tep_event * event,struct tep_print_arg * arg,char ** tok)3525*436bf2bcSAndroid Build Coastguard Worker process_sizeof(struct tep_event *event, struct tep_print_arg *arg, char **tok)
3526*436bf2bcSAndroid Build Coastguard Worker {
3527*436bf2bcSAndroid Build Coastguard Worker 	struct tep_format_field *field;
3528*436bf2bcSAndroid Build Coastguard Worker 	enum tep_event_type type;
3529*436bf2bcSAndroid Build Coastguard Worker 	char *token = NULL;
3530*436bf2bcSAndroid Build Coastguard Worker 	bool token_has_paren = false;
3531*436bf2bcSAndroid Build Coastguard Worker 	int ret;
3532*436bf2bcSAndroid Build Coastguard Worker 
3533*436bf2bcSAndroid Build Coastguard Worker 	type = read_token_item(event->tep, &token);
3534*436bf2bcSAndroid Build Coastguard Worker 
3535*436bf2bcSAndroid Build Coastguard Worker 	arg->type = TEP_PRINT_ATOM;
3536*436bf2bcSAndroid Build Coastguard Worker 
3537*436bf2bcSAndroid Build Coastguard Worker 	/* We handle some sizeof types */
3538*436bf2bcSAndroid Build Coastguard Worker 	if (strcmp(token, "unsigned") == 0) {
3539*436bf2bcSAndroid Build Coastguard Worker 		free_token(token);
3540*436bf2bcSAndroid Build Coastguard Worker 		type = read_token_item(event->tep, &token);
3541*436bf2bcSAndroid Build Coastguard Worker 
3542*436bf2bcSAndroid Build Coastguard Worker 		if (type == TEP_EVENT_ERROR)
3543*436bf2bcSAndroid Build Coastguard Worker 			goto error;
3544*436bf2bcSAndroid Build Coastguard Worker 
3545*436bf2bcSAndroid Build Coastguard Worker 		/* If it's not an item (like "long") then do not process more */
3546*436bf2bcSAndroid Build Coastguard Worker 		if (type != TEP_EVENT_ITEM)
3547*436bf2bcSAndroid Build Coastguard Worker 			token_has_paren = true;
3548*436bf2bcSAndroid Build Coastguard Worker 	}
3549*436bf2bcSAndroid Build Coastguard Worker 
3550*436bf2bcSAndroid Build Coastguard Worker 	if (token_has_paren || strcmp(token, "int") == 0) {
3551*436bf2bcSAndroid Build Coastguard Worker 		arg->atom.atom = strdup("4");
3552*436bf2bcSAndroid Build Coastguard Worker 
3553*436bf2bcSAndroid Build Coastguard Worker 	} else if (strcmp(token, "long") == 0) {
3554*436bf2bcSAndroid Build Coastguard Worker 		free_token(token);
3555*436bf2bcSAndroid Build Coastguard Worker 		type = read_token_item(event->tep, &token);
3556*436bf2bcSAndroid Build Coastguard Worker 
3557*436bf2bcSAndroid Build Coastguard Worker 		if (token && strcmp(token, "long") == 0) {
3558*436bf2bcSAndroid Build Coastguard Worker 			arg->atom.atom = strdup("8");
3559*436bf2bcSAndroid Build Coastguard Worker 		} else {
3560*436bf2bcSAndroid Build Coastguard Worker 			switch (event->tep->long_size) {
3561*436bf2bcSAndroid Build Coastguard Worker 			case 4:
3562*436bf2bcSAndroid Build Coastguard Worker 				arg->atom.atom = strdup("4");
3563*436bf2bcSAndroid Build Coastguard Worker 				break;
3564*436bf2bcSAndroid Build Coastguard Worker 			case 8:
3565*436bf2bcSAndroid Build Coastguard Worker 				arg->atom.atom = strdup("8");
3566*436bf2bcSAndroid Build Coastguard Worker 				break;
3567*436bf2bcSAndroid Build Coastguard Worker 			default:
3568*436bf2bcSAndroid Build Coastguard Worker 				/* long size not defined yet, fail to parse it */
3569*436bf2bcSAndroid Build Coastguard Worker 				goto error;
3570*436bf2bcSAndroid Build Coastguard Worker 			}
3571*436bf2bcSAndroid Build Coastguard Worker 			/* The token is the next token */
3572*436bf2bcSAndroid Build Coastguard Worker 			token_has_paren = true;
3573*436bf2bcSAndroid Build Coastguard Worker 		}
3574*436bf2bcSAndroid Build Coastguard Worker 
3575*436bf2bcSAndroid Build Coastguard Worker 	} else if (strcmp(token, "__u64") == 0 || strcmp(token, "u64") == 0 ||
3576*436bf2bcSAndroid Build Coastguard Worker 		   strcmp(token, "__s64") == 0 || strcmp(token, "s64") == 0) {
3577*436bf2bcSAndroid Build Coastguard Worker 		arg->atom.atom = strdup("8");
3578*436bf2bcSAndroid Build Coastguard Worker 
3579*436bf2bcSAndroid Build Coastguard Worker 	} else if (strcmp(token, "__u32") == 0 || strcmp(token, "u32") == 0 ||
3580*436bf2bcSAndroid Build Coastguard Worker 		   strcmp(token, "__s32") == 0 || strcmp(token, "s32") == 0) {
3581*436bf2bcSAndroid Build Coastguard Worker 		arg->atom.atom = strdup("4");
3582*436bf2bcSAndroid Build Coastguard Worker 
3583*436bf2bcSAndroid Build Coastguard Worker 	} else if (strcmp(token, "__u16") == 0 || strcmp(token, "u16") == 0 ||
3584*436bf2bcSAndroid Build Coastguard Worker 		   strcmp(token, "__s16") == 0 || strcmp(token, "s16") == 0) {
3585*436bf2bcSAndroid Build Coastguard Worker 		arg->atom.atom = strdup("2");
3586*436bf2bcSAndroid Build Coastguard Worker 
3587*436bf2bcSAndroid Build Coastguard Worker 	} else if (strcmp(token, "__u8") == 0 || strcmp(token, "u8") == 0 ||
3588*436bf2bcSAndroid Build Coastguard Worker 		   strcmp(token, "__8") == 0 || strcmp(token, "s8") == 0) {
3589*436bf2bcSAndroid Build Coastguard Worker 		arg->atom.atom = strdup("1");
3590*436bf2bcSAndroid Build Coastguard Worker 
3591*436bf2bcSAndroid Build Coastguard Worker 	} else if (strcmp(token, "REC") == 0) {
3592*436bf2bcSAndroid Build Coastguard Worker 
3593*436bf2bcSAndroid Build Coastguard Worker 		free_token(token);
3594*436bf2bcSAndroid Build Coastguard Worker 		type = read_token_item(event->tep, &token);
3595*436bf2bcSAndroid Build Coastguard Worker 
3596*436bf2bcSAndroid Build Coastguard Worker 		if (test_type_token(type, token,  TEP_EVENT_OP, "->"))
3597*436bf2bcSAndroid Build Coastguard Worker 			goto error;
3598*436bf2bcSAndroid Build Coastguard Worker 		free_token(token);
3599*436bf2bcSAndroid Build Coastguard Worker 
3600*436bf2bcSAndroid Build Coastguard Worker 		if (read_expect_type(event->tep, TEP_EVENT_ITEM, &token) < 0)
3601*436bf2bcSAndroid Build Coastguard Worker 			goto error;
3602*436bf2bcSAndroid Build Coastguard Worker 
3603*436bf2bcSAndroid Build Coastguard Worker 		field = tep_find_any_field(event, token);
3604*436bf2bcSAndroid Build Coastguard Worker 		/* Can't handle arrays (yet) */
3605*436bf2bcSAndroid Build Coastguard Worker 		if (!field || field->flags & TEP_FIELD_IS_ARRAY)
3606*436bf2bcSAndroid Build Coastguard Worker 			goto error;
3607*436bf2bcSAndroid Build Coastguard Worker 
3608*436bf2bcSAndroid Build Coastguard Worker 		ret = asprintf(&arg->atom.atom, "%d", field->size);
3609*436bf2bcSAndroid Build Coastguard Worker 		if (ret < 0)
3610*436bf2bcSAndroid Build Coastguard Worker 			goto error;
3611*436bf2bcSAndroid Build Coastguard Worker 
3612*436bf2bcSAndroid Build Coastguard Worker 	} else {
3613*436bf2bcSAndroid Build Coastguard Worker 		goto error;
3614*436bf2bcSAndroid Build Coastguard Worker 	}
3615*436bf2bcSAndroid Build Coastguard Worker 
3616*436bf2bcSAndroid Build Coastguard Worker 	if (!token_has_paren) {
3617*436bf2bcSAndroid Build Coastguard Worker 		/* The token contains the last item before the parenthesis */
3618*436bf2bcSAndroid Build Coastguard Worker 		free_token(token);
3619*436bf2bcSAndroid Build Coastguard Worker 		type = read_token_item(event->tep, &token);
3620*436bf2bcSAndroid Build Coastguard Worker 	}
3621*436bf2bcSAndroid Build Coastguard Worker 	if (test_type_token(type, token,  TEP_EVENT_DELIM, ")"))
3622*436bf2bcSAndroid Build Coastguard Worker 		goto error;
3623*436bf2bcSAndroid Build Coastguard Worker 
3624*436bf2bcSAndroid Build Coastguard Worker 	free_token(token);
3625*436bf2bcSAndroid Build Coastguard Worker 	return read_token_item(event->tep, tok);
3626*436bf2bcSAndroid Build Coastguard Worker error:
3627*436bf2bcSAndroid Build Coastguard Worker 	free_token(token);
3628*436bf2bcSAndroid Build Coastguard Worker 	*tok = NULL;
3629*436bf2bcSAndroid Build Coastguard Worker 	return TEP_EVENT_ERROR;
3630*436bf2bcSAndroid Build Coastguard Worker }
3631*436bf2bcSAndroid Build Coastguard Worker 
3632*436bf2bcSAndroid Build Coastguard Worker static enum tep_event_type
process_function(struct tep_event * event,struct tep_print_arg * arg,char * token,char ** tok)3633*436bf2bcSAndroid Build Coastguard Worker process_function(struct tep_event *event, struct tep_print_arg *arg,
3634*436bf2bcSAndroid Build Coastguard Worker 		 char *token, char **tok)
3635*436bf2bcSAndroid Build Coastguard Worker {
3636*436bf2bcSAndroid Build Coastguard Worker 	struct tep_function_handler *func;
3637*436bf2bcSAndroid Build Coastguard Worker 
3638*436bf2bcSAndroid Build Coastguard Worker 	if (strcmp(token, "__print_flags") == 0) {
3639*436bf2bcSAndroid Build Coastguard Worker 		free_token(token);
3640*436bf2bcSAndroid Build Coastguard Worker 		is_flag_field = 1;
3641*436bf2bcSAndroid Build Coastguard Worker 		return process_flags(event, arg, tok);
3642*436bf2bcSAndroid Build Coastguard Worker 	}
3643*436bf2bcSAndroid Build Coastguard Worker 	if (strcmp(token, "__print_symbolic") == 0) {
3644*436bf2bcSAndroid Build Coastguard Worker 		free_token(token);
3645*436bf2bcSAndroid Build Coastguard Worker 		is_symbolic_field = 1;
3646*436bf2bcSAndroid Build Coastguard Worker 		return process_symbols(event, arg, tok);
3647*436bf2bcSAndroid Build Coastguard Worker 	}
3648*436bf2bcSAndroid Build Coastguard Worker 	if (strcmp(token, "__print_hex") == 0) {
3649*436bf2bcSAndroid Build Coastguard Worker 		free_token(token);
3650*436bf2bcSAndroid Build Coastguard Worker 		return process_hex(event, arg, tok);
3651*436bf2bcSAndroid Build Coastguard Worker 	}
3652*436bf2bcSAndroid Build Coastguard Worker 	if (strcmp(token, "__print_hex_str") == 0) {
3653*436bf2bcSAndroid Build Coastguard Worker 		free_token(token);
3654*436bf2bcSAndroid Build Coastguard Worker 		return process_hex_str(event, arg, tok);
3655*436bf2bcSAndroid Build Coastguard Worker 	}
3656*436bf2bcSAndroid Build Coastguard Worker 	if (strcmp(token, "__print_array") == 0) {
3657*436bf2bcSAndroid Build Coastguard Worker 		free_token(token);
3658*436bf2bcSAndroid Build Coastguard Worker 		return process_int_array(event, arg, tok);
3659*436bf2bcSAndroid Build Coastguard Worker 	}
3660*436bf2bcSAndroid Build Coastguard Worker 	if (strcmp(token, "__get_str") == 0 ||
3661*436bf2bcSAndroid Build Coastguard Worker 	    strcmp(token, "__get_rel_str") == 0) {
3662*436bf2bcSAndroid Build Coastguard Worker 		free_token(token);
3663*436bf2bcSAndroid Build Coastguard Worker 		return process_str(event, arg, tok);
3664*436bf2bcSAndroid Build Coastguard Worker 	}
3665*436bf2bcSAndroid Build Coastguard Worker 	if (strcmp(token, "__get_bitmask") == 0 ||
3666*436bf2bcSAndroid Build Coastguard Worker 	    strcmp(token, "__get_rel_bitmask") == 0) {
3667*436bf2bcSAndroid Build Coastguard Worker 		free_token(token);
3668*436bf2bcSAndroid Build Coastguard Worker 		return process_bitmask(event, arg, tok);
3669*436bf2bcSAndroid Build Coastguard Worker 	}
3670*436bf2bcSAndroid Build Coastguard Worker 	if (strcmp(token, "__get_cpumask") == 0 ||
3671*436bf2bcSAndroid Build Coastguard Worker 	    strcmp(token, "__get_rel_cpumask") == 0) {
3672*436bf2bcSAndroid Build Coastguard Worker 		free_token(token);
3673*436bf2bcSAndroid Build Coastguard Worker 		return process_cpumask(event, arg, tok);
3674*436bf2bcSAndroid Build Coastguard Worker 	}
3675*436bf2bcSAndroid Build Coastguard Worker 	if (strcmp(token, "__get_dynamic_array") == 0 ||
3676*436bf2bcSAndroid Build Coastguard Worker 	    strcmp(token, "__get_rel_dynamic_array") == 0 ||
3677*436bf2bcSAndroid Build Coastguard Worker 	    strcmp(token, "__get_sockaddr") == 0 ||
3678*436bf2bcSAndroid Build Coastguard Worker 	    strcmp(token, "__get_sockaddr_rel") == 0) {
3679*436bf2bcSAndroid Build Coastguard Worker 		free_token(token);
3680*436bf2bcSAndroid Build Coastguard Worker 		return process_dynamic_array(event, arg, tok);
3681*436bf2bcSAndroid Build Coastguard Worker 	}
3682*436bf2bcSAndroid Build Coastguard Worker 	if (strcmp(token, "__get_dynamic_array_len") == 0 ||
3683*436bf2bcSAndroid Build Coastguard Worker 	    strcmp(token, "__get_rel_dynamic_array_len") == 0) {
3684*436bf2bcSAndroid Build Coastguard Worker 		free_token(token);
3685*436bf2bcSAndroid Build Coastguard Worker 		return process_dynamic_array_len(event, arg, tok);
3686*436bf2bcSAndroid Build Coastguard Worker 	}
3687*436bf2bcSAndroid Build Coastguard Worker 	if (strcmp(token, "__builtin_expect") == 0) {
3688*436bf2bcSAndroid Build Coastguard Worker 		free_token(token);
3689*436bf2bcSAndroid Build Coastguard Worker 		return process_builtin_expect(event, arg, tok);
3690*436bf2bcSAndroid Build Coastguard Worker 	}
3691*436bf2bcSAndroid Build Coastguard Worker 	if (strcmp(token, "sizeof") == 0) {
3692*436bf2bcSAndroid Build Coastguard Worker 		free_token(token);
3693*436bf2bcSAndroid Build Coastguard Worker 		return process_sizeof(event, arg, tok);
3694*436bf2bcSAndroid Build Coastguard Worker 	}
3695*436bf2bcSAndroid Build Coastguard Worker 
3696*436bf2bcSAndroid Build Coastguard Worker 	func = find_func_handler(event->tep, token);
3697*436bf2bcSAndroid Build Coastguard Worker 	if (func) {
3698*436bf2bcSAndroid Build Coastguard Worker 		free_token(token);
3699*436bf2bcSAndroid Build Coastguard Worker 		return process_func_handler(event, func, arg, tok);
3700*436bf2bcSAndroid Build Coastguard Worker 	}
3701*436bf2bcSAndroid Build Coastguard Worker 
3702*436bf2bcSAndroid Build Coastguard Worker 	do_warning_event(event, "function %s not defined", token);
3703*436bf2bcSAndroid Build Coastguard Worker 	free_token(token);
3704*436bf2bcSAndroid Build Coastguard Worker 	return TEP_EVENT_ERROR;
3705*436bf2bcSAndroid Build Coastguard Worker }
3706*436bf2bcSAndroid Build Coastguard Worker 
3707*436bf2bcSAndroid Build Coastguard Worker static enum tep_event_type
process_arg_token(struct tep_event * event,struct tep_print_arg * arg,char ** tok,enum tep_event_type type)3708*436bf2bcSAndroid Build Coastguard Worker process_arg_token(struct tep_event *event, struct tep_print_arg *arg,
3709*436bf2bcSAndroid Build Coastguard Worker 		  char **tok, enum tep_event_type type)
3710*436bf2bcSAndroid Build Coastguard Worker {
3711*436bf2bcSAndroid Build Coastguard Worker 	char *token;
3712*436bf2bcSAndroid Build Coastguard Worker 	char *atom;
3713*436bf2bcSAndroid Build Coastguard Worker 
3714*436bf2bcSAndroid Build Coastguard Worker 	token = *tok;
3715*436bf2bcSAndroid Build Coastguard Worker 
3716*436bf2bcSAndroid Build Coastguard Worker 	switch (type) {
3717*436bf2bcSAndroid Build Coastguard Worker 	case TEP_EVENT_ITEM:
3718*436bf2bcSAndroid Build Coastguard Worker 		if (strcmp(token, "REC") == 0) {
3719*436bf2bcSAndroid Build Coastguard Worker 			free_token(token);
3720*436bf2bcSAndroid Build Coastguard Worker 			type = process_entry(event, arg, &token);
3721*436bf2bcSAndroid Build Coastguard Worker 			break;
3722*436bf2bcSAndroid Build Coastguard Worker 		}
3723*436bf2bcSAndroid Build Coastguard Worker 		atom = token;
3724*436bf2bcSAndroid Build Coastguard Worker 		/* test the next token */
3725*436bf2bcSAndroid Build Coastguard Worker 		type = read_token_item(event->tep, &token);
3726*436bf2bcSAndroid Build Coastguard Worker 
3727*436bf2bcSAndroid Build Coastguard Worker 		/*
3728*436bf2bcSAndroid Build Coastguard Worker 		 * If the next token is a parenthesis, then this
3729*436bf2bcSAndroid Build Coastguard Worker 		 * is a function.
3730*436bf2bcSAndroid Build Coastguard Worker 		 */
3731*436bf2bcSAndroid Build Coastguard Worker 		if (type == TEP_EVENT_DELIM && strcmp(token, "(") == 0) {
3732*436bf2bcSAndroid Build Coastguard Worker 			free_token(token);
3733*436bf2bcSAndroid Build Coastguard Worker 			token = NULL;
3734*436bf2bcSAndroid Build Coastguard Worker 			/* this will free atom. */
3735*436bf2bcSAndroid Build Coastguard Worker 			type = process_function(event, arg, atom, &token);
3736*436bf2bcSAndroid Build Coastguard Worker 			break;
3737*436bf2bcSAndroid Build Coastguard Worker 		}
3738*436bf2bcSAndroid Build Coastguard Worker 		/* atoms can be more than one token long */
3739*436bf2bcSAndroid Build Coastguard Worker 		while (type == TEP_EVENT_ITEM) {
3740*436bf2bcSAndroid Build Coastguard Worker 			int ret;
3741*436bf2bcSAndroid Build Coastguard Worker 
3742*436bf2bcSAndroid Build Coastguard Worker 			ret = append(&atom, " ", token);
3743*436bf2bcSAndroid Build Coastguard Worker 			if (ret < 0) {
3744*436bf2bcSAndroid Build Coastguard Worker 				free(atom);
3745*436bf2bcSAndroid Build Coastguard Worker 				*tok = NULL;
3746*436bf2bcSAndroid Build Coastguard Worker 				free_token(token);
3747*436bf2bcSAndroid Build Coastguard Worker 				return TEP_EVENT_ERROR;
3748*436bf2bcSAndroid Build Coastguard Worker 			}
3749*436bf2bcSAndroid Build Coastguard Worker 			free_token(token);
3750*436bf2bcSAndroid Build Coastguard Worker 			type = read_token_item(event->tep, &token);
3751*436bf2bcSAndroid Build Coastguard Worker 		}
3752*436bf2bcSAndroid Build Coastguard Worker 
3753*436bf2bcSAndroid Build Coastguard Worker 		arg->type = TEP_PRINT_ATOM;
3754*436bf2bcSAndroid Build Coastguard Worker 		arg->atom.atom = atom;
3755*436bf2bcSAndroid Build Coastguard Worker 		break;
3756*436bf2bcSAndroid Build Coastguard Worker 
3757*436bf2bcSAndroid Build Coastguard Worker 	case TEP_EVENT_SQUOTE:
3758*436bf2bcSAndroid Build Coastguard Worker 		arg->type = TEP_PRINT_ATOM;
3759*436bf2bcSAndroid Build Coastguard Worker 		/* Make characters into numbers */
3760*436bf2bcSAndroid Build Coastguard Worker 		if (asprintf(&arg->atom.atom, "%d", token[0]) < 0) {
3761*436bf2bcSAndroid Build Coastguard Worker 			free_token(token);
3762*436bf2bcSAndroid Build Coastguard Worker 			*tok = NULL;
3763*436bf2bcSAndroid Build Coastguard Worker 			arg->atom.atom = NULL;
3764*436bf2bcSAndroid Build Coastguard Worker 			return TEP_EVENT_ERROR;
3765*436bf2bcSAndroid Build Coastguard Worker 		}
3766*436bf2bcSAndroid Build Coastguard Worker 		free_token(token);
3767*436bf2bcSAndroid Build Coastguard Worker 		type = read_token_item(event->tep, &token);
3768*436bf2bcSAndroid Build Coastguard Worker 		break;
3769*436bf2bcSAndroid Build Coastguard Worker 	case TEP_EVENT_DQUOTE:
3770*436bf2bcSAndroid Build Coastguard Worker 		arg->type = TEP_PRINT_ATOM;
3771*436bf2bcSAndroid Build Coastguard Worker 		arg->atom.atom = token;
3772*436bf2bcSAndroid Build Coastguard Worker 		type = read_token_item(event->tep, &token);
3773*436bf2bcSAndroid Build Coastguard Worker 		break;
3774*436bf2bcSAndroid Build Coastguard Worker 	case TEP_EVENT_DELIM:
3775*436bf2bcSAndroid Build Coastguard Worker 		if (strcmp(token, "(") == 0) {
3776*436bf2bcSAndroid Build Coastguard Worker 			free_token(token);
3777*436bf2bcSAndroid Build Coastguard Worker 			type = process_paren(event, arg, &token);
3778*436bf2bcSAndroid Build Coastguard Worker 			break;
3779*436bf2bcSAndroid Build Coastguard Worker 		}
3780*436bf2bcSAndroid Build Coastguard Worker 	case TEP_EVENT_OP:
3781*436bf2bcSAndroid Build Coastguard Worker 		/* handle single ops */
3782*436bf2bcSAndroid Build Coastguard Worker 		arg->type = TEP_PRINT_OP;
3783*436bf2bcSAndroid Build Coastguard Worker 		arg->op.op = token;
3784*436bf2bcSAndroid Build Coastguard Worker 		arg->op.left = NULL;
3785*436bf2bcSAndroid Build Coastguard Worker 		type = process_op(event, arg, &token);
3786*436bf2bcSAndroid Build Coastguard Worker 
3787*436bf2bcSAndroid Build Coastguard Worker 		/* On error, the op is freed */
3788*436bf2bcSAndroid Build Coastguard Worker 		if (type == TEP_EVENT_ERROR)
3789*436bf2bcSAndroid Build Coastguard Worker 			arg->op.op = NULL;
3790*436bf2bcSAndroid Build Coastguard Worker 
3791*436bf2bcSAndroid Build Coastguard Worker 		/* return error type if errored */
3792*436bf2bcSAndroid Build Coastguard Worker 		break;
3793*436bf2bcSAndroid Build Coastguard Worker 
3794*436bf2bcSAndroid Build Coastguard Worker 	case TEP_EVENT_ERROR ... TEP_EVENT_NEWLINE:
3795*436bf2bcSAndroid Build Coastguard Worker 	default:
3796*436bf2bcSAndroid Build Coastguard Worker 		do_warning_event(event, "unexpected type %d", type);
3797*436bf2bcSAndroid Build Coastguard Worker 		return TEP_EVENT_ERROR;
3798*436bf2bcSAndroid Build Coastguard Worker 	}
3799*436bf2bcSAndroid Build Coastguard Worker 	*tok = token;
3800*436bf2bcSAndroid Build Coastguard Worker 
3801*436bf2bcSAndroid Build Coastguard Worker 	return type;
3802*436bf2bcSAndroid Build Coastguard Worker }
3803*436bf2bcSAndroid Build Coastguard Worker 
event_read_print_args(struct tep_event * event,struct tep_print_arg ** list)3804*436bf2bcSAndroid Build Coastguard Worker static int event_read_print_args(struct tep_event *event, struct tep_print_arg **list)
3805*436bf2bcSAndroid Build Coastguard Worker {
3806*436bf2bcSAndroid Build Coastguard Worker 	enum tep_event_type type = TEP_EVENT_ERROR;
3807*436bf2bcSAndroid Build Coastguard Worker 	struct tep_print_arg *arg;
3808*436bf2bcSAndroid Build Coastguard Worker 	char *token;
3809*436bf2bcSAndroid Build Coastguard Worker 	int args = 0;
3810*436bf2bcSAndroid Build Coastguard Worker 
3811*436bf2bcSAndroid Build Coastguard Worker 	do {
3812*436bf2bcSAndroid Build Coastguard Worker 		if (type == TEP_EVENT_NEWLINE) {
3813*436bf2bcSAndroid Build Coastguard Worker 			type = read_token_item(event->tep, &token);
3814*436bf2bcSAndroid Build Coastguard Worker 			continue;
3815*436bf2bcSAndroid Build Coastguard Worker 		}
3816*436bf2bcSAndroid Build Coastguard Worker 
3817*436bf2bcSAndroid Build Coastguard Worker 		arg = alloc_arg();
3818*436bf2bcSAndroid Build Coastguard Worker 		if (!arg) {
3819*436bf2bcSAndroid Build Coastguard Worker 			do_warning_event(event, "%s: not enough memory!",
3820*436bf2bcSAndroid Build Coastguard Worker 					 __func__);
3821*436bf2bcSAndroid Build Coastguard Worker 			return -1;
3822*436bf2bcSAndroid Build Coastguard Worker 		}
3823*436bf2bcSAndroid Build Coastguard Worker 
3824*436bf2bcSAndroid Build Coastguard Worker 		type = process_arg(event, arg, &token);
3825*436bf2bcSAndroid Build Coastguard Worker 
3826*436bf2bcSAndroid Build Coastguard Worker 		if (type == TEP_EVENT_ERROR) {
3827*436bf2bcSAndroid Build Coastguard Worker 			free_token(token);
3828*436bf2bcSAndroid Build Coastguard Worker 			free_arg(arg);
3829*436bf2bcSAndroid Build Coastguard Worker 			return -1;
3830*436bf2bcSAndroid Build Coastguard Worker 		}
3831*436bf2bcSAndroid Build Coastguard Worker 
3832*436bf2bcSAndroid Build Coastguard Worker 		*list = arg;
3833*436bf2bcSAndroid Build Coastguard Worker 		args++;
3834*436bf2bcSAndroid Build Coastguard Worker 
3835*436bf2bcSAndroid Build Coastguard Worker 		if (type == TEP_EVENT_OP) {
3836*436bf2bcSAndroid Build Coastguard Worker 			type = process_op(event, arg, &token);
3837*436bf2bcSAndroid Build Coastguard Worker 			free_token(token);
3838*436bf2bcSAndroid Build Coastguard Worker 
3839*436bf2bcSAndroid Build Coastguard Worker 			if (consolidate_op_arg(type, arg) < 0)
3840*436bf2bcSAndroid Build Coastguard Worker 				type = TEP_EVENT_ERROR;
3841*436bf2bcSAndroid Build Coastguard Worker 
3842*436bf2bcSAndroid Build Coastguard Worker 			if (type == TEP_EVENT_ERROR) {
3843*436bf2bcSAndroid Build Coastguard Worker 				*list = NULL;
3844*436bf2bcSAndroid Build Coastguard Worker 				free_arg(arg);
3845*436bf2bcSAndroid Build Coastguard Worker 				return -1;
3846*436bf2bcSAndroid Build Coastguard Worker 			}
3847*436bf2bcSAndroid Build Coastguard Worker 			list = &arg->next;
3848*436bf2bcSAndroid Build Coastguard Worker 			continue;
3849*436bf2bcSAndroid Build Coastguard Worker 		}
3850*436bf2bcSAndroid Build Coastguard Worker 
3851*436bf2bcSAndroid Build Coastguard Worker 		if (type == TEP_EVENT_DELIM && strcmp(token, ",") == 0) {
3852*436bf2bcSAndroid Build Coastguard Worker 			free_token(token);
3853*436bf2bcSAndroid Build Coastguard Worker 			*list = arg;
3854*436bf2bcSAndroid Build Coastguard Worker 			list = &arg->next;
3855*436bf2bcSAndroid Build Coastguard Worker 			continue;
3856*436bf2bcSAndroid Build Coastguard Worker 		}
3857*436bf2bcSAndroid Build Coastguard Worker 		break;
3858*436bf2bcSAndroid Build Coastguard Worker 	} while (type != TEP_EVENT_NONE);
3859*436bf2bcSAndroid Build Coastguard Worker 
3860*436bf2bcSAndroid Build Coastguard Worker 	if (type != TEP_EVENT_NONE && type != TEP_EVENT_ERROR)
3861*436bf2bcSAndroid Build Coastguard Worker 		free_token(token);
3862*436bf2bcSAndroid Build Coastguard Worker 
3863*436bf2bcSAndroid Build Coastguard Worker 	return args;
3864*436bf2bcSAndroid Build Coastguard Worker }
3865*436bf2bcSAndroid Build Coastguard Worker 
event_read_print(struct tep_event * event)3866*436bf2bcSAndroid Build Coastguard Worker static int event_read_print(struct tep_event *event)
3867*436bf2bcSAndroid Build Coastguard Worker {
3868*436bf2bcSAndroid Build Coastguard Worker 	enum tep_event_type type;
3869*436bf2bcSAndroid Build Coastguard Worker 	char *token;
3870*436bf2bcSAndroid Build Coastguard Worker 	int ret;
3871*436bf2bcSAndroid Build Coastguard Worker 
3872*436bf2bcSAndroid Build Coastguard Worker 	if (read_expected_item(event->tep, TEP_EVENT_ITEM, "print") < 0)
3873*436bf2bcSAndroid Build Coastguard Worker 		return -1;
3874*436bf2bcSAndroid Build Coastguard Worker 
3875*436bf2bcSAndroid Build Coastguard Worker 	if (read_expected(event->tep, TEP_EVENT_ITEM, "fmt") < 0)
3876*436bf2bcSAndroid Build Coastguard Worker 		return -1;
3877*436bf2bcSAndroid Build Coastguard Worker 
3878*436bf2bcSAndroid Build Coastguard Worker 	if (read_expected(event->tep, TEP_EVENT_OP, ":") < 0)
3879*436bf2bcSAndroid Build Coastguard Worker 		return -1;
3880*436bf2bcSAndroid Build Coastguard Worker 
3881*436bf2bcSAndroid Build Coastguard Worker 	if (read_expect_type(event->tep, TEP_EVENT_DQUOTE, &token) < 0)
3882*436bf2bcSAndroid Build Coastguard Worker 		goto fail;
3883*436bf2bcSAndroid Build Coastguard Worker 
3884*436bf2bcSAndroid Build Coastguard Worker  concat:
3885*436bf2bcSAndroid Build Coastguard Worker 	event->print_fmt.format = token;
3886*436bf2bcSAndroid Build Coastguard Worker 	event->print_fmt.args = NULL;
3887*436bf2bcSAndroid Build Coastguard Worker 
3888*436bf2bcSAndroid Build Coastguard Worker 	/* ok to have no arg */
3889*436bf2bcSAndroid Build Coastguard Worker 	type = read_token_item(event->tep, &token);
3890*436bf2bcSAndroid Build Coastguard Worker 
3891*436bf2bcSAndroid Build Coastguard Worker 	if (type == TEP_EVENT_NONE)
3892*436bf2bcSAndroid Build Coastguard Worker 		return 0;
3893*436bf2bcSAndroid Build Coastguard Worker 
3894*436bf2bcSAndroid Build Coastguard Worker 	/* Handle concatenation of print lines */
3895*436bf2bcSAndroid Build Coastguard Worker 	if (type == TEP_EVENT_DQUOTE) {
3896*436bf2bcSAndroid Build Coastguard Worker 		char *cat;
3897*436bf2bcSAndroid Build Coastguard Worker 
3898*436bf2bcSAndroid Build Coastguard Worker 		if (asprintf(&cat, "%s%s", event->print_fmt.format, token) < 0)
3899*436bf2bcSAndroid Build Coastguard Worker 			goto fail;
3900*436bf2bcSAndroid Build Coastguard Worker 		free_token(token);
3901*436bf2bcSAndroid Build Coastguard Worker 		free_token(event->print_fmt.format);
3902*436bf2bcSAndroid Build Coastguard Worker 		event->print_fmt.format = NULL;
3903*436bf2bcSAndroid Build Coastguard Worker 		token = cat;
3904*436bf2bcSAndroid Build Coastguard Worker 		goto concat;
3905*436bf2bcSAndroid Build Coastguard Worker 	}
3906*436bf2bcSAndroid Build Coastguard Worker 
3907*436bf2bcSAndroid Build Coastguard Worker 	if (test_type_token(type, token, TEP_EVENT_DELIM, ","))
3908*436bf2bcSAndroid Build Coastguard Worker 		goto fail;
3909*436bf2bcSAndroid Build Coastguard Worker 
3910*436bf2bcSAndroid Build Coastguard Worker 	free_token(token);
3911*436bf2bcSAndroid Build Coastguard Worker 
3912*436bf2bcSAndroid Build Coastguard Worker 	ret = event_read_print_args(event, &event->print_fmt.args);
3913*436bf2bcSAndroid Build Coastguard Worker 	if (ret < 0)
3914*436bf2bcSAndroid Build Coastguard Worker 		return -1;
3915*436bf2bcSAndroid Build Coastguard Worker 
3916*436bf2bcSAndroid Build Coastguard Worker 	return ret;
3917*436bf2bcSAndroid Build Coastguard Worker 
3918*436bf2bcSAndroid Build Coastguard Worker  fail:
3919*436bf2bcSAndroid Build Coastguard Worker 	free_token(token);
3920*436bf2bcSAndroid Build Coastguard Worker 	return -1;
3921*436bf2bcSAndroid Build Coastguard Worker }
3922*436bf2bcSAndroid Build Coastguard Worker 
3923*436bf2bcSAndroid Build Coastguard Worker /**
3924*436bf2bcSAndroid Build Coastguard Worker  * tep_find_common_field - return a common field by event
3925*436bf2bcSAndroid Build Coastguard Worker  * @event: handle for the event
3926*436bf2bcSAndroid Build Coastguard Worker  * @name: the name of the common field to return
3927*436bf2bcSAndroid Build Coastguard Worker  *
3928*436bf2bcSAndroid Build Coastguard Worker  * Returns a common field from the event by the given @name.
3929*436bf2bcSAndroid Build Coastguard Worker  * This only searches the common fields and not all field.
3930*436bf2bcSAndroid Build Coastguard Worker  */
3931*436bf2bcSAndroid Build Coastguard Worker struct tep_format_field *
tep_find_common_field(struct tep_event * event,const char * name)3932*436bf2bcSAndroid Build Coastguard Worker tep_find_common_field(struct tep_event *event, const char *name)
3933*436bf2bcSAndroid Build Coastguard Worker {
3934*436bf2bcSAndroid Build Coastguard Worker 	struct tep_format_field *format;
3935*436bf2bcSAndroid Build Coastguard Worker 
3936*436bf2bcSAndroid Build Coastguard Worker 	for (format = event->format.common_fields;
3937*436bf2bcSAndroid Build Coastguard Worker 	     format; format = format->next) {
3938*436bf2bcSAndroid Build Coastguard Worker 		if (strcmp(format->name, name) == 0)
3939*436bf2bcSAndroid Build Coastguard Worker 			break;
3940*436bf2bcSAndroid Build Coastguard Worker 	}
3941*436bf2bcSAndroid Build Coastguard Worker 
3942*436bf2bcSAndroid Build Coastguard Worker 	return format;
3943*436bf2bcSAndroid Build Coastguard Worker }
3944*436bf2bcSAndroid Build Coastguard Worker 
3945*436bf2bcSAndroid Build Coastguard Worker /**
3946*436bf2bcSAndroid Build Coastguard Worker  * tep_find_field - find a non-common field
3947*436bf2bcSAndroid Build Coastguard Worker  * @event: handle for the event
3948*436bf2bcSAndroid Build Coastguard Worker  * @name: the name of the non-common field
3949*436bf2bcSAndroid Build Coastguard Worker  *
3950*436bf2bcSAndroid Build Coastguard Worker  * Returns a non-common field by the given @name.
3951*436bf2bcSAndroid Build Coastguard Worker  * This does not search common fields.
3952*436bf2bcSAndroid Build Coastguard Worker  */
3953*436bf2bcSAndroid Build Coastguard Worker struct tep_format_field *
tep_find_field(struct tep_event * event,const char * name)3954*436bf2bcSAndroid Build Coastguard Worker tep_find_field(struct tep_event *event, const char *name)
3955*436bf2bcSAndroid Build Coastguard Worker {
3956*436bf2bcSAndroid Build Coastguard Worker 	struct tep_format_field *format;
3957*436bf2bcSAndroid Build Coastguard Worker 
3958*436bf2bcSAndroid Build Coastguard Worker 	for (format = event->format.fields;
3959*436bf2bcSAndroid Build Coastguard Worker 	     format; format = format->next) {
3960*436bf2bcSAndroid Build Coastguard Worker 		if (strcmp(format->name, name) == 0)
3961*436bf2bcSAndroid Build Coastguard Worker 			break;
3962*436bf2bcSAndroid Build Coastguard Worker 	}
3963*436bf2bcSAndroid Build Coastguard Worker 
3964*436bf2bcSAndroid Build Coastguard Worker 	return format;
3965*436bf2bcSAndroid Build Coastguard Worker }
3966*436bf2bcSAndroid Build Coastguard Worker 
3967*436bf2bcSAndroid Build Coastguard Worker /**
3968*436bf2bcSAndroid Build Coastguard Worker  * tep_find_any_field - find any field by name
3969*436bf2bcSAndroid Build Coastguard Worker  * @event: handle for the event
3970*436bf2bcSAndroid Build Coastguard Worker  * @name: the name of the field
3971*436bf2bcSAndroid Build Coastguard Worker  *
3972*436bf2bcSAndroid Build Coastguard Worker  * Returns a field by the given @name.
3973*436bf2bcSAndroid Build Coastguard Worker  * This searches the common field names first, then
3974*436bf2bcSAndroid Build Coastguard Worker  * the non-common ones if a common one was not found.
3975*436bf2bcSAndroid Build Coastguard Worker  */
3976*436bf2bcSAndroid Build Coastguard Worker struct tep_format_field *
tep_find_any_field(struct tep_event * event,const char * name)3977*436bf2bcSAndroid Build Coastguard Worker tep_find_any_field(struct tep_event *event, const char *name)
3978*436bf2bcSAndroid Build Coastguard Worker {
3979*436bf2bcSAndroid Build Coastguard Worker 	struct tep_format_field *format;
3980*436bf2bcSAndroid Build Coastguard Worker 
3981*436bf2bcSAndroid Build Coastguard Worker 	format = tep_find_common_field(event, name);
3982*436bf2bcSAndroid Build Coastguard Worker 	if (format)
3983*436bf2bcSAndroid Build Coastguard Worker 		return format;
3984*436bf2bcSAndroid Build Coastguard Worker 	return tep_find_field(event, name);
3985*436bf2bcSAndroid Build Coastguard Worker }
3986*436bf2bcSAndroid Build Coastguard Worker 
3987*436bf2bcSAndroid Build Coastguard Worker /**
3988*436bf2bcSAndroid Build Coastguard Worker  * tep_read_number - read a number from data
3989*436bf2bcSAndroid Build Coastguard Worker  * @tep: a handle to the trace event parser context
3990*436bf2bcSAndroid Build Coastguard Worker  * @ptr: the raw data
3991*436bf2bcSAndroid Build Coastguard Worker  * @size: the size of the data that holds the number
3992*436bf2bcSAndroid Build Coastguard Worker  *
3993*436bf2bcSAndroid Build Coastguard Worker  * Returns the number (converted to host) from the
3994*436bf2bcSAndroid Build Coastguard Worker  * raw data.
3995*436bf2bcSAndroid Build Coastguard Worker  */
tep_read_number(struct tep_handle * tep,const void * ptr,int size)3996*436bf2bcSAndroid Build Coastguard Worker unsigned long long tep_read_number(struct tep_handle *tep,
3997*436bf2bcSAndroid Build Coastguard Worker 				   const void *ptr, int size)
3998*436bf2bcSAndroid Build Coastguard Worker {
3999*436bf2bcSAndroid Build Coastguard Worker 	unsigned long long val;
4000*436bf2bcSAndroid Build Coastguard Worker 
4001*436bf2bcSAndroid Build Coastguard Worker 	switch (size) {
4002*436bf2bcSAndroid Build Coastguard Worker 	case 1:
4003*436bf2bcSAndroid Build Coastguard Worker 		return *(unsigned char *)ptr;
4004*436bf2bcSAndroid Build Coastguard Worker 	case 2:
4005*436bf2bcSAndroid Build Coastguard Worker 		return data2host2(tep, *(unsigned short *)ptr);
4006*436bf2bcSAndroid Build Coastguard Worker 	case 4:
4007*436bf2bcSAndroid Build Coastguard Worker 		return data2host4(tep, *(unsigned int *)ptr);
4008*436bf2bcSAndroid Build Coastguard Worker 	case 8:
4009*436bf2bcSAndroid Build Coastguard Worker 		memcpy(&val, (ptr), sizeof(unsigned long long));
4010*436bf2bcSAndroid Build Coastguard Worker 		return data2host8(tep, val);
4011*436bf2bcSAndroid Build Coastguard Worker 	default:
4012*436bf2bcSAndroid Build Coastguard Worker 		/* BUG! */
4013*436bf2bcSAndroid Build Coastguard Worker 		return 0;
4014*436bf2bcSAndroid Build Coastguard Worker 	}
4015*436bf2bcSAndroid Build Coastguard Worker }
4016*436bf2bcSAndroid Build Coastguard Worker 
4017*436bf2bcSAndroid Build Coastguard Worker /**
4018*436bf2bcSAndroid Build Coastguard Worker  * tep_read_number_field - read a number from data
4019*436bf2bcSAndroid Build Coastguard Worker  * @field: a handle to the field
4020*436bf2bcSAndroid Build Coastguard Worker  * @data: the raw data to read
4021*436bf2bcSAndroid Build Coastguard Worker  * @value: the value to place the number in
4022*436bf2bcSAndroid Build Coastguard Worker  *
4023*436bf2bcSAndroid Build Coastguard Worker  * Reads raw data according to a field offset and size,
4024*436bf2bcSAndroid Build Coastguard Worker  * and translates it into @value.
4025*436bf2bcSAndroid Build Coastguard Worker  *
4026*436bf2bcSAndroid Build Coastguard Worker  * Returns 0 on success, -1 otherwise.
4027*436bf2bcSAndroid Build Coastguard Worker  */
tep_read_number_field(struct tep_format_field * field,const void * data,unsigned long long * value)4028*436bf2bcSAndroid Build Coastguard Worker int tep_read_number_field(struct tep_format_field *field, const void *data,
4029*436bf2bcSAndroid Build Coastguard Worker 			  unsigned long long *value)
4030*436bf2bcSAndroid Build Coastguard Worker {
4031*436bf2bcSAndroid Build Coastguard Worker 	if (!field)
4032*436bf2bcSAndroid Build Coastguard Worker 		return -1;
4033*436bf2bcSAndroid Build Coastguard Worker 	switch (field->size) {
4034*436bf2bcSAndroid Build Coastguard Worker 	case 1:
4035*436bf2bcSAndroid Build Coastguard Worker 	case 2:
4036*436bf2bcSAndroid Build Coastguard Worker 	case 4:
4037*436bf2bcSAndroid Build Coastguard Worker 	case 8:
4038*436bf2bcSAndroid Build Coastguard Worker 		*value = tep_read_number(field->event->tep,
4039*436bf2bcSAndroid Build Coastguard Worker 					 data + field->offset, field->size);
4040*436bf2bcSAndroid Build Coastguard Worker 		return 0;
4041*436bf2bcSAndroid Build Coastguard Worker 	default:
4042*436bf2bcSAndroid Build Coastguard Worker 		return -1;
4043*436bf2bcSAndroid Build Coastguard Worker 	}
4044*436bf2bcSAndroid Build Coastguard Worker }
4045*436bf2bcSAndroid Build Coastguard Worker 
get_common_info(struct tep_handle * tep,const char * type,int * offset,int * size)4046*436bf2bcSAndroid Build Coastguard Worker static int get_common_info(struct tep_handle *tep,
4047*436bf2bcSAndroid Build Coastguard Worker 			   const char *type, int *offset, int *size)
4048*436bf2bcSAndroid Build Coastguard Worker {
4049*436bf2bcSAndroid Build Coastguard Worker 	struct tep_event *event;
4050*436bf2bcSAndroid Build Coastguard Worker 	struct tep_format_field *field;
4051*436bf2bcSAndroid Build Coastguard Worker 
4052*436bf2bcSAndroid Build Coastguard Worker 	/*
4053*436bf2bcSAndroid Build Coastguard Worker 	 * All events should have the same common elements.
4054*436bf2bcSAndroid Build Coastguard Worker 	 * Pick any event to find where the type is;
4055*436bf2bcSAndroid Build Coastguard Worker 	 */
4056*436bf2bcSAndroid Build Coastguard Worker 	if (!tep->events) {
4057*436bf2bcSAndroid Build Coastguard Worker 		do_warning("no event_list!");
4058*436bf2bcSAndroid Build Coastguard Worker 		return -1;
4059*436bf2bcSAndroid Build Coastguard Worker 	}
4060*436bf2bcSAndroid Build Coastguard Worker 
4061*436bf2bcSAndroid Build Coastguard Worker 	event = tep->events[0];
4062*436bf2bcSAndroid Build Coastguard Worker 	field = tep_find_common_field(event, type);
4063*436bf2bcSAndroid Build Coastguard Worker 	if (!field)
4064*436bf2bcSAndroid Build Coastguard Worker 		return -1;
4065*436bf2bcSAndroid Build Coastguard Worker 
4066*436bf2bcSAndroid Build Coastguard Worker 	*offset = field->offset;
4067*436bf2bcSAndroid Build Coastguard Worker 	*size = field->size;
4068*436bf2bcSAndroid Build Coastguard Worker 
4069*436bf2bcSAndroid Build Coastguard Worker 	return 0;
4070*436bf2bcSAndroid Build Coastguard Worker }
4071*436bf2bcSAndroid Build Coastguard Worker 
__parse_common(struct tep_handle * tep,void * data,int * size,int * offset,const char * name)4072*436bf2bcSAndroid Build Coastguard Worker static int __parse_common(struct tep_handle *tep, void *data,
4073*436bf2bcSAndroid Build Coastguard Worker 			  int *size, int *offset, const char *name)
4074*436bf2bcSAndroid Build Coastguard Worker {
4075*436bf2bcSAndroid Build Coastguard Worker 	int ret;
4076*436bf2bcSAndroid Build Coastguard Worker 
4077*436bf2bcSAndroid Build Coastguard Worker 	if (!*size) {
4078*436bf2bcSAndroid Build Coastguard Worker 		ret = get_common_info(tep, name, offset, size);
4079*436bf2bcSAndroid Build Coastguard Worker 		if (ret < 0)
4080*436bf2bcSAndroid Build Coastguard Worker 			return ret;
4081*436bf2bcSAndroid Build Coastguard Worker 	}
4082*436bf2bcSAndroid Build Coastguard Worker 	return tep_read_number(tep, data + *offset, *size);
4083*436bf2bcSAndroid Build Coastguard Worker }
4084*436bf2bcSAndroid Build Coastguard Worker 
trace_parse_common_type(struct tep_handle * tep,void * data)4085*436bf2bcSAndroid Build Coastguard Worker static int trace_parse_common_type(struct tep_handle *tep, void *data)
4086*436bf2bcSAndroid Build Coastguard Worker {
4087*436bf2bcSAndroid Build Coastguard Worker 	return __parse_common(tep, data,
4088*436bf2bcSAndroid Build Coastguard Worker 			      &tep->type_size, &tep->type_offset,
4089*436bf2bcSAndroid Build Coastguard Worker 			      "common_type");
4090*436bf2bcSAndroid Build Coastguard Worker }
4091*436bf2bcSAndroid Build Coastguard Worker 
parse_common_pid(struct tep_handle * tep,void * data)4092*436bf2bcSAndroid Build Coastguard Worker static int parse_common_pid(struct tep_handle *tep, void *data)
4093*436bf2bcSAndroid Build Coastguard Worker {
4094*436bf2bcSAndroid Build Coastguard Worker 	return __parse_common(tep, data,
4095*436bf2bcSAndroid Build Coastguard Worker 			      &tep->pid_size, &tep->pid_offset,
4096*436bf2bcSAndroid Build Coastguard Worker 			      "common_pid");
4097*436bf2bcSAndroid Build Coastguard Worker }
4098*436bf2bcSAndroid Build Coastguard Worker 
parse_common_pc(struct tep_handle * tep,void * data)4099*436bf2bcSAndroid Build Coastguard Worker static int parse_common_pc(struct tep_handle *tep, void *data)
4100*436bf2bcSAndroid Build Coastguard Worker {
4101*436bf2bcSAndroid Build Coastguard Worker 	return __parse_common(tep, data,
4102*436bf2bcSAndroid Build Coastguard Worker 			      &tep->pc_size, &tep->pc_offset,
4103*436bf2bcSAndroid Build Coastguard Worker 			      "common_preempt_count");
4104*436bf2bcSAndroid Build Coastguard Worker }
4105*436bf2bcSAndroid Build Coastguard Worker 
parse_common_flags(struct tep_handle * tep,void * data)4106*436bf2bcSAndroid Build Coastguard Worker static int parse_common_flags(struct tep_handle *tep, void *data)
4107*436bf2bcSAndroid Build Coastguard Worker {
4108*436bf2bcSAndroid Build Coastguard Worker 	return __parse_common(tep, data,
4109*436bf2bcSAndroid Build Coastguard Worker 			      &tep->flags_size, &tep->flags_offset,
4110*436bf2bcSAndroid Build Coastguard Worker 			      "common_flags");
4111*436bf2bcSAndroid Build Coastguard Worker }
4112*436bf2bcSAndroid Build Coastguard Worker 
parse_common_lock_depth(struct tep_handle * tep,void * data)4113*436bf2bcSAndroid Build Coastguard Worker static int parse_common_lock_depth(struct tep_handle *tep, void *data)
4114*436bf2bcSAndroid Build Coastguard Worker {
4115*436bf2bcSAndroid Build Coastguard Worker 	return __parse_common(tep, data,
4116*436bf2bcSAndroid Build Coastguard Worker 			      &tep->ld_size, &tep->ld_offset,
4117*436bf2bcSAndroid Build Coastguard Worker 			      "common_lock_depth");
4118*436bf2bcSAndroid Build Coastguard Worker }
4119*436bf2bcSAndroid Build Coastguard Worker 
parse_common_migrate_disable(struct tep_handle * tep,void * data)4120*436bf2bcSAndroid Build Coastguard Worker static int parse_common_migrate_disable(struct tep_handle *tep, void *data)
4121*436bf2bcSAndroid Build Coastguard Worker {
4122*436bf2bcSAndroid Build Coastguard Worker 	return __parse_common(tep, data,
4123*436bf2bcSAndroid Build Coastguard Worker 			      &tep->ld_size, &tep->ld_offset,
4124*436bf2bcSAndroid Build Coastguard Worker 			      "common_migrate_disable");
4125*436bf2bcSAndroid Build Coastguard Worker }
4126*436bf2bcSAndroid Build Coastguard Worker 
4127*436bf2bcSAndroid Build Coastguard Worker static int events_id_cmp(const void *a, const void *b);
4128*436bf2bcSAndroid Build Coastguard Worker 
4129*436bf2bcSAndroid Build Coastguard Worker /**
4130*436bf2bcSAndroid Build Coastguard Worker  * tep_find_event - find an event by given id
4131*436bf2bcSAndroid Build Coastguard Worker  * @tep: a handle to the trace event parser context
4132*436bf2bcSAndroid Build Coastguard Worker  * @id: the id of the event
4133*436bf2bcSAndroid Build Coastguard Worker  *
4134*436bf2bcSAndroid Build Coastguard Worker  * Returns an event that has a given @id.
4135*436bf2bcSAndroid Build Coastguard Worker  */
tep_find_event(struct tep_handle * tep,int id)4136*436bf2bcSAndroid Build Coastguard Worker struct tep_event *tep_find_event(struct tep_handle *tep, int id)
4137*436bf2bcSAndroid Build Coastguard Worker {
4138*436bf2bcSAndroid Build Coastguard Worker 	struct tep_event **eventptr;
4139*436bf2bcSAndroid Build Coastguard Worker 	struct tep_event key;
4140*436bf2bcSAndroid Build Coastguard Worker 	struct tep_event *pkey = &key;
4141*436bf2bcSAndroid Build Coastguard Worker 
4142*436bf2bcSAndroid Build Coastguard Worker 	/* Check cache first */
4143*436bf2bcSAndroid Build Coastguard Worker 	if (tep->last_event && tep->last_event->id == id)
4144*436bf2bcSAndroid Build Coastguard Worker 		return tep->last_event;
4145*436bf2bcSAndroid Build Coastguard Worker 
4146*436bf2bcSAndroid Build Coastguard Worker 	key.id = id;
4147*436bf2bcSAndroid Build Coastguard Worker 
4148*436bf2bcSAndroid Build Coastguard Worker 	eventptr = bsearch(&pkey, tep->events, tep->nr_events,
4149*436bf2bcSAndroid Build Coastguard Worker 			   sizeof(*tep->events), events_id_cmp);
4150*436bf2bcSAndroid Build Coastguard Worker 
4151*436bf2bcSAndroid Build Coastguard Worker 	if (eventptr) {
4152*436bf2bcSAndroid Build Coastguard Worker 		tep->last_event = *eventptr;
4153*436bf2bcSAndroid Build Coastguard Worker 		return *eventptr;
4154*436bf2bcSAndroid Build Coastguard Worker 	}
4155*436bf2bcSAndroid Build Coastguard Worker 
4156*436bf2bcSAndroid Build Coastguard Worker 	return NULL;
4157*436bf2bcSAndroid Build Coastguard Worker }
4158*436bf2bcSAndroid Build Coastguard Worker 
4159*436bf2bcSAndroid Build Coastguard Worker /**
4160*436bf2bcSAndroid Build Coastguard Worker  * tep_find_event_by_name - find an event by given name
4161*436bf2bcSAndroid Build Coastguard Worker  * @tep: a handle to the trace event parser context
4162*436bf2bcSAndroid Build Coastguard Worker  * @sys: the system name to search for
4163*436bf2bcSAndroid Build Coastguard Worker  * @name: the name of the event to search for
4164*436bf2bcSAndroid Build Coastguard Worker  *
4165*436bf2bcSAndroid Build Coastguard Worker  * This returns an event with a given @name and under the system
4166*436bf2bcSAndroid Build Coastguard Worker  * @sys. If @sys is NULL the first event with @name is returned.
4167*436bf2bcSAndroid Build Coastguard Worker  */
4168*436bf2bcSAndroid Build Coastguard Worker struct tep_event *
tep_find_event_by_name(struct tep_handle * tep,const char * sys,const char * name)4169*436bf2bcSAndroid Build Coastguard Worker tep_find_event_by_name(struct tep_handle *tep,
4170*436bf2bcSAndroid Build Coastguard Worker 		       const char *sys, const char *name)
4171*436bf2bcSAndroid Build Coastguard Worker {
4172*436bf2bcSAndroid Build Coastguard Worker 	struct tep_event *event = NULL;
4173*436bf2bcSAndroid Build Coastguard Worker 	int i;
4174*436bf2bcSAndroid Build Coastguard Worker 
4175*436bf2bcSAndroid Build Coastguard Worker 	if (tep->last_event &&
4176*436bf2bcSAndroid Build Coastguard Worker 	    strcmp(tep->last_event->name, name) == 0 &&
4177*436bf2bcSAndroid Build Coastguard Worker 	    (!sys || strcmp(tep->last_event->system, sys) == 0))
4178*436bf2bcSAndroid Build Coastguard Worker 		return tep->last_event;
4179*436bf2bcSAndroid Build Coastguard Worker 
4180*436bf2bcSAndroid Build Coastguard Worker 	for (i = 0; i < tep->nr_events; i++) {
4181*436bf2bcSAndroid Build Coastguard Worker 		event = tep->events[i];
4182*436bf2bcSAndroid Build Coastguard Worker 		if (strcmp(event->name, name) == 0) {
4183*436bf2bcSAndroid Build Coastguard Worker 			if (!sys)
4184*436bf2bcSAndroid Build Coastguard Worker 				break;
4185*436bf2bcSAndroid Build Coastguard Worker 			if (strcmp(event->system, sys) == 0)
4186*436bf2bcSAndroid Build Coastguard Worker 				break;
4187*436bf2bcSAndroid Build Coastguard Worker 		}
4188*436bf2bcSAndroid Build Coastguard Worker 	}
4189*436bf2bcSAndroid Build Coastguard Worker 	if (i == tep->nr_events)
4190*436bf2bcSAndroid Build Coastguard Worker 		event = NULL;
4191*436bf2bcSAndroid Build Coastguard Worker 
4192*436bf2bcSAndroid Build Coastguard Worker 	tep->last_event = event;
4193*436bf2bcSAndroid Build Coastguard Worker 	return event;
4194*436bf2bcSAndroid Build Coastguard Worker }
4195*436bf2bcSAndroid Build Coastguard Worker 
test_for_symbol(struct tep_handle * tep,struct tep_print_arg * arg)4196*436bf2bcSAndroid Build Coastguard Worker static unsigned long long test_for_symbol(struct tep_handle *tep,
4197*436bf2bcSAndroid Build Coastguard Worker 					  struct tep_print_arg *arg)
4198*436bf2bcSAndroid Build Coastguard Worker {
4199*436bf2bcSAndroid Build Coastguard Worker 	unsigned long long val = 0;
4200*436bf2bcSAndroid Build Coastguard Worker 	struct func_list *item = tep->funclist;
4201*436bf2bcSAndroid Build Coastguard Worker 	char *func;
4202*436bf2bcSAndroid Build Coastguard Worker 	int i;
4203*436bf2bcSAndroid Build Coastguard Worker 
4204*436bf2bcSAndroid Build Coastguard Worker 	if (isdigit(arg->atom.atom[0]))
4205*436bf2bcSAndroid Build Coastguard Worker 		return 0;
4206*436bf2bcSAndroid Build Coastguard Worker 
4207*436bf2bcSAndroid Build Coastguard Worker 	/* Linear search but only happens once (see after the loop) */
4208*436bf2bcSAndroid Build Coastguard Worker 	for (i = 0; i < (int)tep->func_count; i++) {
4209*436bf2bcSAndroid Build Coastguard Worker 		unsigned long long addr;
4210*436bf2bcSAndroid Build Coastguard Worker 		const char *name;
4211*436bf2bcSAndroid Build Coastguard Worker 
4212*436bf2bcSAndroid Build Coastguard Worker 		if (tep->func_map) {
4213*436bf2bcSAndroid Build Coastguard Worker 			addr = tep->func_map[i].addr;
4214*436bf2bcSAndroid Build Coastguard Worker 			name = tep->func_map[i].func;
4215*436bf2bcSAndroid Build Coastguard Worker 		} else if (item) {
4216*436bf2bcSAndroid Build Coastguard Worker 			addr = item->addr;
4217*436bf2bcSAndroid Build Coastguard Worker 			name = item->func;
4218*436bf2bcSAndroid Build Coastguard Worker 			item = item->next;
4219*436bf2bcSAndroid Build Coastguard Worker 		} else
4220*436bf2bcSAndroid Build Coastguard Worker 			break;
4221*436bf2bcSAndroid Build Coastguard Worker 
4222*436bf2bcSAndroid Build Coastguard Worker 		if (strcmp(arg->atom.atom, name) == 0) {
4223*436bf2bcSAndroid Build Coastguard Worker 			val = addr;
4224*436bf2bcSAndroid Build Coastguard Worker 			break;
4225*436bf2bcSAndroid Build Coastguard Worker 		}
4226*436bf2bcSAndroid Build Coastguard Worker 	}
4227*436bf2bcSAndroid Build Coastguard Worker 
4228*436bf2bcSAndroid Build Coastguard Worker 	/*
4229*436bf2bcSAndroid Build Coastguard Worker 	 * This modifies the arg to hardcode the value
4230*436bf2bcSAndroid Build Coastguard Worker 	 * and will not loop again.
4231*436bf2bcSAndroid Build Coastguard Worker 	 */
4232*436bf2bcSAndroid Build Coastguard Worker 	func = realloc(arg->atom.atom, 32);
4233*436bf2bcSAndroid Build Coastguard Worker 	if (func) {
4234*436bf2bcSAndroid Build Coastguard Worker 		snprintf(func, 32, "%lld", val);
4235*436bf2bcSAndroid Build Coastguard Worker 		arg->atom.atom = func;
4236*436bf2bcSAndroid Build Coastguard Worker 	}
4237*436bf2bcSAndroid Build Coastguard Worker 	return val;
4238*436bf2bcSAndroid Build Coastguard Worker }
4239*436bf2bcSAndroid Build Coastguard Worker 
4240*436bf2bcSAndroid Build Coastguard Worker #define TEP_OFFSET_LEN_MASK		0xffff
4241*436bf2bcSAndroid Build Coastguard Worker #define TEP_LEN_SHIFT			16
4242*436bf2bcSAndroid Build Coastguard Worker 
dynamic_offset(struct tep_handle * tep,int size,void * data,int data_size,unsigned int * offset,unsigned int * len)4243*436bf2bcSAndroid Build Coastguard Worker static void dynamic_offset(struct tep_handle *tep, int size, void *data,
4244*436bf2bcSAndroid Build Coastguard Worker 			   int data_size, unsigned int *offset, unsigned int *len)
4245*436bf2bcSAndroid Build Coastguard Worker {
4246*436bf2bcSAndroid Build Coastguard Worker 	unsigned long long val;
4247*436bf2bcSAndroid Build Coastguard Worker 	unsigned int o, l;
4248*436bf2bcSAndroid Build Coastguard Worker 
4249*436bf2bcSAndroid Build Coastguard Worker 	/*
4250*436bf2bcSAndroid Build Coastguard Worker 	 * The total allocated length of the dynamic array is
4251*436bf2bcSAndroid Build Coastguard Worker 	 * stored in the top half of the field and the offset
4252*436bf2bcSAndroid Build Coastguard Worker 	 * is in the bottom half of the 32 bit field.
4253*436bf2bcSAndroid Build Coastguard Worker 	 */
4254*436bf2bcSAndroid Build Coastguard Worker 	val = tep_read_number(tep, data, size);
4255*436bf2bcSAndroid Build Coastguard Worker 
4256*436bf2bcSAndroid Build Coastguard Worker 	/* Check for overflows */
4257*436bf2bcSAndroid Build Coastguard Worker 	o = (unsigned int)(val & TEP_OFFSET_LEN_MASK);
4258*436bf2bcSAndroid Build Coastguard Worker 
4259*436bf2bcSAndroid Build Coastguard Worker 	/* If there's no length, then just make the length the size of the data */
4260*436bf2bcSAndroid Build Coastguard Worker 	if (size == 2)
4261*436bf2bcSAndroid Build Coastguard Worker 		l = data_size - o;
4262*436bf2bcSAndroid Build Coastguard Worker 	else
4263*436bf2bcSAndroid Build Coastguard Worker 		l = (unsigned int)((val >> TEP_LEN_SHIFT) & TEP_OFFSET_LEN_MASK);
4264*436bf2bcSAndroid Build Coastguard Worker 
4265*436bf2bcSAndroid Build Coastguard Worker 	if (offset)
4266*436bf2bcSAndroid Build Coastguard Worker 		*offset = o > data_size ? 0 : o;
4267*436bf2bcSAndroid Build Coastguard Worker 	if (len)
4268*436bf2bcSAndroid Build Coastguard Worker 		*len = o + l > data_size ? 0 : l;
4269*436bf2bcSAndroid Build Coastguard Worker }
4270*436bf2bcSAndroid Build Coastguard Worker 
dynamic_offset_field(struct tep_handle * tep,struct tep_format_field * field,void * data,int size,unsigned int * offset,unsigned int * len)4271*436bf2bcSAndroid Build Coastguard Worker static inline void dynamic_offset_field(struct tep_handle *tep,
4272*436bf2bcSAndroid Build Coastguard Worker 					struct tep_format_field *field,
4273*436bf2bcSAndroid Build Coastguard Worker 					void *data, int size,
4274*436bf2bcSAndroid Build Coastguard Worker 					unsigned int *offset,
4275*436bf2bcSAndroid Build Coastguard Worker 					unsigned int *len)
4276*436bf2bcSAndroid Build Coastguard Worker {
4277*436bf2bcSAndroid Build Coastguard Worker 	/* Test for overflow */
4278*436bf2bcSAndroid Build Coastguard Worker 	if (field->offset + field->size > size) {
4279*436bf2bcSAndroid Build Coastguard Worker 		if (offset)
4280*436bf2bcSAndroid Build Coastguard Worker 			*offset = 0;
4281*436bf2bcSAndroid Build Coastguard Worker 		if (len)
4282*436bf2bcSAndroid Build Coastguard Worker 			*len = 0;
4283*436bf2bcSAndroid Build Coastguard Worker 		return;
4284*436bf2bcSAndroid Build Coastguard Worker 	}
4285*436bf2bcSAndroid Build Coastguard Worker 	dynamic_offset(tep, field->size, data + field->offset, size, offset, len);
4286*436bf2bcSAndroid Build Coastguard Worker 	if (field->flags & TEP_FIELD_IS_RELATIVE)
4287*436bf2bcSAndroid Build Coastguard Worker 		*offset += field->offset + field->size;
4288*436bf2bcSAndroid Build Coastguard Worker }
4289*436bf2bcSAndroid Build Coastguard Worker 
check_data_offset_size(struct tep_event * event,const char * field_name,int data_size,int field_offset,int field_size)4290*436bf2bcSAndroid Build Coastguard Worker static bool check_data_offset_size(struct tep_event *event, const char *field_name,
4291*436bf2bcSAndroid Build Coastguard Worker 				    int data_size, int field_offset, int field_size)
4292*436bf2bcSAndroid Build Coastguard Worker {
4293*436bf2bcSAndroid Build Coastguard Worker 	/* Check to make sure the field is within the data */
4294*436bf2bcSAndroid Build Coastguard Worker 	if (field_offset + field_size <= data_size)
4295*436bf2bcSAndroid Build Coastguard Worker 		return false;
4296*436bf2bcSAndroid Build Coastguard Worker 
4297*436bf2bcSAndroid Build Coastguard Worker 	tep_warning("Event '%s' field '%s' goes beyond the size of the event (%d > %d)",
4298*436bf2bcSAndroid Build Coastguard Worker 		    event->name, field_name, field_offset + field_size, data_size);
4299*436bf2bcSAndroid Build Coastguard Worker 	return true;
4300*436bf2bcSAndroid Build Coastguard Worker }
4301*436bf2bcSAndroid Build Coastguard Worker 
4302*436bf2bcSAndroid Build Coastguard Worker static unsigned long long
eval_num_arg(void * data,int size,struct tep_event * event,struct tep_print_arg * arg)4303*436bf2bcSAndroid Build Coastguard Worker eval_num_arg(void *data, int size, struct tep_event *event, struct tep_print_arg *arg)
4304*436bf2bcSAndroid Build Coastguard Worker {
4305*436bf2bcSAndroid Build Coastguard Worker 	struct tep_handle *tep = event->tep;
4306*436bf2bcSAndroid Build Coastguard Worker 	unsigned long long val = 0;
4307*436bf2bcSAndroid Build Coastguard Worker 	unsigned long long left, right;
4308*436bf2bcSAndroid Build Coastguard Worker 	struct tep_print_arg *typearg = NULL;
4309*436bf2bcSAndroid Build Coastguard Worker 	struct tep_print_arg *larg;
4310*436bf2bcSAndroid Build Coastguard Worker 	unsigned int offset;
4311*436bf2bcSAndroid Build Coastguard Worker 	unsigned int field_size;
4312*436bf2bcSAndroid Build Coastguard Worker 
4313*436bf2bcSAndroid Build Coastguard Worker 	switch (arg->type) {
4314*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_NULL:
4315*436bf2bcSAndroid Build Coastguard Worker 		/* ?? */
4316*436bf2bcSAndroid Build Coastguard Worker 		return 0;
4317*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_ATOM:
4318*436bf2bcSAndroid Build Coastguard Worker 		val = strtoull(arg->atom.atom, NULL, 0);
4319*436bf2bcSAndroid Build Coastguard Worker 		if (!val)
4320*436bf2bcSAndroid Build Coastguard Worker 			val = test_for_symbol(tep, arg);
4321*436bf2bcSAndroid Build Coastguard Worker 		return val;
4322*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_FIELD:
4323*436bf2bcSAndroid Build Coastguard Worker 		if (!arg->field.field) {
4324*436bf2bcSAndroid Build Coastguard Worker 			arg->field.field = tep_find_any_field(event, arg->field.name);
4325*436bf2bcSAndroid Build Coastguard Worker 			if (!arg->field.field)
4326*436bf2bcSAndroid Build Coastguard Worker 				goto out_warning_field;
4327*436bf2bcSAndroid Build Coastguard Worker 		}
4328*436bf2bcSAndroid Build Coastguard Worker 		if (check_data_offset_size(event, arg->field.name, size,
4329*436bf2bcSAndroid Build Coastguard Worker 					   arg->field.field->offset,
4330*436bf2bcSAndroid Build Coastguard Worker 					   arg->field.field->size)) {
4331*436bf2bcSAndroid Build Coastguard Worker 			val = 0;
4332*436bf2bcSAndroid Build Coastguard Worker 			break;
4333*436bf2bcSAndroid Build Coastguard Worker 		}
4334*436bf2bcSAndroid Build Coastguard Worker 		/* must be a number */
4335*436bf2bcSAndroid Build Coastguard Worker 		val = tep_read_number(tep, data + arg->field.field->offset,
4336*436bf2bcSAndroid Build Coastguard Worker 				      arg->field.field->size);
4337*436bf2bcSAndroid Build Coastguard Worker 		break;
4338*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_FLAGS:
4339*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_SYMBOL:
4340*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_INT_ARRAY:
4341*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_HEX:
4342*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_HEX_STR:
4343*436bf2bcSAndroid Build Coastguard Worker 		break;
4344*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_TYPE:
4345*436bf2bcSAndroid Build Coastguard Worker 		val = eval_num_arg(data, size, event, arg->typecast.item);
4346*436bf2bcSAndroid Build Coastguard Worker 		return eval_type(val, arg, 0);
4347*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_STRING:
4348*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_BSTRING:
4349*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_BITMASK:
4350*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_CPUMASK:
4351*436bf2bcSAndroid Build Coastguard Worker 		return 0;
4352*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_FUNC: {
4353*436bf2bcSAndroid Build Coastguard Worker 		struct trace_seq s;
4354*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_init(&s);
4355*436bf2bcSAndroid Build Coastguard Worker 		val = process_defined_func(&s, data, size, event, arg);
4356*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_destroy(&s);
4357*436bf2bcSAndroid Build Coastguard Worker 		return val;
4358*436bf2bcSAndroid Build Coastguard Worker 	}
4359*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_OP:
4360*436bf2bcSAndroid Build Coastguard Worker 		if (strcmp(arg->op.op, "[") == 0) {
4361*436bf2bcSAndroid Build Coastguard Worker 			/*
4362*436bf2bcSAndroid Build Coastguard Worker 			 * Arrays are special, since we don't want
4363*436bf2bcSAndroid Build Coastguard Worker 			 * to read the arg as is.
4364*436bf2bcSAndroid Build Coastguard Worker 			 */
4365*436bf2bcSAndroid Build Coastguard Worker 			right = eval_num_arg(data, size, event, arg->op.right);
4366*436bf2bcSAndroid Build Coastguard Worker 
4367*436bf2bcSAndroid Build Coastguard Worker 			/* handle typecasts */
4368*436bf2bcSAndroid Build Coastguard Worker 			larg = arg->op.left;
4369*436bf2bcSAndroid Build Coastguard Worker 			while (larg->type == TEP_PRINT_TYPE) {
4370*436bf2bcSAndroid Build Coastguard Worker 				if (!typearg)
4371*436bf2bcSAndroid Build Coastguard Worker 					typearg = larg;
4372*436bf2bcSAndroid Build Coastguard Worker 				larg = larg->typecast.item;
4373*436bf2bcSAndroid Build Coastguard Worker 			}
4374*436bf2bcSAndroid Build Coastguard Worker 
4375*436bf2bcSAndroid Build Coastguard Worker 			/* Default to long size */
4376*436bf2bcSAndroid Build Coastguard Worker 			field_size = tep->long_size;
4377*436bf2bcSAndroid Build Coastguard Worker 
4378*436bf2bcSAndroid Build Coastguard Worker 			switch (larg->type) {
4379*436bf2bcSAndroid Build Coastguard Worker 			case TEP_PRINT_DYNAMIC_ARRAY:
4380*436bf2bcSAndroid Build Coastguard Worker 				dynamic_offset_field(tep, larg->dynarray.field, data,
4381*436bf2bcSAndroid Build Coastguard Worker 						     size, &offset, NULL);
4382*436bf2bcSAndroid Build Coastguard Worker 				offset += right;
4383*436bf2bcSAndroid Build Coastguard Worker 				if (larg->dynarray.field->elementsize)
4384*436bf2bcSAndroid Build Coastguard Worker 					field_size = larg->dynarray.field->elementsize;
4385*436bf2bcSAndroid Build Coastguard Worker 				break;
4386*436bf2bcSAndroid Build Coastguard Worker 			case TEP_PRINT_FIELD:
4387*436bf2bcSAndroid Build Coastguard Worker 				if (!larg->field.field) {
4388*436bf2bcSAndroid Build Coastguard Worker 					larg->field.field =
4389*436bf2bcSAndroid Build Coastguard Worker 						tep_find_any_field(event, larg->field.name);
4390*436bf2bcSAndroid Build Coastguard Worker 					if (!larg->field.field) {
4391*436bf2bcSAndroid Build Coastguard Worker 						arg = larg;
4392*436bf2bcSAndroid Build Coastguard Worker 						goto out_warning_field;
4393*436bf2bcSAndroid Build Coastguard Worker 					}
4394*436bf2bcSAndroid Build Coastguard Worker 				}
4395*436bf2bcSAndroid Build Coastguard Worker 				field_size = larg->field.field->elementsize;
4396*436bf2bcSAndroid Build Coastguard Worker 				offset = larg->field.field->offset +
4397*436bf2bcSAndroid Build Coastguard Worker 					right * larg->field.field->elementsize;
4398*436bf2bcSAndroid Build Coastguard Worker 				break;
4399*436bf2bcSAndroid Build Coastguard Worker 			default:
4400*436bf2bcSAndroid Build Coastguard Worker 				goto default_op; /* oops, all bets off */
4401*436bf2bcSAndroid Build Coastguard Worker 			}
4402*436bf2bcSAndroid Build Coastguard Worker 			if (check_data_offset_size(event, arg->field.name, size,
4403*436bf2bcSAndroid Build Coastguard Worker 						   offset, field_size)) {
4404*436bf2bcSAndroid Build Coastguard Worker 				val = 0;
4405*436bf2bcSAndroid Build Coastguard Worker 				break;
4406*436bf2bcSAndroid Build Coastguard Worker 			}
4407*436bf2bcSAndroid Build Coastguard Worker 			val = tep_read_number(tep,
4408*436bf2bcSAndroid Build Coastguard Worker 					      data + offset, field_size);
4409*436bf2bcSAndroid Build Coastguard Worker 			if (typearg)
4410*436bf2bcSAndroid Build Coastguard Worker 				val = eval_type(val, typearg, 1);
4411*436bf2bcSAndroid Build Coastguard Worker 			break;
4412*436bf2bcSAndroid Build Coastguard Worker 		} else if (strcmp(arg->op.op, "?") == 0) {
4413*436bf2bcSAndroid Build Coastguard Worker 			left = eval_num_arg(data, size, event, arg->op.left);
4414*436bf2bcSAndroid Build Coastguard Worker 			arg = arg->op.right;
4415*436bf2bcSAndroid Build Coastguard Worker 			if (left)
4416*436bf2bcSAndroid Build Coastguard Worker 				val = eval_num_arg(data, size, event, arg->op.left);
4417*436bf2bcSAndroid Build Coastguard Worker 			else
4418*436bf2bcSAndroid Build Coastguard Worker 				val = eval_num_arg(data, size, event, arg->op.right);
4419*436bf2bcSAndroid Build Coastguard Worker 			break;
4420*436bf2bcSAndroid Build Coastguard Worker 		}
4421*436bf2bcSAndroid Build Coastguard Worker  default_op:
4422*436bf2bcSAndroid Build Coastguard Worker 		left = eval_num_arg(data, size, event, arg->op.left);
4423*436bf2bcSAndroid Build Coastguard Worker 		right = eval_num_arg(data, size, event, arg->op.right);
4424*436bf2bcSAndroid Build Coastguard Worker 		switch (arg->op.op[0]) {
4425*436bf2bcSAndroid Build Coastguard Worker 		case '!':
4426*436bf2bcSAndroid Build Coastguard Worker 			switch (arg->op.op[1]) {
4427*436bf2bcSAndroid Build Coastguard Worker 			case 0:
4428*436bf2bcSAndroid Build Coastguard Worker 				val = !right;
4429*436bf2bcSAndroid Build Coastguard Worker 				break;
4430*436bf2bcSAndroid Build Coastguard Worker 			case '=':
4431*436bf2bcSAndroid Build Coastguard Worker 				val = left != right;
4432*436bf2bcSAndroid Build Coastguard Worker 				break;
4433*436bf2bcSAndroid Build Coastguard Worker 			default:
4434*436bf2bcSAndroid Build Coastguard Worker 				goto out_warning_op;
4435*436bf2bcSAndroid Build Coastguard Worker 			}
4436*436bf2bcSAndroid Build Coastguard Worker 			break;
4437*436bf2bcSAndroid Build Coastguard Worker 		case '~':
4438*436bf2bcSAndroid Build Coastguard Worker 			val = ~right;
4439*436bf2bcSAndroid Build Coastguard Worker 			break;
4440*436bf2bcSAndroid Build Coastguard Worker 		case '|':
4441*436bf2bcSAndroid Build Coastguard Worker 			if (arg->op.op[1])
4442*436bf2bcSAndroid Build Coastguard Worker 				val = left || right;
4443*436bf2bcSAndroid Build Coastguard Worker 			else
4444*436bf2bcSAndroid Build Coastguard Worker 				val = left | right;
4445*436bf2bcSAndroid Build Coastguard Worker 			break;
4446*436bf2bcSAndroid Build Coastguard Worker 		case '&':
4447*436bf2bcSAndroid Build Coastguard Worker 			if (arg->op.op[1])
4448*436bf2bcSAndroid Build Coastguard Worker 				val = left && right;
4449*436bf2bcSAndroid Build Coastguard Worker 			else
4450*436bf2bcSAndroid Build Coastguard Worker 				val = left & right;
4451*436bf2bcSAndroid Build Coastguard Worker 			break;
4452*436bf2bcSAndroid Build Coastguard Worker 		case '<':
4453*436bf2bcSAndroid Build Coastguard Worker 			switch (arg->op.op[1]) {
4454*436bf2bcSAndroid Build Coastguard Worker 			case 0:
4455*436bf2bcSAndroid Build Coastguard Worker 				val = left < right;
4456*436bf2bcSAndroid Build Coastguard Worker 				break;
4457*436bf2bcSAndroid Build Coastguard Worker 			case '<':
4458*436bf2bcSAndroid Build Coastguard Worker 				val = left << right;
4459*436bf2bcSAndroid Build Coastguard Worker 				break;
4460*436bf2bcSAndroid Build Coastguard Worker 			case '=':
4461*436bf2bcSAndroid Build Coastguard Worker 				val = left <= right;
4462*436bf2bcSAndroid Build Coastguard Worker 				break;
4463*436bf2bcSAndroid Build Coastguard Worker 			default:
4464*436bf2bcSAndroid Build Coastguard Worker 				goto out_warning_op;
4465*436bf2bcSAndroid Build Coastguard Worker 			}
4466*436bf2bcSAndroid Build Coastguard Worker 			break;
4467*436bf2bcSAndroid Build Coastguard Worker 		case '>':
4468*436bf2bcSAndroid Build Coastguard Worker 			switch (arg->op.op[1]) {
4469*436bf2bcSAndroid Build Coastguard Worker 			case 0:
4470*436bf2bcSAndroid Build Coastguard Worker 				val = left > right;
4471*436bf2bcSAndroid Build Coastguard Worker 				break;
4472*436bf2bcSAndroid Build Coastguard Worker 			case '>':
4473*436bf2bcSAndroid Build Coastguard Worker 				val = left >> right;
4474*436bf2bcSAndroid Build Coastguard Worker 				break;
4475*436bf2bcSAndroid Build Coastguard Worker 			case '=':
4476*436bf2bcSAndroid Build Coastguard Worker 				val = left >= right;
4477*436bf2bcSAndroid Build Coastguard Worker 				break;
4478*436bf2bcSAndroid Build Coastguard Worker 			default:
4479*436bf2bcSAndroid Build Coastguard Worker 				goto out_warning_op;
4480*436bf2bcSAndroid Build Coastguard Worker 			}
4481*436bf2bcSAndroid Build Coastguard Worker 			break;
4482*436bf2bcSAndroid Build Coastguard Worker 		case '=':
4483*436bf2bcSAndroid Build Coastguard Worker 			if (arg->op.op[1] != '=')
4484*436bf2bcSAndroid Build Coastguard Worker 				goto out_warning_op;
4485*436bf2bcSAndroid Build Coastguard Worker 
4486*436bf2bcSAndroid Build Coastguard Worker 			val = left == right;
4487*436bf2bcSAndroid Build Coastguard Worker 			break;
4488*436bf2bcSAndroid Build Coastguard Worker 		case '-':
4489*436bf2bcSAndroid Build Coastguard Worker 			val = left - right;
4490*436bf2bcSAndroid Build Coastguard Worker 			break;
4491*436bf2bcSAndroid Build Coastguard Worker 		case '+':
4492*436bf2bcSAndroid Build Coastguard Worker 			val = left + right;
4493*436bf2bcSAndroid Build Coastguard Worker 			break;
4494*436bf2bcSAndroid Build Coastguard Worker 		case '/':
4495*436bf2bcSAndroid Build Coastguard Worker 			val = left / right;
4496*436bf2bcSAndroid Build Coastguard Worker 			break;
4497*436bf2bcSAndroid Build Coastguard Worker 		case '%':
4498*436bf2bcSAndroid Build Coastguard Worker 			val = left % right;
4499*436bf2bcSAndroid Build Coastguard Worker 			break;
4500*436bf2bcSAndroid Build Coastguard Worker 		case '*':
4501*436bf2bcSAndroid Build Coastguard Worker 			val = left * right;
4502*436bf2bcSAndroid Build Coastguard Worker 			break;
4503*436bf2bcSAndroid Build Coastguard Worker 		default:
4504*436bf2bcSAndroid Build Coastguard Worker 			goto out_warning_op;
4505*436bf2bcSAndroid Build Coastguard Worker 		}
4506*436bf2bcSAndroid Build Coastguard Worker 		break;
4507*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_DYNAMIC_ARRAY_LEN:
4508*436bf2bcSAndroid Build Coastguard Worker 		dynamic_offset_field(tep, arg->dynarray.field, data, size,
4509*436bf2bcSAndroid Build Coastguard Worker 				     NULL, &field_size);
4510*436bf2bcSAndroid Build Coastguard Worker 		val = field_size;
4511*436bf2bcSAndroid Build Coastguard Worker 		break;
4512*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_DYNAMIC_ARRAY:
4513*436bf2bcSAndroid Build Coastguard Worker 		/* Without [], we pass the address to the dynamic data */
4514*436bf2bcSAndroid Build Coastguard Worker 		dynamic_offset_field(tep, arg->dynarray.field, data, size,
4515*436bf2bcSAndroid Build Coastguard Worker 				     &offset, NULL);
4516*436bf2bcSAndroid Build Coastguard Worker 		if (check_data_offset_size(event, arg->field.name, size,
4517*436bf2bcSAndroid Build Coastguard Worker 					   offset, 0)) {
4518*436bf2bcSAndroid Build Coastguard Worker 			val = (unsigned long)data;
4519*436bf2bcSAndroid Build Coastguard Worker 			break;
4520*436bf2bcSAndroid Build Coastguard Worker 		}
4521*436bf2bcSAndroid Build Coastguard Worker 		val = (unsigned long)data + offset;
4522*436bf2bcSAndroid Build Coastguard Worker 		break;
4523*436bf2bcSAndroid Build Coastguard Worker 	default: /* not sure what to do there */
4524*436bf2bcSAndroid Build Coastguard Worker 		return 0;
4525*436bf2bcSAndroid Build Coastguard Worker 	}
4526*436bf2bcSAndroid Build Coastguard Worker 	return val;
4527*436bf2bcSAndroid Build Coastguard Worker 
4528*436bf2bcSAndroid Build Coastguard Worker out_warning_op:
4529*436bf2bcSAndroid Build Coastguard Worker 	do_warning_event(event, "%s: unknown op '%s'", __func__, arg->op.op);
4530*436bf2bcSAndroid Build Coastguard Worker 	return 0;
4531*436bf2bcSAndroid Build Coastguard Worker 
4532*436bf2bcSAndroid Build Coastguard Worker out_warning_field:
4533*436bf2bcSAndroid Build Coastguard Worker 	do_warning_event(event, "%s: field %s not found",
4534*436bf2bcSAndroid Build Coastguard Worker 			 __func__, arg->field.name);
4535*436bf2bcSAndroid Build Coastguard Worker 	return 0;
4536*436bf2bcSAndroid Build Coastguard Worker }
4537*436bf2bcSAndroid Build Coastguard Worker 
4538*436bf2bcSAndroid Build Coastguard Worker struct flag {
4539*436bf2bcSAndroid Build Coastguard Worker 	const char *name;
4540*436bf2bcSAndroid Build Coastguard Worker 	unsigned long long value;
4541*436bf2bcSAndroid Build Coastguard Worker };
4542*436bf2bcSAndroid Build Coastguard Worker 
4543*436bf2bcSAndroid Build Coastguard Worker static const struct flag flags[] = {
4544*436bf2bcSAndroid Build Coastguard Worker 	{ "HI_SOFTIRQ", 0 },
4545*436bf2bcSAndroid Build Coastguard Worker 	{ "TIMER_SOFTIRQ", 1 },
4546*436bf2bcSAndroid Build Coastguard Worker 	{ "NET_TX_SOFTIRQ", 2 },
4547*436bf2bcSAndroid Build Coastguard Worker 	{ "NET_RX_SOFTIRQ", 3 },
4548*436bf2bcSAndroid Build Coastguard Worker 	{ "BLOCK_SOFTIRQ", 4 },
4549*436bf2bcSAndroid Build Coastguard Worker 	{ "IRQ_POLL_SOFTIRQ", 5 },
4550*436bf2bcSAndroid Build Coastguard Worker 	{ "TASKLET_SOFTIRQ", 6 },
4551*436bf2bcSAndroid Build Coastguard Worker 	{ "SCHED_SOFTIRQ", 7 },
4552*436bf2bcSAndroid Build Coastguard Worker 	{ "HRTIMER_SOFTIRQ", 8 },
4553*436bf2bcSAndroid Build Coastguard Worker 	{ "RCU_SOFTIRQ", 9 },
4554*436bf2bcSAndroid Build Coastguard Worker 
4555*436bf2bcSAndroid Build Coastguard Worker 	{ "HRTIMER_NORESTART", 0 },
4556*436bf2bcSAndroid Build Coastguard Worker 	{ "HRTIMER_RESTART", 1 },
4557*436bf2bcSAndroid Build Coastguard Worker };
4558*436bf2bcSAndroid Build Coastguard Worker 
eval_flag(const char * flag)4559*436bf2bcSAndroid Build Coastguard Worker static long long eval_flag(const char *flag)
4560*436bf2bcSAndroid Build Coastguard Worker {
4561*436bf2bcSAndroid Build Coastguard Worker 	int i;
4562*436bf2bcSAndroid Build Coastguard Worker 
4563*436bf2bcSAndroid Build Coastguard Worker 	/*
4564*436bf2bcSAndroid Build Coastguard Worker 	 * Some flags in the format files do not get converted.
4565*436bf2bcSAndroid Build Coastguard Worker 	 * If the flag is not numeric, see if it is something that
4566*436bf2bcSAndroid Build Coastguard Worker 	 * we already know about.
4567*436bf2bcSAndroid Build Coastguard Worker 	 */
4568*436bf2bcSAndroid Build Coastguard Worker 	if (isdigit(flag[0]))
4569*436bf2bcSAndroid Build Coastguard Worker 		return strtoull(flag, NULL, 0);
4570*436bf2bcSAndroid Build Coastguard Worker 
4571*436bf2bcSAndroid Build Coastguard Worker 	for (i = 0; i < (int)(sizeof(flags)/sizeof(flags[0])); i++)
4572*436bf2bcSAndroid Build Coastguard Worker 		if (strcmp(flags[i].name, flag) == 0)
4573*436bf2bcSAndroid Build Coastguard Worker 			return flags[i].value;
4574*436bf2bcSAndroid Build Coastguard Worker 
4575*436bf2bcSAndroid Build Coastguard Worker 	return -1LL;
4576*436bf2bcSAndroid Build Coastguard Worker }
4577*436bf2bcSAndroid Build Coastguard Worker 
print_str_to_seq(struct trace_seq * s,const char * format,int len_arg,const char * str)4578*436bf2bcSAndroid Build Coastguard Worker static void print_str_to_seq(struct trace_seq *s, const char *format,
4579*436bf2bcSAndroid Build Coastguard Worker 			     int len_arg, const char *str)
4580*436bf2bcSAndroid Build Coastguard Worker {
4581*436bf2bcSAndroid Build Coastguard Worker 	if (len_arg >= 0)
4582*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_printf(s, format, len_arg, str);
4583*436bf2bcSAndroid Build Coastguard Worker 	else
4584*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_printf(s, format, str);
4585*436bf2bcSAndroid Build Coastguard Worker }
4586*436bf2bcSAndroid Build Coastguard Worker 
print_bitmask_to_seq(struct tep_handle * tep,struct trace_seq * s,const char * format,int len_arg,const void * data,int size)4587*436bf2bcSAndroid Build Coastguard Worker static void print_bitmask_to_seq(struct tep_handle *tep,
4588*436bf2bcSAndroid Build Coastguard Worker 				 struct trace_seq *s, const char *format,
4589*436bf2bcSAndroid Build Coastguard Worker 				 int len_arg, const void *data, int size)
4590*436bf2bcSAndroid Build Coastguard Worker {
4591*436bf2bcSAndroid Build Coastguard Worker 	int nr_bits = size * 8;
4592*436bf2bcSAndroid Build Coastguard Worker 	int str_size = (nr_bits + 3) / 4;
4593*436bf2bcSAndroid Build Coastguard Worker 	int len = 0;
4594*436bf2bcSAndroid Build Coastguard Worker 	char buf[3];
4595*436bf2bcSAndroid Build Coastguard Worker 	char *str;
4596*436bf2bcSAndroid Build Coastguard Worker 	int index;
4597*436bf2bcSAndroid Build Coastguard Worker 	int i;
4598*436bf2bcSAndroid Build Coastguard Worker 
4599*436bf2bcSAndroid Build Coastguard Worker 	/*
4600*436bf2bcSAndroid Build Coastguard Worker 	 * The kernel likes to put in commas every 32 bits, we
4601*436bf2bcSAndroid Build Coastguard Worker 	 * can do the same.
4602*436bf2bcSAndroid Build Coastguard Worker 	 */
4603*436bf2bcSAndroid Build Coastguard Worker 	str_size += (nr_bits - 1) / 32;
4604*436bf2bcSAndroid Build Coastguard Worker 
4605*436bf2bcSAndroid Build Coastguard Worker 	str = malloc(str_size + 1);
4606*436bf2bcSAndroid Build Coastguard Worker 	if (!str) {
4607*436bf2bcSAndroid Build Coastguard Worker 		do_warning("%s: not enough memory!", __func__);
4608*436bf2bcSAndroid Build Coastguard Worker 		return;
4609*436bf2bcSAndroid Build Coastguard Worker 	}
4610*436bf2bcSAndroid Build Coastguard Worker 	str[str_size] = 0;
4611*436bf2bcSAndroid Build Coastguard Worker 
4612*436bf2bcSAndroid Build Coastguard Worker 	/* Start out with -2 for the two chars per byte */
4613*436bf2bcSAndroid Build Coastguard Worker 	for (i = str_size - 2; i >= 0; i -= 2) {
4614*436bf2bcSAndroid Build Coastguard Worker 		/*
4615*436bf2bcSAndroid Build Coastguard Worker 		 * data points to a bit mask of size bytes.
4616*436bf2bcSAndroid Build Coastguard Worker 		 * In the kernel, this is an array of long words, thus
4617*436bf2bcSAndroid Build Coastguard Worker 		 * endianness is very important.
4618*436bf2bcSAndroid Build Coastguard Worker 		 */
4619*436bf2bcSAndroid Build Coastguard Worker 		if (tep->file_bigendian)
4620*436bf2bcSAndroid Build Coastguard Worker 			index = size - (len + 1);
4621*436bf2bcSAndroid Build Coastguard Worker 		else
4622*436bf2bcSAndroid Build Coastguard Worker 			index = len;
4623*436bf2bcSAndroid Build Coastguard Worker 
4624*436bf2bcSAndroid Build Coastguard Worker 		snprintf(buf, 3, "%02x", *((unsigned char *)data + index));
4625*436bf2bcSAndroid Build Coastguard Worker 		memcpy(str + i, buf, 2);
4626*436bf2bcSAndroid Build Coastguard Worker 		len++;
4627*436bf2bcSAndroid Build Coastguard Worker 		if (!(len & 3) && i > 0) {
4628*436bf2bcSAndroid Build Coastguard Worker 			i--;
4629*436bf2bcSAndroid Build Coastguard Worker 			str[i] = ',';
4630*436bf2bcSAndroid Build Coastguard Worker 		}
4631*436bf2bcSAndroid Build Coastguard Worker 	}
4632*436bf2bcSAndroid Build Coastguard Worker 
4633*436bf2bcSAndroid Build Coastguard Worker 	if (len_arg >= 0)
4634*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_printf(s, format, len_arg, str);
4635*436bf2bcSAndroid Build Coastguard Worker 	else
4636*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_printf(s, format, str);
4637*436bf2bcSAndroid Build Coastguard Worker 
4638*436bf2bcSAndroid Build Coastguard Worker 	free(str);
4639*436bf2bcSAndroid Build Coastguard Worker }
4640*436bf2bcSAndroid Build Coastguard Worker 
4641*436bf2bcSAndroid Build Coastguard Worker #define log10(n)               \
4642*436bf2bcSAndroid Build Coastguard Worker (			       \
4643*436bf2bcSAndroid Build Coastguard Worker 	n < 10UL ? 0 :	       \
4644*436bf2bcSAndroid Build Coastguard Worker 	n < 100UL ? 1 :	       \
4645*436bf2bcSAndroid Build Coastguard Worker 	n < 1000UL ? 2 :       \
4646*436bf2bcSAndroid Build Coastguard Worker 	n < 10000UL ? 3 :      \
4647*436bf2bcSAndroid Build Coastguard Worker 	n < 100000UL ? 4 :     \
4648*436bf2bcSAndroid Build Coastguard Worker 	n < 1000000UL ? 5 :    \
4649*436bf2bcSAndroid Build Coastguard Worker 	n < 10000000UL ? 6 :   \
4650*436bf2bcSAndroid Build Coastguard Worker 	n < 100000000UL ? 7 :  \
4651*436bf2bcSAndroid Build Coastguard Worker 	n < 1000000000UL ? 8 : \
4652*436bf2bcSAndroid Build Coastguard Worker 	9		       \
4653*436bf2bcSAndroid Build Coastguard Worker )
4654*436bf2bcSAndroid Build Coastguard Worker 
4655*436bf2bcSAndroid Build Coastguard Worker /* ilog10(0) should be 1 but the 0 simplifies below math */
4656*436bf2bcSAndroid Build Coastguard Worker #define ilog10(n)    \
4657*436bf2bcSAndroid Build Coastguard Worker (                     \
4658*436bf2bcSAndroid Build Coastguard Worker 	n == 0 ? 0UL : \
4659*436bf2bcSAndroid Build Coastguard Worker 	n == 1 ? 10UL : \
4660*436bf2bcSAndroid Build Coastguard Worker 	n == 2 ? 100UL : \
4661*436bf2bcSAndroid Build Coastguard Worker 	n == 3 ? 1000UL : \
4662*436bf2bcSAndroid Build Coastguard Worker 	n == 4 ? 10000UL : \
4663*436bf2bcSAndroid Build Coastguard Worker 	n == 5 ? 100000UL : \
4664*436bf2bcSAndroid Build Coastguard Worker 	n == 6 ? 1000000UL : \
4665*436bf2bcSAndroid Build Coastguard Worker 	n == 7 ? 10000000UL : \
4666*436bf2bcSAndroid Build Coastguard Worker 	n == 8 ? 100000000UL : \
4667*436bf2bcSAndroid Build Coastguard Worker 		 1000000000UL   \
4668*436bf2bcSAndroid Build Coastguard Worker )
4669*436bf2bcSAndroid Build Coastguard Worker 
cpumask_worst_size(unsigned int nr_bits)4670*436bf2bcSAndroid Build Coastguard Worker static unsigned int cpumask_worst_size(unsigned int nr_bits)
4671*436bf2bcSAndroid Build Coastguard Worker {
4672*436bf2bcSAndroid Build Coastguard Worker 	/*
4673*436bf2bcSAndroid Build Coastguard Worker 	 * Printing all the CPUs separated by a comma is a decent bound for the
4674*436bf2bcSAndroid Build Coastguard Worker 	 * maximum memory required to print a cpumask (a slightly better bound
4675*436bf2bcSAndroid Build Coastguard Worker 	 * is chunks of 2 bits set, i.e. 0-1,3-4,6-7...).
4676*436bf2bcSAndroid Build Coastguard Worker 	 *
4677*436bf2bcSAndroid Build Coastguard Worker 	 * e.g. for nr_bits=132:
4678*436bf2bcSAndroid Build Coastguard Worker 	 * - 131 commas
4679*436bf2bcSAndroid Build Coastguard Worker 	 * - 10 * 1 chars for CPUS [0, 9]
4680*436bf2bcSAndroid Build Coastguard Worker 	 * - 90 * 2 chars for CPUS [10-99]
4681*436bf2bcSAndroid Build Coastguard Worker 	 * - 32 * 3 chars for CPUS [100-131]
4682*436bf2bcSAndroid Build Coastguard Worker 	 */
4683*436bf2bcSAndroid Build Coastguard Worker 	unsigned int last_cpu = nr_bits - 1;
4684*436bf2bcSAndroid Build Coastguard Worker 	unsigned int nr_chars = nr_bits - 1;
4685*436bf2bcSAndroid Build Coastguard Worker 	int last_lvl = log10(last_cpu);
4686*436bf2bcSAndroid Build Coastguard Worker 
4687*436bf2bcSAndroid Build Coastguard Worker 	/* All log10 levels before the last one have all values used */
4688*436bf2bcSAndroid Build Coastguard Worker 	for (int lvl = 0; lvl < last_lvl; lvl++) {
4689*436bf2bcSAndroid Build Coastguard Worker 		int nr_values = ilog10(lvl + 1) - ilog10(lvl);
4690*436bf2bcSAndroid Build Coastguard Worker 
4691*436bf2bcSAndroid Build Coastguard Worker 		nr_chars += nr_values * (lvl + 1);
4692*436bf2bcSAndroid Build Coastguard Worker 	}
4693*436bf2bcSAndroid Build Coastguard Worker 	/* Last level is incomplete */
4694*436bf2bcSAndroid Build Coastguard Worker 	nr_chars += (nr_bits - ilog10(last_lvl)) * (last_lvl + 1);
4695*436bf2bcSAndroid Build Coastguard Worker 
4696*436bf2bcSAndroid Build Coastguard Worker 	return nr_chars;
4697*436bf2bcSAndroid Build Coastguard Worker }
4698*436bf2bcSAndroid Build Coastguard Worker 
print_cpumask_to_seq(struct tep_handle * tep,struct trace_seq * s,const char * format,int len_arg,const void * data,int size)4699*436bf2bcSAndroid Build Coastguard Worker static void print_cpumask_to_seq(struct tep_handle *tep,
4700*436bf2bcSAndroid Build Coastguard Worker 				 struct trace_seq *s, const char *format,
4701*436bf2bcSAndroid Build Coastguard Worker 				 int len_arg, const void *data, int size)
4702*436bf2bcSAndroid Build Coastguard Worker {
4703*436bf2bcSAndroid Build Coastguard Worker 	int firstone = -1, firstzero = -1;
4704*436bf2bcSAndroid Build Coastguard Worker 	int nr_bits = size * 8;
4705*436bf2bcSAndroid Build Coastguard Worker 	bool first = true;
4706*436bf2bcSAndroid Build Coastguard Worker 	int str_size = 0;
4707*436bf2bcSAndroid Build Coastguard Worker 	char buf[12]; /* '-' + log10(2^32) + 1 digits + '\0' */
4708*436bf2bcSAndroid Build Coastguard Worker 	char *str;
4709*436bf2bcSAndroid Build Coastguard Worker 	int index;
4710*436bf2bcSAndroid Build Coastguard Worker 	int i;
4711*436bf2bcSAndroid Build Coastguard Worker 
4712*436bf2bcSAndroid Build Coastguard Worker 	str = malloc(cpumask_worst_size(nr_bits) + 1);
4713*436bf2bcSAndroid Build Coastguard Worker 	if (!str) {
4714*436bf2bcSAndroid Build Coastguard Worker 		do_warning("%s: not enough memory!", __func__);
4715*436bf2bcSAndroid Build Coastguard Worker 		return;
4716*436bf2bcSAndroid Build Coastguard Worker 	}
4717*436bf2bcSAndroid Build Coastguard Worker 
4718*436bf2bcSAndroid Build Coastguard Worker 	for (i = 0; i < size; i++) {
4719*436bf2bcSAndroid Build Coastguard Worker 		unsigned char byte;
4720*436bf2bcSAndroid Build Coastguard Worker 		int fmtsize;
4721*436bf2bcSAndroid Build Coastguard Worker 
4722*436bf2bcSAndroid Build Coastguard Worker 		if (tep->file_bigendian)
4723*436bf2bcSAndroid Build Coastguard Worker 			index = size - (i + 1);
4724*436bf2bcSAndroid Build Coastguard Worker 		else
4725*436bf2bcSAndroid Build Coastguard Worker 			index = i;
4726*436bf2bcSAndroid Build Coastguard Worker 
4727*436bf2bcSAndroid Build Coastguard Worker 		/* Byte by byte scan, not the best... */
4728*436bf2bcSAndroid Build Coastguard Worker 		byte = *(((unsigned char *)data) + index);
4729*436bf2bcSAndroid Build Coastguard Worker more:
4730*436bf2bcSAndroid Build Coastguard Worker 		/* First find a bit set to one...*/
4731*436bf2bcSAndroid Build Coastguard Worker 		if (firstone < 0 && byte) {
4732*436bf2bcSAndroid Build Coastguard Worker 			/*
4733*436bf2bcSAndroid Build Coastguard Worker 			 * Set all lower bits, so a later ffz on this same byte
4734*436bf2bcSAndroid Build Coastguard Worker 			 * is guaranteed to find a later bit.
4735*436bf2bcSAndroid Build Coastguard Worker 			 */
4736*436bf2bcSAndroid Build Coastguard Worker 			firstone = ffs(byte) - 1;
4737*436bf2bcSAndroid Build Coastguard Worker 			byte |= (1 << firstone) - 1;
4738*436bf2bcSAndroid Build Coastguard Worker 			firstone += i * 8;
4739*436bf2bcSAndroid Build Coastguard Worker 		}
4740*436bf2bcSAndroid Build Coastguard Worker 
4741*436bf2bcSAndroid Build Coastguard Worker 		if (firstone < 0)
4742*436bf2bcSAndroid Build Coastguard Worker 			continue;
4743*436bf2bcSAndroid Build Coastguard Worker 
4744*436bf2bcSAndroid Build Coastguard Worker 		/* ...Then find a bit set to zero */
4745*436bf2bcSAndroid Build Coastguard Worker 		if ((~byte) & 0xFF) {
4746*436bf2bcSAndroid Build Coastguard Worker 			/*
4747*436bf2bcSAndroid Build Coastguard Worker 			 * Clear all lower bits, so a later ffs on this same
4748*436bf2bcSAndroid Build Coastguard Worker 			 * byte is guaranteed to find a later bit.
4749*436bf2bcSAndroid Build Coastguard Worker 			 */
4750*436bf2bcSAndroid Build Coastguard Worker 			firstzero = ffs(~byte) - 1;
4751*436bf2bcSAndroid Build Coastguard Worker 			byte &= ~((1 << (firstzero)) - 1);
4752*436bf2bcSAndroid Build Coastguard Worker 			firstzero += i * 8;
4753*436bf2bcSAndroid Build Coastguard Worker 		} else if (i == size - 1) { /* ...Or reach the end of the mask */
4754*436bf2bcSAndroid Build Coastguard Worker 			firstzero = nr_bits;
4755*436bf2bcSAndroid Build Coastguard Worker 			byte = 0;
4756*436bf2bcSAndroid Build Coastguard Worker 		} else {
4757*436bf2bcSAndroid Build Coastguard Worker 			continue;
4758*436bf2bcSAndroid Build Coastguard Worker 		}
4759*436bf2bcSAndroid Build Coastguard Worker 
4760*436bf2bcSAndroid Build Coastguard Worker 		/* We've found a bit set to one, and a later bit set to zero. */
4761*436bf2bcSAndroid Build Coastguard Worker 		if (!first) {
4762*436bf2bcSAndroid Build Coastguard Worker 			str[str_size] = ',';
4763*436bf2bcSAndroid Build Coastguard Worker 			str_size++;
4764*436bf2bcSAndroid Build Coastguard Worker 		}
4765*436bf2bcSAndroid Build Coastguard Worker 		first = false;
4766*436bf2bcSAndroid Build Coastguard Worker 
4767*436bf2bcSAndroid Build Coastguard Worker 		/* It takes {log10(number) + 1} chars to format a number */
4768*436bf2bcSAndroid Build Coastguard Worker 		fmtsize = log10(firstone) + 1;
4769*436bf2bcSAndroid Build Coastguard Worker 		snprintf(buf, fmtsize + 1, "%d", firstone);
4770*436bf2bcSAndroid Build Coastguard Worker 		memcpy(str + str_size, buf, fmtsize);
4771*436bf2bcSAndroid Build Coastguard Worker 		str_size += fmtsize;
4772*436bf2bcSAndroid Build Coastguard Worker 
4773*436bf2bcSAndroid Build Coastguard Worker 		if (firstzero > firstone + 1) {
4774*436bf2bcSAndroid Build Coastguard Worker 			fmtsize = log10(firstzero - 1) + 2;
4775*436bf2bcSAndroid Build Coastguard Worker 			snprintf(buf, fmtsize + 1, "-%d", firstzero - 1);
4776*436bf2bcSAndroid Build Coastguard Worker 			memcpy(str + str_size, buf, fmtsize);
4777*436bf2bcSAndroid Build Coastguard Worker 			str_size += fmtsize;
4778*436bf2bcSAndroid Build Coastguard Worker 		}
4779*436bf2bcSAndroid Build Coastguard Worker 
4780*436bf2bcSAndroid Build Coastguard Worker 		firstzero = firstone = -1;
4781*436bf2bcSAndroid Build Coastguard Worker 		if (byte)
4782*436bf2bcSAndroid Build Coastguard Worker 			goto more;
4783*436bf2bcSAndroid Build Coastguard Worker 	}
4784*436bf2bcSAndroid Build Coastguard Worker 
4785*436bf2bcSAndroid Build Coastguard Worker 	str[str_size] = 0;
4786*436bf2bcSAndroid Build Coastguard Worker 	str_size++;
4787*436bf2bcSAndroid Build Coastguard Worker 
4788*436bf2bcSAndroid Build Coastguard Worker 	if (len_arg >= 0)
4789*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_printf(s, format, len_arg, str);
4790*436bf2bcSAndroid Build Coastguard Worker 	else
4791*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_printf(s, format, str);
4792*436bf2bcSAndroid Build Coastguard Worker 
4793*436bf2bcSAndroid Build Coastguard Worker 	free(str);
4794*436bf2bcSAndroid Build Coastguard Worker }
4795*436bf2bcSAndroid Build Coastguard Worker 
print_str_arg(struct trace_seq * s,void * data,int size,struct tep_event * event,const char * format,int len_arg,struct tep_print_arg * arg)4796*436bf2bcSAndroid Build Coastguard Worker static void print_str_arg(struct trace_seq *s, void *data, int size,
4797*436bf2bcSAndroid Build Coastguard Worker 			  struct tep_event *event, const char *format,
4798*436bf2bcSAndroid Build Coastguard Worker 			  int len_arg, struct tep_print_arg *arg)
4799*436bf2bcSAndroid Build Coastguard Worker {
4800*436bf2bcSAndroid Build Coastguard Worker 	struct tep_handle *tep = event->tep;
4801*436bf2bcSAndroid Build Coastguard Worker 	struct tep_print_flag_sym *flag;
4802*436bf2bcSAndroid Build Coastguard Worker 	struct tep_format_field *field;
4803*436bf2bcSAndroid Build Coastguard Worker 	struct printk_map *printk;
4804*436bf2bcSAndroid Build Coastguard Worker 	unsigned int offset, len;
4805*436bf2bcSAndroid Build Coastguard Worker 	long long val, fval;
4806*436bf2bcSAndroid Build Coastguard Worker 	unsigned long long addr;
4807*436bf2bcSAndroid Build Coastguard Worker 	char *str;
4808*436bf2bcSAndroid Build Coastguard Worker 	unsigned char *hex;
4809*436bf2bcSAndroid Build Coastguard Worker 	int print;
4810*436bf2bcSAndroid Build Coastguard Worker 	int i;
4811*436bf2bcSAndroid Build Coastguard Worker 
4812*436bf2bcSAndroid Build Coastguard Worker 	switch (arg->type) {
4813*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_NULL:
4814*436bf2bcSAndroid Build Coastguard Worker 		/* ?? */
4815*436bf2bcSAndroid Build Coastguard Worker 		return;
4816*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_ATOM:
4817*436bf2bcSAndroid Build Coastguard Worker 		print_str_to_seq(s, format, len_arg, arg->atom.atom);
4818*436bf2bcSAndroid Build Coastguard Worker 		return;
4819*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_FIELD:
4820*436bf2bcSAndroid Build Coastguard Worker 		field = arg->field.field;
4821*436bf2bcSAndroid Build Coastguard Worker 		if (!field) {
4822*436bf2bcSAndroid Build Coastguard Worker 			field = tep_find_any_field(event, arg->field.name);
4823*436bf2bcSAndroid Build Coastguard Worker 			if (!field) {
4824*436bf2bcSAndroid Build Coastguard Worker 				str = arg->field.name;
4825*436bf2bcSAndroid Build Coastguard Worker 				goto out_warning_field;
4826*436bf2bcSAndroid Build Coastguard Worker 			}
4827*436bf2bcSAndroid Build Coastguard Worker 			arg->field.field = field;
4828*436bf2bcSAndroid Build Coastguard Worker 		}
4829*436bf2bcSAndroid Build Coastguard Worker 		/* Zero sized fields, mean the rest of the data */
4830*436bf2bcSAndroid Build Coastguard Worker 		len = field->size ? : size - field->offset;
4831*436bf2bcSAndroid Build Coastguard Worker 
4832*436bf2bcSAndroid Build Coastguard Worker 		/*
4833*436bf2bcSAndroid Build Coastguard Worker 		 * Some events pass in pointers. If this is not an array
4834*436bf2bcSAndroid Build Coastguard Worker 		 * and the size is the same as long_size, assume that it
4835*436bf2bcSAndroid Build Coastguard Worker 		 * is a pointer.
4836*436bf2bcSAndroid Build Coastguard Worker 		 */
4837*436bf2bcSAndroid Build Coastguard Worker 		if (!(field->flags & TEP_FIELD_IS_ARRAY) &&
4838*436bf2bcSAndroid Build Coastguard Worker 		    field->size == tep->long_size) {
4839*436bf2bcSAndroid Build Coastguard Worker 
4840*436bf2bcSAndroid Build Coastguard Worker 			/* Handle heterogeneous recording and processing
4841*436bf2bcSAndroid Build Coastguard Worker 			 * architectures
4842*436bf2bcSAndroid Build Coastguard Worker 			 *
4843*436bf2bcSAndroid Build Coastguard Worker 			 * CASE I:
4844*436bf2bcSAndroid Build Coastguard Worker 			 * Traces recorded on 32-bit devices (32-bit
4845*436bf2bcSAndroid Build Coastguard Worker 			 * addressing) and processed on 64-bit devices:
4846*436bf2bcSAndroid Build Coastguard Worker 			 * In this case, only 32 bits should be read.
4847*436bf2bcSAndroid Build Coastguard Worker 			 *
4848*436bf2bcSAndroid Build Coastguard Worker 			 * CASE II:
4849*436bf2bcSAndroid Build Coastguard Worker 			 * Traces recorded on 64 bit devices and processed
4850*436bf2bcSAndroid Build Coastguard Worker 			 * on 32-bit devices:
4851*436bf2bcSAndroid Build Coastguard Worker 			 * In this case, 64 bits must be read.
4852*436bf2bcSAndroid Build Coastguard Worker 			 */
4853*436bf2bcSAndroid Build Coastguard Worker 			addr = (tep->long_size == 8) ?
4854*436bf2bcSAndroid Build Coastguard Worker 				*(unsigned long long *)(data + field->offset) :
4855*436bf2bcSAndroid Build Coastguard Worker 				(unsigned long long)*(unsigned int *)(data + field->offset);
4856*436bf2bcSAndroid Build Coastguard Worker 
4857*436bf2bcSAndroid Build Coastguard Worker 			/* Check if it matches a print format */
4858*436bf2bcSAndroid Build Coastguard Worker 			printk = find_printk(tep, addr);
4859*436bf2bcSAndroid Build Coastguard Worker 			if (printk)
4860*436bf2bcSAndroid Build Coastguard Worker 				trace_seq_puts(s, printk->printk);
4861*436bf2bcSAndroid Build Coastguard Worker 			else
4862*436bf2bcSAndroid Build Coastguard Worker 				trace_seq_printf(s, "%llx", addr);
4863*436bf2bcSAndroid Build Coastguard Worker 			break;
4864*436bf2bcSAndroid Build Coastguard Worker 		}
4865*436bf2bcSAndroid Build Coastguard Worker 		str = malloc(len + 1);
4866*436bf2bcSAndroid Build Coastguard Worker 		if (!str) {
4867*436bf2bcSAndroid Build Coastguard Worker 			do_warning_event(event, "%s: not enough memory!",
4868*436bf2bcSAndroid Build Coastguard Worker 					 __func__);
4869*436bf2bcSAndroid Build Coastguard Worker 			return;
4870*436bf2bcSAndroid Build Coastguard Worker 		}
4871*436bf2bcSAndroid Build Coastguard Worker 		memcpy(str, data + field->offset, len);
4872*436bf2bcSAndroid Build Coastguard Worker 		str[len] = 0;
4873*436bf2bcSAndroid Build Coastguard Worker 		print_str_to_seq(s, format, len_arg, str);
4874*436bf2bcSAndroid Build Coastguard Worker 		free(str);
4875*436bf2bcSAndroid Build Coastguard Worker 		break;
4876*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_FLAGS:
4877*436bf2bcSAndroid Build Coastguard Worker 		val = eval_num_arg(data, size, event, arg->flags.field);
4878*436bf2bcSAndroid Build Coastguard Worker 		print = 0;
4879*436bf2bcSAndroid Build Coastguard Worker 		for (flag = arg->flags.flags; flag; flag = flag->next) {
4880*436bf2bcSAndroid Build Coastguard Worker 			fval = eval_flag(flag->value);
4881*436bf2bcSAndroid Build Coastguard Worker 			if (!val && fval < 0) {
4882*436bf2bcSAndroid Build Coastguard Worker 				print_str_to_seq(s, format, len_arg, flag->str);
4883*436bf2bcSAndroid Build Coastguard Worker 				break;
4884*436bf2bcSAndroid Build Coastguard Worker 			}
4885*436bf2bcSAndroid Build Coastguard Worker 			if (fval > 0 && (val & fval) == fval) {
4886*436bf2bcSAndroid Build Coastguard Worker 				if (print && arg->flags.delim)
4887*436bf2bcSAndroid Build Coastguard Worker 					trace_seq_puts(s, arg->flags.delim);
4888*436bf2bcSAndroid Build Coastguard Worker 				print_str_to_seq(s, format, len_arg, flag->str);
4889*436bf2bcSAndroid Build Coastguard Worker 				print = 1;
4890*436bf2bcSAndroid Build Coastguard Worker 				val &= ~fval;
4891*436bf2bcSAndroid Build Coastguard Worker 			}
4892*436bf2bcSAndroid Build Coastguard Worker 		}
4893*436bf2bcSAndroid Build Coastguard Worker 		if (val) {
4894*436bf2bcSAndroid Build Coastguard Worker 			if (print && arg->flags.delim)
4895*436bf2bcSAndroid Build Coastguard Worker 				trace_seq_puts(s, arg->flags.delim);
4896*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_printf(s, "0x%llx", val);
4897*436bf2bcSAndroid Build Coastguard Worker 		}
4898*436bf2bcSAndroid Build Coastguard Worker 		break;
4899*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_SYMBOL:
4900*436bf2bcSAndroid Build Coastguard Worker 		val = eval_num_arg(data, size, event, arg->symbol.field);
4901*436bf2bcSAndroid Build Coastguard Worker 		for (flag = arg->symbol.symbols; flag; flag = flag->next) {
4902*436bf2bcSAndroid Build Coastguard Worker 			fval = eval_flag(flag->value);
4903*436bf2bcSAndroid Build Coastguard Worker 			if (val == fval) {
4904*436bf2bcSAndroid Build Coastguard Worker 				print_str_to_seq(s, format, len_arg, flag->str);
4905*436bf2bcSAndroid Build Coastguard Worker 				break;
4906*436bf2bcSAndroid Build Coastguard Worker 			}
4907*436bf2bcSAndroid Build Coastguard Worker 		}
4908*436bf2bcSAndroid Build Coastguard Worker 		if (!flag)
4909*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_printf(s, "0x%llx", val);
4910*436bf2bcSAndroid Build Coastguard Worker 		break;
4911*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_HEX:
4912*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_HEX_STR:
4913*436bf2bcSAndroid Build Coastguard Worker 		if (arg->hex.field->type == TEP_PRINT_DYNAMIC_ARRAY) {
4914*436bf2bcSAndroid Build Coastguard Worker 			dynamic_offset_field(tep, arg->hex.field->dynarray.field, data,
4915*436bf2bcSAndroid Build Coastguard Worker 				             size, &offset, NULL);
4916*436bf2bcSAndroid Build Coastguard Worker 			hex = data + offset;
4917*436bf2bcSAndroid Build Coastguard Worker 		} else {
4918*436bf2bcSAndroid Build Coastguard Worker 			field = arg->hex.field->field.field;
4919*436bf2bcSAndroid Build Coastguard Worker 			if (!field) {
4920*436bf2bcSAndroid Build Coastguard Worker 				str = arg->hex.field->field.name;
4921*436bf2bcSAndroid Build Coastguard Worker 				field = tep_find_any_field(event, str);
4922*436bf2bcSAndroid Build Coastguard Worker 				if (!field)
4923*436bf2bcSAndroid Build Coastguard Worker 					goto out_warning_field;
4924*436bf2bcSAndroid Build Coastguard Worker 				arg->hex.field->field.field = field;
4925*436bf2bcSAndroid Build Coastguard Worker 			}
4926*436bf2bcSAndroid Build Coastguard Worker 			hex = data + field->offset;
4927*436bf2bcSAndroid Build Coastguard Worker 		}
4928*436bf2bcSAndroid Build Coastguard Worker 		len = eval_num_arg(data, size, event, arg->hex.size);
4929*436bf2bcSAndroid Build Coastguard Worker 		for (i = 0; i < len; i++) {
4930*436bf2bcSAndroid Build Coastguard Worker 			if (i && arg->type == TEP_PRINT_HEX)
4931*436bf2bcSAndroid Build Coastguard Worker 				trace_seq_putc(s, ' ');
4932*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_printf(s, "%02x", hex[i]);
4933*436bf2bcSAndroid Build Coastguard Worker 		}
4934*436bf2bcSAndroid Build Coastguard Worker 		break;
4935*436bf2bcSAndroid Build Coastguard Worker 
4936*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_INT_ARRAY: {
4937*436bf2bcSAndroid Build Coastguard Worker 		void *num;
4938*436bf2bcSAndroid Build Coastguard Worker 		int el_size;
4939*436bf2bcSAndroid Build Coastguard Worker 
4940*436bf2bcSAndroid Build Coastguard Worker 		if (arg->int_array.field->type == TEP_PRINT_DYNAMIC_ARRAY) {
4941*436bf2bcSAndroid Build Coastguard Worker 			dynamic_offset_field(tep, arg->int_array.field->dynarray.field, data,
4942*436bf2bcSAndroid Build Coastguard Worker 					     size, &offset, NULL);
4943*436bf2bcSAndroid Build Coastguard Worker 			num = data + offset;
4944*436bf2bcSAndroid Build Coastguard Worker 		} else {
4945*436bf2bcSAndroid Build Coastguard Worker 			field = arg->int_array.field->field.field;
4946*436bf2bcSAndroid Build Coastguard Worker 			if (!field) {
4947*436bf2bcSAndroid Build Coastguard Worker 				str = arg->int_array.field->field.name;
4948*436bf2bcSAndroid Build Coastguard Worker 				field = tep_find_any_field(event, str);
4949*436bf2bcSAndroid Build Coastguard Worker 				if (!field)
4950*436bf2bcSAndroid Build Coastguard Worker 					goto out_warning_field;
4951*436bf2bcSAndroid Build Coastguard Worker 				arg->int_array.field->field.field = field;
4952*436bf2bcSAndroid Build Coastguard Worker 			}
4953*436bf2bcSAndroid Build Coastguard Worker 			num = data + field->offset;
4954*436bf2bcSAndroid Build Coastguard Worker 		}
4955*436bf2bcSAndroid Build Coastguard Worker 		len = eval_num_arg(data, size, event, arg->int_array.count);
4956*436bf2bcSAndroid Build Coastguard Worker 		el_size = eval_num_arg(data, size, event,
4957*436bf2bcSAndroid Build Coastguard Worker 				       arg->int_array.el_size);
4958*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_putc(s, '{');
4959*436bf2bcSAndroid Build Coastguard Worker 		for (i = 0; i < len; i++) {
4960*436bf2bcSAndroid Build Coastguard Worker 			if (i)
4961*436bf2bcSAndroid Build Coastguard Worker 				trace_seq_putc(s, ',');
4962*436bf2bcSAndroid Build Coastguard Worker 
4963*436bf2bcSAndroid Build Coastguard Worker 			if (el_size == 1) {
4964*436bf2bcSAndroid Build Coastguard Worker 				trace_seq_printf(s, "0x%x", *(uint8_t *)num);
4965*436bf2bcSAndroid Build Coastguard Worker 			} else if (el_size == 2) {
4966*436bf2bcSAndroid Build Coastguard Worker 				trace_seq_printf(s, "0x%x", *(uint16_t *)num);
4967*436bf2bcSAndroid Build Coastguard Worker 			} else if (el_size == 4) {
4968*436bf2bcSAndroid Build Coastguard Worker 				trace_seq_printf(s, "0x%x", *(uint32_t *)num);
4969*436bf2bcSAndroid Build Coastguard Worker 			} else if (el_size == 8) {
4970*436bf2bcSAndroid Build Coastguard Worker 				trace_seq_printf(s, "0x%"PRIx64, *(uint64_t *)num);
4971*436bf2bcSAndroid Build Coastguard Worker 			} else {
4972*436bf2bcSAndroid Build Coastguard Worker 				trace_seq_printf(s, "BAD SIZE:%d 0x%x",
4973*436bf2bcSAndroid Build Coastguard Worker 						 el_size, *(uint8_t *)num);
4974*436bf2bcSAndroid Build Coastguard Worker 				el_size = 1;
4975*436bf2bcSAndroid Build Coastguard Worker 			}
4976*436bf2bcSAndroid Build Coastguard Worker 
4977*436bf2bcSAndroid Build Coastguard Worker 			num += el_size;
4978*436bf2bcSAndroid Build Coastguard Worker 		}
4979*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_putc(s, '}');
4980*436bf2bcSAndroid Build Coastguard Worker 		break;
4981*436bf2bcSAndroid Build Coastguard Worker 	}
4982*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_TYPE:
4983*436bf2bcSAndroid Build Coastguard Worker 		break;
4984*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_STRING: {
4985*436bf2bcSAndroid Build Coastguard Worker 		if (!arg->string.field) {
4986*436bf2bcSAndroid Build Coastguard Worker 			arg->string.field = tep_find_any_field(event, arg->string.string);
4987*436bf2bcSAndroid Build Coastguard Worker 			if (!arg->string.field)
4988*436bf2bcSAndroid Build Coastguard Worker 				break;
4989*436bf2bcSAndroid Build Coastguard Worker 			arg->string.offset = arg->string.field->offset;
4990*436bf2bcSAndroid Build Coastguard Worker 		}
4991*436bf2bcSAndroid Build Coastguard Worker 		dynamic_offset_field(tep, arg->string.field, data, size, &offset, &len);
4992*436bf2bcSAndroid Build Coastguard Worker 		/* Do not attempt to save zero length dynamic strings */
4993*436bf2bcSAndroid Build Coastguard Worker 		if (!len)
4994*436bf2bcSAndroid Build Coastguard Worker 			break;
4995*436bf2bcSAndroid Build Coastguard Worker 		print_str_to_seq(s, format, len_arg, ((char *)data) + offset);
4996*436bf2bcSAndroid Build Coastguard Worker 		break;
4997*436bf2bcSAndroid Build Coastguard Worker 	}
4998*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_BSTRING:
4999*436bf2bcSAndroid Build Coastguard Worker 		print_str_to_seq(s, format, len_arg, arg->string.string);
5000*436bf2bcSAndroid Build Coastguard Worker 		break;
5001*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_BITMASK: {
5002*436bf2bcSAndroid Build Coastguard Worker 		if (!arg->bitmask.field) {
5003*436bf2bcSAndroid Build Coastguard Worker 			arg->bitmask.field = tep_find_any_field(event, arg->bitmask.bitmask);
5004*436bf2bcSAndroid Build Coastguard Worker 			if (!arg->bitmask.field)
5005*436bf2bcSAndroid Build Coastguard Worker 				break;
5006*436bf2bcSAndroid Build Coastguard Worker 			arg->bitmask.offset = arg->bitmask.field->offset;
5007*436bf2bcSAndroid Build Coastguard Worker 		}
5008*436bf2bcSAndroid Build Coastguard Worker 		dynamic_offset_field(tep, arg->bitmask.field, data, size, &offset, &len);
5009*436bf2bcSAndroid Build Coastguard Worker 		print_bitmask_to_seq(tep, s, format, len_arg,
5010*436bf2bcSAndroid Build Coastguard Worker 				     data + offset, len);
5011*436bf2bcSAndroid Build Coastguard Worker 		break;
5012*436bf2bcSAndroid Build Coastguard Worker 	}
5013*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_CPUMASK: {
5014*436bf2bcSAndroid Build Coastguard Worker 		if (!arg->bitmask.field) {
5015*436bf2bcSAndroid Build Coastguard Worker 			arg->bitmask.field = tep_find_any_field(event, arg->bitmask.bitmask);
5016*436bf2bcSAndroid Build Coastguard Worker 			arg->bitmask.offset = arg->bitmask.field->offset;
5017*436bf2bcSAndroid Build Coastguard Worker 		}
5018*436bf2bcSAndroid Build Coastguard Worker 		if (!arg->bitmask.field)
5019*436bf2bcSAndroid Build Coastguard Worker 			break;
5020*436bf2bcSAndroid Build Coastguard Worker 		dynamic_offset_field(tep, arg->bitmask.field, data, size, &offset, &len);
5021*436bf2bcSAndroid Build Coastguard Worker 		print_cpumask_to_seq(tep, s, format, len_arg,
5022*436bf2bcSAndroid Build Coastguard Worker 				     data + offset, len);
5023*436bf2bcSAndroid Build Coastguard Worker 		break;
5024*436bf2bcSAndroid Build Coastguard Worker 	}
5025*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_OP:
5026*436bf2bcSAndroid Build Coastguard Worker 		/*
5027*436bf2bcSAndroid Build Coastguard Worker 		 * The only op for string should be ? :
5028*436bf2bcSAndroid Build Coastguard Worker 		 */
5029*436bf2bcSAndroid Build Coastguard Worker 		if (arg->op.op[0] != '?')
5030*436bf2bcSAndroid Build Coastguard Worker 			return;
5031*436bf2bcSAndroid Build Coastguard Worker 		val = eval_num_arg(data, size, event, arg->op.left);
5032*436bf2bcSAndroid Build Coastguard Worker 		if (val)
5033*436bf2bcSAndroid Build Coastguard Worker 			print_str_arg(s, data, size, event,
5034*436bf2bcSAndroid Build Coastguard Worker 				      format, len_arg, arg->op.right->op.left);
5035*436bf2bcSAndroid Build Coastguard Worker 		else
5036*436bf2bcSAndroid Build Coastguard Worker 			print_str_arg(s, data, size, event,
5037*436bf2bcSAndroid Build Coastguard Worker 				      format, len_arg, arg->op.right->op.right);
5038*436bf2bcSAndroid Build Coastguard Worker 		break;
5039*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_FUNC:
5040*436bf2bcSAndroid Build Coastguard Worker 		process_defined_func(s, data, size, event, arg);
5041*436bf2bcSAndroid Build Coastguard Worker 		break;
5042*436bf2bcSAndroid Build Coastguard Worker 	default:
5043*436bf2bcSAndroid Build Coastguard Worker 		/* well... */
5044*436bf2bcSAndroid Build Coastguard Worker 		break;
5045*436bf2bcSAndroid Build Coastguard Worker 	}
5046*436bf2bcSAndroid Build Coastguard Worker 
5047*436bf2bcSAndroid Build Coastguard Worker 	return;
5048*436bf2bcSAndroid Build Coastguard Worker 
5049*436bf2bcSAndroid Build Coastguard Worker out_warning_field:
5050*436bf2bcSAndroid Build Coastguard Worker 	do_warning_event(event, "%s: field %s not found",
5051*436bf2bcSAndroid Build Coastguard Worker 			 __func__, arg->field.name);
5052*436bf2bcSAndroid Build Coastguard Worker }
5053*436bf2bcSAndroid Build Coastguard Worker 
5054*436bf2bcSAndroid Build Coastguard Worker static unsigned long long
process_defined_func(struct trace_seq * s,void * data,int size,struct tep_event * event,struct tep_print_arg * arg)5055*436bf2bcSAndroid Build Coastguard Worker process_defined_func(struct trace_seq *s, void *data, int size,
5056*436bf2bcSAndroid Build Coastguard Worker 		     struct tep_event *event, struct tep_print_arg *arg)
5057*436bf2bcSAndroid Build Coastguard Worker {
5058*436bf2bcSAndroid Build Coastguard Worker 	struct tep_function_handler *func_handle = arg->func.func;
5059*436bf2bcSAndroid Build Coastguard Worker 	struct func_params *param;
5060*436bf2bcSAndroid Build Coastguard Worker 	unsigned long long *args;
5061*436bf2bcSAndroid Build Coastguard Worker 	unsigned long long ret;
5062*436bf2bcSAndroid Build Coastguard Worker 	struct tep_print_arg *farg;
5063*436bf2bcSAndroid Build Coastguard Worker 	struct trace_seq str;
5064*436bf2bcSAndroid Build Coastguard Worker 	struct save_str {
5065*436bf2bcSAndroid Build Coastguard Worker 		struct save_str *next;
5066*436bf2bcSAndroid Build Coastguard Worker 		char *str;
5067*436bf2bcSAndroid Build Coastguard Worker 	} *strings = NULL, *string;
5068*436bf2bcSAndroid Build Coastguard Worker 	int i;
5069*436bf2bcSAndroid Build Coastguard Worker 
5070*436bf2bcSAndroid Build Coastguard Worker 	if (!func_handle->nr_args) {
5071*436bf2bcSAndroid Build Coastguard Worker 		ret = (*func_handle->func)(s, NULL);
5072*436bf2bcSAndroid Build Coastguard Worker 		goto out;
5073*436bf2bcSAndroid Build Coastguard Worker 	}
5074*436bf2bcSAndroid Build Coastguard Worker 
5075*436bf2bcSAndroid Build Coastguard Worker 	farg = arg->func.args;
5076*436bf2bcSAndroid Build Coastguard Worker 	param = func_handle->params;
5077*436bf2bcSAndroid Build Coastguard Worker 
5078*436bf2bcSAndroid Build Coastguard Worker 	ret = ULLONG_MAX;
5079*436bf2bcSAndroid Build Coastguard Worker 	args = malloc(sizeof(*args) * func_handle->nr_args);
5080*436bf2bcSAndroid Build Coastguard Worker 	if (!args)
5081*436bf2bcSAndroid Build Coastguard Worker 		goto out;
5082*436bf2bcSAndroid Build Coastguard Worker 
5083*436bf2bcSAndroid Build Coastguard Worker 	for (i = 0; i < func_handle->nr_args; i++) {
5084*436bf2bcSAndroid Build Coastguard Worker 		switch (param->type) {
5085*436bf2bcSAndroid Build Coastguard Worker 		case TEP_FUNC_ARG_INT:
5086*436bf2bcSAndroid Build Coastguard Worker 		case TEP_FUNC_ARG_LONG:
5087*436bf2bcSAndroid Build Coastguard Worker 		case TEP_FUNC_ARG_PTR:
5088*436bf2bcSAndroid Build Coastguard Worker 			args[i] = eval_num_arg(data, size, event, farg);
5089*436bf2bcSAndroid Build Coastguard Worker 			break;
5090*436bf2bcSAndroid Build Coastguard Worker 		case TEP_FUNC_ARG_STRING:
5091*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_init(&str);
5092*436bf2bcSAndroid Build Coastguard Worker 			print_str_arg(&str, data, size, event, "%s", -1, farg);
5093*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_terminate(&str);
5094*436bf2bcSAndroid Build Coastguard Worker 			string = malloc(sizeof(*string));
5095*436bf2bcSAndroid Build Coastguard Worker 			if (!string) {
5096*436bf2bcSAndroid Build Coastguard Worker 				do_warning_event(event, "%s(%d): malloc str",
5097*436bf2bcSAndroid Build Coastguard Worker 						 __func__, __LINE__);
5098*436bf2bcSAndroid Build Coastguard Worker 				goto out_free;
5099*436bf2bcSAndroid Build Coastguard Worker 			}
5100*436bf2bcSAndroid Build Coastguard Worker 			string->next = strings;
5101*436bf2bcSAndroid Build Coastguard Worker 			string->str = strdup(str.buffer);
5102*436bf2bcSAndroid Build Coastguard Worker 			if (!string->str) {
5103*436bf2bcSAndroid Build Coastguard Worker 				free(string);
5104*436bf2bcSAndroid Build Coastguard Worker 				do_warning_event(event, "%s(%d): malloc str",
5105*436bf2bcSAndroid Build Coastguard Worker 						 __func__, __LINE__);
5106*436bf2bcSAndroid Build Coastguard Worker 				goto out_free;
5107*436bf2bcSAndroid Build Coastguard Worker 			}
5108*436bf2bcSAndroid Build Coastguard Worker 			args[i] = (uintptr_t)string->str;
5109*436bf2bcSAndroid Build Coastguard Worker 			strings = string;
5110*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_destroy(&str);
5111*436bf2bcSAndroid Build Coastguard Worker 			break;
5112*436bf2bcSAndroid Build Coastguard Worker 		default:
5113*436bf2bcSAndroid Build Coastguard Worker 			/*
5114*436bf2bcSAndroid Build Coastguard Worker 			 * Something went totally wrong, this is not
5115*436bf2bcSAndroid Build Coastguard Worker 			 * an input error, something in this code broke.
5116*436bf2bcSAndroid Build Coastguard Worker 			 */
5117*436bf2bcSAndroid Build Coastguard Worker 			do_warning_event(event, "Unexpected end of arguments\n");
5118*436bf2bcSAndroid Build Coastguard Worker 			goto out_free;
5119*436bf2bcSAndroid Build Coastguard Worker 		}
5120*436bf2bcSAndroid Build Coastguard Worker 		farg = farg->next;
5121*436bf2bcSAndroid Build Coastguard Worker 		param = param->next;
5122*436bf2bcSAndroid Build Coastguard Worker 	}
5123*436bf2bcSAndroid Build Coastguard Worker 
5124*436bf2bcSAndroid Build Coastguard Worker 	ret = (*func_handle->func)(s, args);
5125*436bf2bcSAndroid Build Coastguard Worker out_free:
5126*436bf2bcSAndroid Build Coastguard Worker 	free(args);
5127*436bf2bcSAndroid Build Coastguard Worker 	while (strings) {
5128*436bf2bcSAndroid Build Coastguard Worker 		string = strings;
5129*436bf2bcSAndroid Build Coastguard Worker 		strings = string->next;
5130*436bf2bcSAndroid Build Coastguard Worker 		free(string->str);
5131*436bf2bcSAndroid Build Coastguard Worker 		free(string);
5132*436bf2bcSAndroid Build Coastguard Worker 	}
5133*436bf2bcSAndroid Build Coastguard Worker 
5134*436bf2bcSAndroid Build Coastguard Worker  out:
5135*436bf2bcSAndroid Build Coastguard Worker 	/* TBD : handle return type here */
5136*436bf2bcSAndroid Build Coastguard Worker 	return ret;
5137*436bf2bcSAndroid Build Coastguard Worker }
5138*436bf2bcSAndroid Build Coastguard Worker 
free_args(struct tep_print_arg * args)5139*436bf2bcSAndroid Build Coastguard Worker static void free_args(struct tep_print_arg *args)
5140*436bf2bcSAndroid Build Coastguard Worker {
5141*436bf2bcSAndroid Build Coastguard Worker 	struct tep_print_arg *next;
5142*436bf2bcSAndroid Build Coastguard Worker 
5143*436bf2bcSAndroid Build Coastguard Worker 	while (args) {
5144*436bf2bcSAndroid Build Coastguard Worker 		next = args->next;
5145*436bf2bcSAndroid Build Coastguard Worker 
5146*436bf2bcSAndroid Build Coastguard Worker 		free_arg(args);
5147*436bf2bcSAndroid Build Coastguard Worker 		args = next;
5148*436bf2bcSAndroid Build Coastguard Worker 	}
5149*436bf2bcSAndroid Build Coastguard Worker }
5150*436bf2bcSAndroid Build Coastguard Worker 
make_bprint_args(char * fmt,void * data,int size,struct tep_event * event)5151*436bf2bcSAndroid Build Coastguard Worker static struct tep_print_arg *make_bprint_args(char *fmt, void *data, int size, struct tep_event *event)
5152*436bf2bcSAndroid Build Coastguard Worker {
5153*436bf2bcSAndroid Build Coastguard Worker 	struct tep_handle *tep = event->tep;
5154*436bf2bcSAndroid Build Coastguard Worker 	struct tep_format_field *field, *ip_field;
5155*436bf2bcSAndroid Build Coastguard Worker 	struct tep_print_arg *args, *arg, **next;
5156*436bf2bcSAndroid Build Coastguard Worker 	unsigned long long ip, val;
5157*436bf2bcSAndroid Build Coastguard Worker 	char *ptr;
5158*436bf2bcSAndroid Build Coastguard Worker 	void *bptr;
5159*436bf2bcSAndroid Build Coastguard Worker 	int vsize = 0;
5160*436bf2bcSAndroid Build Coastguard Worker 
5161*436bf2bcSAndroid Build Coastguard Worker 	field = tep->bprint_buf_field;
5162*436bf2bcSAndroid Build Coastguard Worker 	ip_field = tep->bprint_ip_field;
5163*436bf2bcSAndroid Build Coastguard Worker 
5164*436bf2bcSAndroid Build Coastguard Worker 	if (!field) {
5165*436bf2bcSAndroid Build Coastguard Worker 		field = tep_find_field(event, "buf");
5166*436bf2bcSAndroid Build Coastguard Worker 		if (!field) {
5167*436bf2bcSAndroid Build Coastguard Worker 			do_warning_event(event, "can't find buffer field for binary printk");
5168*436bf2bcSAndroid Build Coastguard Worker 			return NULL;
5169*436bf2bcSAndroid Build Coastguard Worker 		}
5170*436bf2bcSAndroid Build Coastguard Worker 		ip_field = tep_find_field(event, "ip");
5171*436bf2bcSAndroid Build Coastguard Worker 		if (!ip_field) {
5172*436bf2bcSAndroid Build Coastguard Worker 			do_warning_event(event, "can't find ip field for binary printk");
5173*436bf2bcSAndroid Build Coastguard Worker 			return NULL;
5174*436bf2bcSAndroid Build Coastguard Worker 		}
5175*436bf2bcSAndroid Build Coastguard Worker 		tep->bprint_buf_field = field;
5176*436bf2bcSAndroid Build Coastguard Worker 		tep->bprint_ip_field = ip_field;
5177*436bf2bcSAndroid Build Coastguard Worker 	}
5178*436bf2bcSAndroid Build Coastguard Worker 
5179*436bf2bcSAndroid Build Coastguard Worker 	ip = tep_read_number(tep, data + ip_field->offset, ip_field->size);
5180*436bf2bcSAndroid Build Coastguard Worker 
5181*436bf2bcSAndroid Build Coastguard Worker 	/*
5182*436bf2bcSAndroid Build Coastguard Worker 	 * The first arg is the IP pointer.
5183*436bf2bcSAndroid Build Coastguard Worker 	 */
5184*436bf2bcSAndroid Build Coastguard Worker 	args = alloc_arg();
5185*436bf2bcSAndroid Build Coastguard Worker 	if (!args) {
5186*436bf2bcSAndroid Build Coastguard Worker 		do_warning_event(event, "%s(%d): not enough memory!",
5187*436bf2bcSAndroid Build Coastguard Worker 				 __func__, __LINE__);
5188*436bf2bcSAndroid Build Coastguard Worker 		return NULL;
5189*436bf2bcSAndroid Build Coastguard Worker 	}
5190*436bf2bcSAndroid Build Coastguard Worker 	arg = args;
5191*436bf2bcSAndroid Build Coastguard Worker 	arg->next = NULL;
5192*436bf2bcSAndroid Build Coastguard Worker 	next = &arg->next;
5193*436bf2bcSAndroid Build Coastguard Worker 
5194*436bf2bcSAndroid Build Coastguard Worker 	arg->type = TEP_PRINT_ATOM;
5195*436bf2bcSAndroid Build Coastguard Worker 
5196*436bf2bcSAndroid Build Coastguard Worker 	if (asprintf(&arg->atom.atom, "%lld", ip) < 0)
5197*436bf2bcSAndroid Build Coastguard Worker 		goto out_free;
5198*436bf2bcSAndroid Build Coastguard Worker 
5199*436bf2bcSAndroid Build Coastguard Worker 	/* skip the first "%ps: " */
5200*436bf2bcSAndroid Build Coastguard Worker 	for (ptr = fmt + 5, bptr = data + field->offset;
5201*436bf2bcSAndroid Build Coastguard Worker 	     bptr < data + size && *ptr; ptr++) {
5202*436bf2bcSAndroid Build Coastguard Worker 		int ls = 0;
5203*436bf2bcSAndroid Build Coastguard Worker 
5204*436bf2bcSAndroid Build Coastguard Worker 		if (*ptr == '%') {
5205*436bf2bcSAndroid Build Coastguard Worker  process_again:
5206*436bf2bcSAndroid Build Coastguard Worker 			ptr++;
5207*436bf2bcSAndroid Build Coastguard Worker 			switch (*ptr) {
5208*436bf2bcSAndroid Build Coastguard Worker 			case '%':
5209*436bf2bcSAndroid Build Coastguard Worker 				break;
5210*436bf2bcSAndroid Build Coastguard Worker 			case 'l':
5211*436bf2bcSAndroid Build Coastguard Worker 				ls++;
5212*436bf2bcSAndroid Build Coastguard Worker 				goto process_again;
5213*436bf2bcSAndroid Build Coastguard Worker 			case 'L':
5214*436bf2bcSAndroid Build Coastguard Worker 				ls = 2;
5215*436bf2bcSAndroid Build Coastguard Worker 				goto process_again;
5216*436bf2bcSAndroid Build Coastguard Worker 			case '0' ... '9':
5217*436bf2bcSAndroid Build Coastguard Worker 			case '.':
5218*436bf2bcSAndroid Build Coastguard Worker 			case '#':
5219*436bf2bcSAndroid Build Coastguard Worker 			case '+':
5220*436bf2bcSAndroid Build Coastguard Worker 				goto process_again;
5221*436bf2bcSAndroid Build Coastguard Worker 			case 'z':
5222*436bf2bcSAndroid Build Coastguard Worker 			case 'Z':
5223*436bf2bcSAndroid Build Coastguard Worker 				ls = 1;
5224*436bf2bcSAndroid Build Coastguard Worker 				goto process_again;
5225*436bf2bcSAndroid Build Coastguard Worker 			case 'p':
5226*436bf2bcSAndroid Build Coastguard Worker 				ls = 1;
5227*436bf2bcSAndroid Build Coastguard Worker 				if (isalnum(ptr[1])) {
5228*436bf2bcSAndroid Build Coastguard Worker 					ptr++;
5229*436bf2bcSAndroid Build Coastguard Worker 					/* Check for special pointers */
5230*436bf2bcSAndroid Build Coastguard Worker 					switch (*ptr) {
5231*436bf2bcSAndroid Build Coastguard Worker 					case 's':
5232*436bf2bcSAndroid Build Coastguard Worker 					case 'S':
5233*436bf2bcSAndroid Build Coastguard Worker 					case 'x':
5234*436bf2bcSAndroid Build Coastguard Worker 						break;
5235*436bf2bcSAndroid Build Coastguard Worker 					case 'f':
5236*436bf2bcSAndroid Build Coastguard Worker 					case 'F':
5237*436bf2bcSAndroid Build Coastguard Worker 						/*
5238*436bf2bcSAndroid Build Coastguard Worker 						 * Pre-5.5 kernels use %pf and
5239*436bf2bcSAndroid Build Coastguard Worker 						 * %pF for printing symbols
5240*436bf2bcSAndroid Build Coastguard Worker 						 * while kernels since 5.5 use
5241*436bf2bcSAndroid Build Coastguard Worker 						 * %pfw for fwnodes. So check
5242*436bf2bcSAndroid Build Coastguard Worker 						 * %p[fF] isn't followed by 'w'.
5243*436bf2bcSAndroid Build Coastguard Worker 						 */
5244*436bf2bcSAndroid Build Coastguard Worker 						if (ptr[1] != 'w')
5245*436bf2bcSAndroid Build Coastguard Worker 							break;
5246*436bf2bcSAndroid Build Coastguard Worker 						/* fall through */
5247*436bf2bcSAndroid Build Coastguard Worker 					default:
5248*436bf2bcSAndroid Build Coastguard Worker 						/*
5249*436bf2bcSAndroid Build Coastguard Worker 						 * Older kernels do not process
5250*436bf2bcSAndroid Build Coastguard Worker 						 * dereferenced pointers.
5251*436bf2bcSAndroid Build Coastguard Worker 						 * Only process if the pointer
5252*436bf2bcSAndroid Build Coastguard Worker 						 * value is a printable.
5253*436bf2bcSAndroid Build Coastguard Worker 						 */
5254*436bf2bcSAndroid Build Coastguard Worker 						if (isprint(*(char *)bptr))
5255*436bf2bcSAndroid Build Coastguard Worker 							goto process_string;
5256*436bf2bcSAndroid Build Coastguard Worker 					}
5257*436bf2bcSAndroid Build Coastguard Worker 				}
5258*436bf2bcSAndroid Build Coastguard Worker 				/* fall through */
5259*436bf2bcSAndroid Build Coastguard Worker 			case 'd':
5260*436bf2bcSAndroid Build Coastguard Worker 			case 'u':
5261*436bf2bcSAndroid Build Coastguard Worker 			case 'i':
5262*436bf2bcSAndroid Build Coastguard Worker 			case 'x':
5263*436bf2bcSAndroid Build Coastguard Worker 			case 'X':
5264*436bf2bcSAndroid Build Coastguard Worker 			case 'o':
5265*436bf2bcSAndroid Build Coastguard Worker 				switch (ls) {
5266*436bf2bcSAndroid Build Coastguard Worker 				case 0:
5267*436bf2bcSAndroid Build Coastguard Worker 					vsize = 4;
5268*436bf2bcSAndroid Build Coastguard Worker 					break;
5269*436bf2bcSAndroid Build Coastguard Worker 				case 1:
5270*436bf2bcSAndroid Build Coastguard Worker 					vsize = tep->long_size;
5271*436bf2bcSAndroid Build Coastguard Worker 					break;
5272*436bf2bcSAndroid Build Coastguard Worker 				case 2:
5273*436bf2bcSAndroid Build Coastguard Worker 					vsize = 8;
5274*436bf2bcSAndroid Build Coastguard Worker 					break;
5275*436bf2bcSAndroid Build Coastguard Worker 				default:
5276*436bf2bcSAndroid Build Coastguard Worker 					vsize = ls; /* ? */
5277*436bf2bcSAndroid Build Coastguard Worker 					break;
5278*436bf2bcSAndroid Build Coastguard Worker 				}
5279*436bf2bcSAndroid Build Coastguard Worker 			/* fall through */
5280*436bf2bcSAndroid Build Coastguard Worker 			case '*':
5281*436bf2bcSAndroid Build Coastguard Worker 				if (*ptr == '*')
5282*436bf2bcSAndroid Build Coastguard Worker 					vsize = 4;
5283*436bf2bcSAndroid Build Coastguard Worker 
5284*436bf2bcSAndroid Build Coastguard Worker 				/* the pointers are always 4 bytes aligned */
5285*436bf2bcSAndroid Build Coastguard Worker 				bptr = (void *)(((unsigned long)bptr + 3) &
5286*436bf2bcSAndroid Build Coastguard Worker 						~3);
5287*436bf2bcSAndroid Build Coastguard Worker 				val = tep_read_number(tep, bptr, vsize);
5288*436bf2bcSAndroid Build Coastguard Worker 				bptr += vsize;
5289*436bf2bcSAndroid Build Coastguard Worker 				arg = alloc_arg();
5290*436bf2bcSAndroid Build Coastguard Worker 				if (!arg) {
5291*436bf2bcSAndroid Build Coastguard Worker 					do_warning_event(event, "%s(%d): not enough memory!",
5292*436bf2bcSAndroid Build Coastguard Worker 						   __func__, __LINE__);
5293*436bf2bcSAndroid Build Coastguard Worker 					goto out_free;
5294*436bf2bcSAndroid Build Coastguard Worker 				}
5295*436bf2bcSAndroid Build Coastguard Worker 				arg->next = NULL;
5296*436bf2bcSAndroid Build Coastguard Worker 				arg->type = TEP_PRINT_ATOM;
5297*436bf2bcSAndroid Build Coastguard Worker 				if (asprintf(&arg->atom.atom, "%lld", val) < 0) {
5298*436bf2bcSAndroid Build Coastguard Worker 					free(arg);
5299*436bf2bcSAndroid Build Coastguard Worker 					goto out_free;
5300*436bf2bcSAndroid Build Coastguard Worker 				}
5301*436bf2bcSAndroid Build Coastguard Worker 				*next = arg;
5302*436bf2bcSAndroid Build Coastguard Worker 				next = &arg->next;
5303*436bf2bcSAndroid Build Coastguard Worker 				/*
5304*436bf2bcSAndroid Build Coastguard Worker 				 * The '*' case means that an arg is used as the length.
5305*436bf2bcSAndroid Build Coastguard Worker 				 * We need to continue to figure out for what.
5306*436bf2bcSAndroid Build Coastguard Worker 				 */
5307*436bf2bcSAndroid Build Coastguard Worker 				if (*ptr == '*')
5308*436bf2bcSAndroid Build Coastguard Worker 					goto process_again;
5309*436bf2bcSAndroid Build Coastguard Worker 
5310*436bf2bcSAndroid Build Coastguard Worker 				break;
5311*436bf2bcSAndroid Build Coastguard Worker 			case 's':
5312*436bf2bcSAndroid Build Coastguard Worker  process_string:
5313*436bf2bcSAndroid Build Coastguard Worker 				arg = alloc_arg();
5314*436bf2bcSAndroid Build Coastguard Worker 				if (!arg) {
5315*436bf2bcSAndroid Build Coastguard Worker 					do_warning_event(event, "%s(%d): not enough memory!",
5316*436bf2bcSAndroid Build Coastguard Worker 						   __func__, __LINE__);
5317*436bf2bcSAndroid Build Coastguard Worker 					goto out_free;
5318*436bf2bcSAndroid Build Coastguard Worker 				}
5319*436bf2bcSAndroid Build Coastguard Worker 				arg->next = NULL;
5320*436bf2bcSAndroid Build Coastguard Worker 				arg->type = TEP_PRINT_BSTRING;
5321*436bf2bcSAndroid Build Coastguard Worker 				arg->string.string = strdup(bptr);
5322*436bf2bcSAndroid Build Coastguard Worker 				if (!arg->string.string) {
5323*436bf2bcSAndroid Build Coastguard Worker 					free(arg);
5324*436bf2bcSAndroid Build Coastguard Worker 					goto out_free;
5325*436bf2bcSAndroid Build Coastguard Worker 				}
5326*436bf2bcSAndroid Build Coastguard Worker 				bptr += strlen(bptr) + 1;
5327*436bf2bcSAndroid Build Coastguard Worker 				*next = arg;
5328*436bf2bcSAndroid Build Coastguard Worker 				next = &arg->next;
5329*436bf2bcSAndroid Build Coastguard Worker 			default:
5330*436bf2bcSAndroid Build Coastguard Worker 				break;
5331*436bf2bcSAndroid Build Coastguard Worker 			}
5332*436bf2bcSAndroid Build Coastguard Worker 		}
5333*436bf2bcSAndroid Build Coastguard Worker 	}
5334*436bf2bcSAndroid Build Coastguard Worker 
5335*436bf2bcSAndroid Build Coastguard Worker 	return args;
5336*436bf2bcSAndroid Build Coastguard Worker 
5337*436bf2bcSAndroid Build Coastguard Worker out_free:
5338*436bf2bcSAndroid Build Coastguard Worker 	free_args(args);
5339*436bf2bcSAndroid Build Coastguard Worker 	return NULL;
5340*436bf2bcSAndroid Build Coastguard Worker }
5341*436bf2bcSAndroid Build Coastguard Worker 
5342*436bf2bcSAndroid Build Coastguard Worker static char *
get_bprint_format(void * data,int size __maybe_unused,struct tep_event * event)5343*436bf2bcSAndroid Build Coastguard Worker get_bprint_format(void *data, int size __maybe_unused,
5344*436bf2bcSAndroid Build Coastguard Worker 		  struct tep_event *event)
5345*436bf2bcSAndroid Build Coastguard Worker {
5346*436bf2bcSAndroid Build Coastguard Worker 	struct tep_handle *tep = event->tep;
5347*436bf2bcSAndroid Build Coastguard Worker 	unsigned long long addr;
5348*436bf2bcSAndroid Build Coastguard Worker 	struct tep_format_field *field;
5349*436bf2bcSAndroid Build Coastguard Worker 	struct printk_map *printk;
5350*436bf2bcSAndroid Build Coastguard Worker 	char *format;
5351*436bf2bcSAndroid Build Coastguard Worker 
5352*436bf2bcSAndroid Build Coastguard Worker 	field = tep->bprint_fmt_field;
5353*436bf2bcSAndroid Build Coastguard Worker 
5354*436bf2bcSAndroid Build Coastguard Worker 	if (!field) {
5355*436bf2bcSAndroid Build Coastguard Worker 		field = tep_find_field(event, "fmt");
5356*436bf2bcSAndroid Build Coastguard Worker 		if (!field) {
5357*436bf2bcSAndroid Build Coastguard Worker 			do_warning_event(event, "can't find format field for binary printk");
5358*436bf2bcSAndroid Build Coastguard Worker 			return NULL;
5359*436bf2bcSAndroid Build Coastguard Worker 		}
5360*436bf2bcSAndroid Build Coastguard Worker 		tep->bprint_fmt_field = field;
5361*436bf2bcSAndroid Build Coastguard Worker 	}
5362*436bf2bcSAndroid Build Coastguard Worker 
5363*436bf2bcSAndroid Build Coastguard Worker 	addr = tep_read_number(tep, data + field->offset, field->size);
5364*436bf2bcSAndroid Build Coastguard Worker 
5365*436bf2bcSAndroid Build Coastguard Worker 	printk = find_printk(tep, addr);
5366*436bf2bcSAndroid Build Coastguard Worker 	if (!printk) {
5367*436bf2bcSAndroid Build Coastguard Worker 		if (asprintf(&format, "%%ps: (NO FORMAT FOUND at %llx)\n", addr) < 0)
5368*436bf2bcSAndroid Build Coastguard Worker 			return NULL;
5369*436bf2bcSAndroid Build Coastguard Worker 		return format;
5370*436bf2bcSAndroid Build Coastguard Worker 	}
5371*436bf2bcSAndroid Build Coastguard Worker 
5372*436bf2bcSAndroid Build Coastguard Worker 	if (asprintf(&format, "%s: %s", "%ps", printk->printk) < 0)
5373*436bf2bcSAndroid Build Coastguard Worker 		return NULL;
5374*436bf2bcSAndroid Build Coastguard Worker 
5375*436bf2bcSAndroid Build Coastguard Worker 	return format;
5376*436bf2bcSAndroid Build Coastguard Worker }
5377*436bf2bcSAndroid Build Coastguard Worker 
print_mac_arg(struct trace_seq * s,const char * format,void * data,int size,struct tep_event * event,struct tep_print_arg * arg)5378*436bf2bcSAndroid Build Coastguard Worker static int print_mac_arg(struct trace_seq *s, const char *format,
5379*436bf2bcSAndroid Build Coastguard Worker 			 void *data, int size, struct tep_event *event,
5380*436bf2bcSAndroid Build Coastguard Worker 			 struct tep_print_arg *arg)
5381*436bf2bcSAndroid Build Coastguard Worker {
5382*436bf2bcSAndroid Build Coastguard Worker 	const char *fmt = "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x";
5383*436bf2bcSAndroid Build Coastguard Worker 	bool reverse = false;
5384*436bf2bcSAndroid Build Coastguard Worker 	unsigned char *buf;
5385*436bf2bcSAndroid Build Coastguard Worker 	int ret = 0;
5386*436bf2bcSAndroid Build Coastguard Worker 
5387*436bf2bcSAndroid Build Coastguard Worker 	if (arg->type == TEP_PRINT_FUNC) {
5388*436bf2bcSAndroid Build Coastguard Worker 		process_defined_func(s, data, size, event, arg);
5389*436bf2bcSAndroid Build Coastguard Worker 		return 0;
5390*436bf2bcSAndroid Build Coastguard Worker 	}
5391*436bf2bcSAndroid Build Coastguard Worker 
5392*436bf2bcSAndroid Build Coastguard Worker 	/* evaluate if the arg has a type cast */
5393*436bf2bcSAndroid Build Coastguard Worker 	while (arg->type == TEP_PRINT_TYPE)
5394*436bf2bcSAndroid Build Coastguard Worker 		arg = arg->typecast.item;
5395*436bf2bcSAndroid Build Coastguard Worker 
5396*436bf2bcSAndroid Build Coastguard Worker 	if (arg->type != TEP_PRINT_FIELD) {
5397*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_printf(s, "ARG TYPE NOT FIELD BUT %d",
5398*436bf2bcSAndroid Build Coastguard Worker 				 arg->type);
5399*436bf2bcSAndroid Build Coastguard Worker 		return 0;
5400*436bf2bcSAndroid Build Coastguard Worker 	}
5401*436bf2bcSAndroid Build Coastguard Worker 
5402*436bf2bcSAndroid Build Coastguard Worker 	if (format[0] == 'm') {
5403*436bf2bcSAndroid Build Coastguard Worker 		fmt = "%.2x%.2x%.2x%.2x%.2x%.2x";
5404*436bf2bcSAndroid Build Coastguard Worker 	} else if (format[0] == 'M' && format[1] == 'F') {
5405*436bf2bcSAndroid Build Coastguard Worker 		fmt = "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x";
5406*436bf2bcSAndroid Build Coastguard Worker 		ret++;
5407*436bf2bcSAndroid Build Coastguard Worker 	}
5408*436bf2bcSAndroid Build Coastguard Worker 	if (format[1] == 'R') {
5409*436bf2bcSAndroid Build Coastguard Worker 		reverse = true;
5410*436bf2bcSAndroid Build Coastguard Worker 		ret++;
5411*436bf2bcSAndroid Build Coastguard Worker 	}
5412*436bf2bcSAndroid Build Coastguard Worker 
5413*436bf2bcSAndroid Build Coastguard Worker 	if (!arg->field.field) {
5414*436bf2bcSAndroid Build Coastguard Worker 		arg->field.field =
5415*436bf2bcSAndroid Build Coastguard Worker 			tep_find_any_field(event, arg->field.name);
5416*436bf2bcSAndroid Build Coastguard Worker 		if (!arg->field.field) {
5417*436bf2bcSAndroid Build Coastguard Worker 			do_warning_event(event, "%s: field %s not found",
5418*436bf2bcSAndroid Build Coastguard Worker 					 __func__, arg->field.name);
5419*436bf2bcSAndroid Build Coastguard Worker 			return ret;
5420*436bf2bcSAndroid Build Coastguard Worker 		}
5421*436bf2bcSAndroid Build Coastguard Worker 	}
5422*436bf2bcSAndroid Build Coastguard Worker 	if (arg->field.field->size != 6) {
5423*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_printf(s, "INVALIDMAC");
5424*436bf2bcSAndroid Build Coastguard Worker 		return ret;
5425*436bf2bcSAndroid Build Coastguard Worker 	}
5426*436bf2bcSAndroid Build Coastguard Worker 
5427*436bf2bcSAndroid Build Coastguard Worker 	buf = data + arg->field.field->offset;
5428*436bf2bcSAndroid Build Coastguard Worker 	if (reverse)
5429*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_printf(s, fmt, buf[5], buf[4], buf[3], buf[2], buf[1], buf[0]);
5430*436bf2bcSAndroid Build Coastguard Worker 	else
5431*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_printf(s, fmt, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
5432*436bf2bcSAndroid Build Coastguard Worker 
5433*436bf2bcSAndroid Build Coastguard Worker 	return ret;
5434*436bf2bcSAndroid Build Coastguard Worker }
5435*436bf2bcSAndroid Build Coastguard Worker 
parse_ip4_print_args(struct tep_handle * tep,const char * ptr,bool * reverse)5436*436bf2bcSAndroid Build Coastguard Worker static int parse_ip4_print_args(struct tep_handle *tep,
5437*436bf2bcSAndroid Build Coastguard Worker 				const char *ptr, bool *reverse)
5438*436bf2bcSAndroid Build Coastguard Worker {
5439*436bf2bcSAndroid Build Coastguard Worker 	int ret = 0;
5440*436bf2bcSAndroid Build Coastguard Worker 
5441*436bf2bcSAndroid Build Coastguard Worker 	*reverse = false;
5442*436bf2bcSAndroid Build Coastguard Worker 
5443*436bf2bcSAndroid Build Coastguard Worker 	/* hnbl */
5444*436bf2bcSAndroid Build Coastguard Worker 	switch (*ptr) {
5445*436bf2bcSAndroid Build Coastguard Worker 	case 'h':
5446*436bf2bcSAndroid Build Coastguard Worker 		if (tep->file_bigendian)
5447*436bf2bcSAndroid Build Coastguard Worker 			*reverse = false;
5448*436bf2bcSAndroid Build Coastguard Worker 		else
5449*436bf2bcSAndroid Build Coastguard Worker 			*reverse = true;
5450*436bf2bcSAndroid Build Coastguard Worker 		ret++;
5451*436bf2bcSAndroid Build Coastguard Worker 		break;
5452*436bf2bcSAndroid Build Coastguard Worker 	case 'l':
5453*436bf2bcSAndroid Build Coastguard Worker 		*reverse = true;
5454*436bf2bcSAndroid Build Coastguard Worker 		ret++;
5455*436bf2bcSAndroid Build Coastguard Worker 		break;
5456*436bf2bcSAndroid Build Coastguard Worker 	case 'n':
5457*436bf2bcSAndroid Build Coastguard Worker 	case 'b':
5458*436bf2bcSAndroid Build Coastguard Worker 		ret++;
5459*436bf2bcSAndroid Build Coastguard Worker 		/* fall through */
5460*436bf2bcSAndroid Build Coastguard Worker 	default:
5461*436bf2bcSAndroid Build Coastguard Worker 		*reverse = false;
5462*436bf2bcSAndroid Build Coastguard Worker 		break;
5463*436bf2bcSAndroid Build Coastguard Worker 	}
5464*436bf2bcSAndroid Build Coastguard Worker 
5465*436bf2bcSAndroid Build Coastguard Worker 	return ret;
5466*436bf2bcSAndroid Build Coastguard Worker }
5467*436bf2bcSAndroid Build Coastguard Worker 
print_ip4_addr(struct trace_seq * s,char i,bool reverse,unsigned char * buf)5468*436bf2bcSAndroid Build Coastguard Worker static void print_ip4_addr(struct trace_seq *s, char i, bool reverse, unsigned char *buf)
5469*436bf2bcSAndroid Build Coastguard Worker {
5470*436bf2bcSAndroid Build Coastguard Worker 	const char *fmt;
5471*436bf2bcSAndroid Build Coastguard Worker 
5472*436bf2bcSAndroid Build Coastguard Worker 	if (i == 'i')
5473*436bf2bcSAndroid Build Coastguard Worker 		fmt = "%03d.%03d.%03d.%03d";
5474*436bf2bcSAndroid Build Coastguard Worker 	else
5475*436bf2bcSAndroid Build Coastguard Worker 		fmt = "%d.%d.%d.%d";
5476*436bf2bcSAndroid Build Coastguard Worker 
5477*436bf2bcSAndroid Build Coastguard Worker 	if (reverse)
5478*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_printf(s, fmt, buf[3], buf[2], buf[1], buf[0]);
5479*436bf2bcSAndroid Build Coastguard Worker 	else
5480*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_printf(s, fmt, buf[0], buf[1], buf[2], buf[3]);
5481*436bf2bcSAndroid Build Coastguard Worker 
5482*436bf2bcSAndroid Build Coastguard Worker }
5483*436bf2bcSAndroid Build Coastguard Worker 
ipv6_addr_v4mapped(const struct in6_addr * a)5484*436bf2bcSAndroid Build Coastguard Worker static inline bool ipv6_addr_v4mapped(const struct in6_addr *a)
5485*436bf2bcSAndroid Build Coastguard Worker {
5486*436bf2bcSAndroid Build Coastguard Worker 	return ((unsigned long)(a->s6_addr32[0] | a->s6_addr32[1]) |
5487*436bf2bcSAndroid Build Coastguard Worker 		(unsigned long)(a->s6_addr32[2] ^ htonl(0x0000ffff))) == 0UL;
5488*436bf2bcSAndroid Build Coastguard Worker }
5489*436bf2bcSAndroid Build Coastguard Worker 
ipv6_addr_is_isatap(const struct in6_addr * addr)5490*436bf2bcSAndroid Build Coastguard Worker static inline bool ipv6_addr_is_isatap(const struct in6_addr *addr)
5491*436bf2bcSAndroid Build Coastguard Worker {
5492*436bf2bcSAndroid Build Coastguard Worker 	return (addr->s6_addr32[2] | htonl(0x02000000)) == htonl(0x02005EFE);
5493*436bf2bcSAndroid Build Coastguard Worker }
5494*436bf2bcSAndroid Build Coastguard Worker 
print_ip6c_addr(struct trace_seq * s,unsigned char * addr)5495*436bf2bcSAndroid Build Coastguard Worker static void print_ip6c_addr(struct trace_seq *s, unsigned char *addr)
5496*436bf2bcSAndroid Build Coastguard Worker {
5497*436bf2bcSAndroid Build Coastguard Worker 	int i, j, range;
5498*436bf2bcSAndroid Build Coastguard Worker 	unsigned char zerolength[8];
5499*436bf2bcSAndroid Build Coastguard Worker 	int longest = 1;
5500*436bf2bcSAndroid Build Coastguard Worker 	int colonpos = -1;
5501*436bf2bcSAndroid Build Coastguard Worker 	uint16_t word;
5502*436bf2bcSAndroid Build Coastguard Worker 	uint8_t hi, lo;
5503*436bf2bcSAndroid Build Coastguard Worker 	bool needcolon = false;
5504*436bf2bcSAndroid Build Coastguard Worker 	bool useIPv4;
5505*436bf2bcSAndroid Build Coastguard Worker 	struct in6_addr in6;
5506*436bf2bcSAndroid Build Coastguard Worker 
5507*436bf2bcSAndroid Build Coastguard Worker 	memcpy(&in6, addr, sizeof(struct in6_addr));
5508*436bf2bcSAndroid Build Coastguard Worker 
5509*436bf2bcSAndroid Build Coastguard Worker 	useIPv4 = ipv6_addr_v4mapped(&in6) || ipv6_addr_is_isatap(&in6);
5510*436bf2bcSAndroid Build Coastguard Worker 
5511*436bf2bcSAndroid Build Coastguard Worker 	memset(zerolength, 0, sizeof(zerolength));
5512*436bf2bcSAndroid Build Coastguard Worker 
5513*436bf2bcSAndroid Build Coastguard Worker 	if (useIPv4)
5514*436bf2bcSAndroid Build Coastguard Worker 		range = 6;
5515*436bf2bcSAndroid Build Coastguard Worker 	else
5516*436bf2bcSAndroid Build Coastguard Worker 		range = 8;
5517*436bf2bcSAndroid Build Coastguard Worker 
5518*436bf2bcSAndroid Build Coastguard Worker 	/* find position of longest 0 run */
5519*436bf2bcSAndroid Build Coastguard Worker 	for (i = 0; i < range; i++) {
5520*436bf2bcSAndroid Build Coastguard Worker 		for (j = i; j < range; j++) {
5521*436bf2bcSAndroid Build Coastguard Worker 			if (in6.s6_addr16[j] != 0)
5522*436bf2bcSAndroid Build Coastguard Worker 				break;
5523*436bf2bcSAndroid Build Coastguard Worker 			zerolength[i]++;
5524*436bf2bcSAndroid Build Coastguard Worker 		}
5525*436bf2bcSAndroid Build Coastguard Worker 	}
5526*436bf2bcSAndroid Build Coastguard Worker 	for (i = 0; i < range; i++) {
5527*436bf2bcSAndroid Build Coastguard Worker 		if (zerolength[i] > longest) {
5528*436bf2bcSAndroid Build Coastguard Worker 			longest = zerolength[i];
5529*436bf2bcSAndroid Build Coastguard Worker 			colonpos = i;
5530*436bf2bcSAndroid Build Coastguard Worker 		}
5531*436bf2bcSAndroid Build Coastguard Worker 	}
5532*436bf2bcSAndroid Build Coastguard Worker 	if (longest == 1)		/* don't compress a single 0 */
5533*436bf2bcSAndroid Build Coastguard Worker 		colonpos = -1;
5534*436bf2bcSAndroid Build Coastguard Worker 
5535*436bf2bcSAndroid Build Coastguard Worker 	/* emit address */
5536*436bf2bcSAndroid Build Coastguard Worker 	for (i = 0; i < range; i++) {
5537*436bf2bcSAndroid Build Coastguard Worker 		if (i == colonpos) {
5538*436bf2bcSAndroid Build Coastguard Worker 			if (needcolon || i == 0)
5539*436bf2bcSAndroid Build Coastguard Worker 				trace_seq_printf(s, ":");
5540*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_printf(s, ":");
5541*436bf2bcSAndroid Build Coastguard Worker 			needcolon = false;
5542*436bf2bcSAndroid Build Coastguard Worker 			i += longest - 1;
5543*436bf2bcSAndroid Build Coastguard Worker 			continue;
5544*436bf2bcSAndroid Build Coastguard Worker 		}
5545*436bf2bcSAndroid Build Coastguard Worker 		if (needcolon) {
5546*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_printf(s, ":");
5547*436bf2bcSAndroid Build Coastguard Worker 			needcolon = false;
5548*436bf2bcSAndroid Build Coastguard Worker 		}
5549*436bf2bcSAndroid Build Coastguard Worker 		/* hex u16 without leading 0s */
5550*436bf2bcSAndroid Build Coastguard Worker 		word = ntohs(in6.s6_addr16[i]);
5551*436bf2bcSAndroid Build Coastguard Worker 		hi = word >> 8;
5552*436bf2bcSAndroid Build Coastguard Worker 		lo = word & 0xff;
5553*436bf2bcSAndroid Build Coastguard Worker 		if (hi)
5554*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_printf(s, "%x%02x", hi, lo);
5555*436bf2bcSAndroid Build Coastguard Worker 		else
5556*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_printf(s, "%x", lo);
5557*436bf2bcSAndroid Build Coastguard Worker 
5558*436bf2bcSAndroid Build Coastguard Worker 		needcolon = true;
5559*436bf2bcSAndroid Build Coastguard Worker 	}
5560*436bf2bcSAndroid Build Coastguard Worker 
5561*436bf2bcSAndroid Build Coastguard Worker 	if (useIPv4) {
5562*436bf2bcSAndroid Build Coastguard Worker 		if (needcolon)
5563*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_printf(s, ":");
5564*436bf2bcSAndroid Build Coastguard Worker 		print_ip4_addr(s, 'I', false, &in6.s6_addr[12]);
5565*436bf2bcSAndroid Build Coastguard Worker 	}
5566*436bf2bcSAndroid Build Coastguard Worker 
5567*436bf2bcSAndroid Build Coastguard Worker 	return;
5568*436bf2bcSAndroid Build Coastguard Worker }
5569*436bf2bcSAndroid Build Coastguard Worker 
print_ip6_addr(struct trace_seq * s,char i,unsigned char * buf)5570*436bf2bcSAndroid Build Coastguard Worker static void print_ip6_addr(struct trace_seq *s, char i, unsigned char *buf)
5571*436bf2bcSAndroid Build Coastguard Worker {
5572*436bf2bcSAndroid Build Coastguard Worker 	int j;
5573*436bf2bcSAndroid Build Coastguard Worker 
5574*436bf2bcSAndroid Build Coastguard Worker 	for (j = 0; j < 16; j += 2) {
5575*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_printf(s, "%02x%02x", buf[j], buf[j+1]);
5576*436bf2bcSAndroid Build Coastguard Worker 		if (i == 'I' && j < 14)
5577*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_printf(s, ":");
5578*436bf2bcSAndroid Build Coastguard Worker 	}
5579*436bf2bcSAndroid Build Coastguard Worker }
5580*436bf2bcSAndroid Build Coastguard Worker 
5581*436bf2bcSAndroid Build Coastguard Worker /*
5582*436bf2bcSAndroid Build Coastguard Worker  * %pi4   print an IPv4 address with leading zeros
5583*436bf2bcSAndroid Build Coastguard Worker  * %pI4   print an IPv4 address without leading zeros
5584*436bf2bcSAndroid Build Coastguard Worker  * %pi6   print an IPv6 address without colons
5585*436bf2bcSAndroid Build Coastguard Worker  * %pI6   print an IPv6 address with colons
5586*436bf2bcSAndroid Build Coastguard Worker  * %pI6c  print an IPv6 address in compressed form with colons
5587*436bf2bcSAndroid Build Coastguard Worker  * %pISpc print an IP address based on sockaddr; p adds port.
5588*436bf2bcSAndroid Build Coastguard Worker  */
print_ipv4_arg(struct trace_seq * s,const char * ptr,char i,void * data,int size,struct tep_event * event,struct tep_print_arg * arg)5589*436bf2bcSAndroid Build Coastguard Worker static int print_ipv4_arg(struct trace_seq *s, const char *ptr, char i,
5590*436bf2bcSAndroid Build Coastguard Worker 			  void *data, int size, struct tep_event *event,
5591*436bf2bcSAndroid Build Coastguard Worker 			  struct tep_print_arg *arg)
5592*436bf2bcSAndroid Build Coastguard Worker {
5593*436bf2bcSAndroid Build Coastguard Worker 	bool reverse = false;
5594*436bf2bcSAndroid Build Coastguard Worker 	unsigned char *buf;
5595*436bf2bcSAndroid Build Coastguard Worker 	int ret;
5596*436bf2bcSAndroid Build Coastguard Worker 
5597*436bf2bcSAndroid Build Coastguard Worker 	ret = parse_ip4_print_args(event->tep, ptr, &reverse);
5598*436bf2bcSAndroid Build Coastguard Worker 
5599*436bf2bcSAndroid Build Coastguard Worker 	if (arg->type == TEP_PRINT_FUNC) {
5600*436bf2bcSAndroid Build Coastguard Worker 		process_defined_func(s, data, size, event, arg);
5601*436bf2bcSAndroid Build Coastguard Worker 		return ret;
5602*436bf2bcSAndroid Build Coastguard Worker 	}
5603*436bf2bcSAndroid Build Coastguard Worker 
5604*436bf2bcSAndroid Build Coastguard Worker 	/* evaluate if the arg has a type cast */
5605*436bf2bcSAndroid Build Coastguard Worker 	while (arg->type == TEP_PRINT_TYPE)
5606*436bf2bcSAndroid Build Coastguard Worker 		arg = arg->typecast.item;
5607*436bf2bcSAndroid Build Coastguard Worker 
5608*436bf2bcSAndroid Build Coastguard Worker 	if (arg->type != TEP_PRINT_FIELD) {
5609*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_printf(s, "ARG TYPE NOT FIELD BUT %d", arg->type);
5610*436bf2bcSAndroid Build Coastguard Worker 		return ret;
5611*436bf2bcSAndroid Build Coastguard Worker 	}
5612*436bf2bcSAndroid Build Coastguard Worker 
5613*436bf2bcSAndroid Build Coastguard Worker 	if (!arg->field.field) {
5614*436bf2bcSAndroid Build Coastguard Worker 		arg->field.field =
5615*436bf2bcSAndroid Build Coastguard Worker 			tep_find_any_field(event, arg->field.name);
5616*436bf2bcSAndroid Build Coastguard Worker 		if (!arg->field.field) {
5617*436bf2bcSAndroid Build Coastguard Worker 			do_warning("%s: field %s not found",
5618*436bf2bcSAndroid Build Coastguard Worker 				   __func__, arg->field.name);
5619*436bf2bcSAndroid Build Coastguard Worker 			return ret;
5620*436bf2bcSAndroid Build Coastguard Worker 		}
5621*436bf2bcSAndroid Build Coastguard Worker 	}
5622*436bf2bcSAndroid Build Coastguard Worker 
5623*436bf2bcSAndroid Build Coastguard Worker 	buf = data + arg->field.field->offset;
5624*436bf2bcSAndroid Build Coastguard Worker 
5625*436bf2bcSAndroid Build Coastguard Worker 	if (arg->field.field->size != 4) {
5626*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_printf(s, "INVALIDIPv4");
5627*436bf2bcSAndroid Build Coastguard Worker 		return ret;
5628*436bf2bcSAndroid Build Coastguard Worker 	}
5629*436bf2bcSAndroid Build Coastguard Worker 
5630*436bf2bcSAndroid Build Coastguard Worker 	print_ip4_addr(s, i, reverse, buf);
5631*436bf2bcSAndroid Build Coastguard Worker 	return ret;
5632*436bf2bcSAndroid Build Coastguard Worker 
5633*436bf2bcSAndroid Build Coastguard Worker }
5634*436bf2bcSAndroid Build Coastguard Worker 
print_ipv6_arg(struct trace_seq * s,const char * ptr,char i,void * data,int size,struct tep_event * event,struct tep_print_arg * arg)5635*436bf2bcSAndroid Build Coastguard Worker static int print_ipv6_arg(struct trace_seq *s, const char *ptr, char i,
5636*436bf2bcSAndroid Build Coastguard Worker 			  void *data, int size, struct tep_event *event,
5637*436bf2bcSAndroid Build Coastguard Worker 			  struct tep_print_arg *arg)
5638*436bf2bcSAndroid Build Coastguard Worker {
5639*436bf2bcSAndroid Build Coastguard Worker 	char have_c = 0;
5640*436bf2bcSAndroid Build Coastguard Worker 	unsigned char *buf;
5641*436bf2bcSAndroid Build Coastguard Worker 	int rc = 0;
5642*436bf2bcSAndroid Build Coastguard Worker 
5643*436bf2bcSAndroid Build Coastguard Worker 	/* pI6c */
5644*436bf2bcSAndroid Build Coastguard Worker 	if (i == 'I' && *ptr == 'c') {
5645*436bf2bcSAndroid Build Coastguard Worker 		have_c = 1;
5646*436bf2bcSAndroid Build Coastguard Worker 		ptr++;
5647*436bf2bcSAndroid Build Coastguard Worker 		rc++;
5648*436bf2bcSAndroid Build Coastguard Worker 	}
5649*436bf2bcSAndroid Build Coastguard Worker 
5650*436bf2bcSAndroid Build Coastguard Worker 	if (arg->type == TEP_PRINT_FUNC) {
5651*436bf2bcSAndroid Build Coastguard Worker 		process_defined_func(s, data, size, event, arg);
5652*436bf2bcSAndroid Build Coastguard Worker 		return rc;
5653*436bf2bcSAndroid Build Coastguard Worker 	}
5654*436bf2bcSAndroid Build Coastguard Worker 
5655*436bf2bcSAndroid Build Coastguard Worker 	/* evaluate if the arg has a type cast */
5656*436bf2bcSAndroid Build Coastguard Worker 	while (arg->type == TEP_PRINT_TYPE)
5657*436bf2bcSAndroid Build Coastguard Worker 		arg = arg->typecast.item;
5658*436bf2bcSAndroid Build Coastguard Worker 
5659*436bf2bcSAndroid Build Coastguard Worker 	if (arg->type != TEP_PRINT_FIELD) {
5660*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_printf(s, "ARG TYPE NOT FIELD BUT %d", arg->type);
5661*436bf2bcSAndroid Build Coastguard Worker 		return rc;
5662*436bf2bcSAndroid Build Coastguard Worker 	}
5663*436bf2bcSAndroid Build Coastguard Worker 
5664*436bf2bcSAndroid Build Coastguard Worker 	if (!arg->field.field) {
5665*436bf2bcSAndroid Build Coastguard Worker 		arg->field.field =
5666*436bf2bcSAndroid Build Coastguard Worker 			tep_find_any_field(event, arg->field.name);
5667*436bf2bcSAndroid Build Coastguard Worker 		if (!arg->field.field) {
5668*436bf2bcSAndroid Build Coastguard Worker 			do_warning("%s: field %s not found",
5669*436bf2bcSAndroid Build Coastguard Worker 				   __func__, arg->field.name);
5670*436bf2bcSAndroid Build Coastguard Worker 			return rc;
5671*436bf2bcSAndroid Build Coastguard Worker 		}
5672*436bf2bcSAndroid Build Coastguard Worker 	}
5673*436bf2bcSAndroid Build Coastguard Worker 
5674*436bf2bcSAndroid Build Coastguard Worker 	buf = data + arg->field.field->offset;
5675*436bf2bcSAndroid Build Coastguard Worker 
5676*436bf2bcSAndroid Build Coastguard Worker 	if (arg->field.field->size != 16) {
5677*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_printf(s, "INVALIDIPv6");
5678*436bf2bcSAndroid Build Coastguard Worker 		return rc;
5679*436bf2bcSAndroid Build Coastguard Worker 	}
5680*436bf2bcSAndroid Build Coastguard Worker 
5681*436bf2bcSAndroid Build Coastguard Worker 	if (have_c)
5682*436bf2bcSAndroid Build Coastguard Worker 		print_ip6c_addr(s, buf);
5683*436bf2bcSAndroid Build Coastguard Worker 	else
5684*436bf2bcSAndroid Build Coastguard Worker 		print_ip6_addr(s, i, buf);
5685*436bf2bcSAndroid Build Coastguard Worker 
5686*436bf2bcSAndroid Build Coastguard Worker 	return rc;
5687*436bf2bcSAndroid Build Coastguard Worker }
5688*436bf2bcSAndroid Build Coastguard Worker 
print_ipsa_arg(struct trace_seq * s,const char * ptr,char i,void * data,int size,struct tep_event * event,struct tep_print_arg * arg)5689*436bf2bcSAndroid Build Coastguard Worker static int print_ipsa_arg(struct trace_seq *s, const char *ptr, char i,
5690*436bf2bcSAndroid Build Coastguard Worker 			  void *data, int size, struct tep_event *event,
5691*436bf2bcSAndroid Build Coastguard Worker 			  struct tep_print_arg *arg)
5692*436bf2bcSAndroid Build Coastguard Worker {
5693*436bf2bcSAndroid Build Coastguard Worker 	char have_c = 0, have_p = 0;
5694*436bf2bcSAndroid Build Coastguard Worker 	unsigned char *buf;
5695*436bf2bcSAndroid Build Coastguard Worker 	struct sockaddr_storage *sa;
5696*436bf2bcSAndroid Build Coastguard Worker 	bool reverse = false;
5697*436bf2bcSAndroid Build Coastguard Worker 	unsigned int offset;
5698*436bf2bcSAndroid Build Coastguard Worker 	unsigned int len;
5699*436bf2bcSAndroid Build Coastguard Worker 	int rc = 0;
5700*436bf2bcSAndroid Build Coastguard Worker 	int ret;
5701*436bf2bcSAndroid Build Coastguard Worker 
5702*436bf2bcSAndroid Build Coastguard Worker 	/* pISpc */
5703*436bf2bcSAndroid Build Coastguard Worker 	if (i == 'I') {
5704*436bf2bcSAndroid Build Coastguard Worker 		if (*ptr == 'p') {
5705*436bf2bcSAndroid Build Coastguard Worker 			have_p = 1;
5706*436bf2bcSAndroid Build Coastguard Worker 			ptr++;
5707*436bf2bcSAndroid Build Coastguard Worker 			rc++;
5708*436bf2bcSAndroid Build Coastguard Worker 		}
5709*436bf2bcSAndroid Build Coastguard Worker 		if (*ptr == 'c') {
5710*436bf2bcSAndroid Build Coastguard Worker 			have_c = 1;
5711*436bf2bcSAndroid Build Coastguard Worker 			ptr++;
5712*436bf2bcSAndroid Build Coastguard Worker 			rc++;
5713*436bf2bcSAndroid Build Coastguard Worker 		}
5714*436bf2bcSAndroid Build Coastguard Worker 	}
5715*436bf2bcSAndroid Build Coastguard Worker 	ret = parse_ip4_print_args(event->tep, ptr, &reverse);
5716*436bf2bcSAndroid Build Coastguard Worker 	ptr += ret;
5717*436bf2bcSAndroid Build Coastguard Worker 	rc += ret;
5718*436bf2bcSAndroid Build Coastguard Worker 
5719*436bf2bcSAndroid Build Coastguard Worker 	if (arg->type == TEP_PRINT_FUNC) {
5720*436bf2bcSAndroid Build Coastguard Worker 		process_defined_func(s, data, size, event, arg);
5721*436bf2bcSAndroid Build Coastguard Worker 		return rc;
5722*436bf2bcSAndroid Build Coastguard Worker 	}
5723*436bf2bcSAndroid Build Coastguard Worker 
5724*436bf2bcSAndroid Build Coastguard Worker 	/* evaluate if the arg has a type cast */
5725*436bf2bcSAndroid Build Coastguard Worker 	while (arg->type == TEP_PRINT_TYPE)
5726*436bf2bcSAndroid Build Coastguard Worker 		arg = arg->typecast.item;
5727*436bf2bcSAndroid Build Coastguard Worker 
5728*436bf2bcSAndroid Build Coastguard Worker 	if (arg->type == TEP_PRINT_FIELD) {
5729*436bf2bcSAndroid Build Coastguard Worker 
5730*436bf2bcSAndroid Build Coastguard Worker 		if (!arg->field.field) {
5731*436bf2bcSAndroid Build Coastguard Worker 			arg->field.field =
5732*436bf2bcSAndroid Build Coastguard Worker 				tep_find_any_field(event, arg->field.name);
5733*436bf2bcSAndroid Build Coastguard Worker 			if (!arg->field.field) {
5734*436bf2bcSAndroid Build Coastguard Worker 				do_warning("%s: field %s not found",
5735*436bf2bcSAndroid Build Coastguard Worker 					   __func__, arg->field.name);
5736*436bf2bcSAndroid Build Coastguard Worker 				return rc;
5737*436bf2bcSAndroid Build Coastguard Worker 			}
5738*436bf2bcSAndroid Build Coastguard Worker 		}
5739*436bf2bcSAndroid Build Coastguard Worker 
5740*436bf2bcSAndroid Build Coastguard Worker 		offset = arg->field.field->offset;
5741*436bf2bcSAndroid Build Coastguard Worker 		len = arg->field.field->size;
5742*436bf2bcSAndroid Build Coastguard Worker 
5743*436bf2bcSAndroid Build Coastguard Worker 	} else if (arg->type == TEP_PRINT_DYNAMIC_ARRAY) {
5744*436bf2bcSAndroid Build Coastguard Worker 
5745*436bf2bcSAndroid Build Coastguard Worker 		dynamic_offset_field(event->tep, arg->dynarray.field, data,
5746*436bf2bcSAndroid Build Coastguard Worker 				     size, &offset, &len);
5747*436bf2bcSAndroid Build Coastguard Worker 
5748*436bf2bcSAndroid Build Coastguard Worker 	} else {
5749*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_printf(s, "ARG NOT FIELD NOR DYNAMIC ARRAY BUT TYPE %d",
5750*436bf2bcSAndroid Build Coastguard Worker 				 arg->type);
5751*436bf2bcSAndroid Build Coastguard Worker 		return rc;
5752*436bf2bcSAndroid Build Coastguard Worker 	}
5753*436bf2bcSAndroid Build Coastguard Worker 
5754*436bf2bcSAndroid Build Coastguard Worker 	sa = (struct sockaddr_storage *)(data + offset);
5755*436bf2bcSAndroid Build Coastguard Worker 
5756*436bf2bcSAndroid Build Coastguard Worker 	if (sa->ss_family == AF_INET) {
5757*436bf2bcSAndroid Build Coastguard Worker 		struct sockaddr_in *sa4 = (struct sockaddr_in *) sa;
5758*436bf2bcSAndroid Build Coastguard Worker 
5759*436bf2bcSAndroid Build Coastguard Worker 		if (len < sizeof(struct sockaddr_in)) {
5760*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_printf(s, "INVALIDIPv4");
5761*436bf2bcSAndroid Build Coastguard Worker 			return rc;
5762*436bf2bcSAndroid Build Coastguard Worker 		}
5763*436bf2bcSAndroid Build Coastguard Worker 
5764*436bf2bcSAndroid Build Coastguard Worker 		print_ip4_addr(s, i, reverse, (unsigned char *) &sa4->sin_addr);
5765*436bf2bcSAndroid Build Coastguard Worker 		if (have_p)
5766*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_printf(s, ":%d", ntohs(sa4->sin_port));
5767*436bf2bcSAndroid Build Coastguard Worker 
5768*436bf2bcSAndroid Build Coastguard Worker 
5769*436bf2bcSAndroid Build Coastguard Worker 	} else if (sa->ss_family == AF_INET6) {
5770*436bf2bcSAndroid Build Coastguard Worker 		struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) sa;
5771*436bf2bcSAndroid Build Coastguard Worker 
5772*436bf2bcSAndroid Build Coastguard Worker 		if (len < sizeof(struct sockaddr_in6)) {
5773*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_printf(s, "INVALIDIPv6");
5774*436bf2bcSAndroid Build Coastguard Worker 			return rc;
5775*436bf2bcSAndroid Build Coastguard Worker 		}
5776*436bf2bcSAndroid Build Coastguard Worker 
5777*436bf2bcSAndroid Build Coastguard Worker 		if (have_p)
5778*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_printf(s, "[");
5779*436bf2bcSAndroid Build Coastguard Worker 
5780*436bf2bcSAndroid Build Coastguard Worker 		buf = (unsigned char *) &sa6->sin6_addr;
5781*436bf2bcSAndroid Build Coastguard Worker 		if (have_c)
5782*436bf2bcSAndroid Build Coastguard Worker 			print_ip6c_addr(s, buf);
5783*436bf2bcSAndroid Build Coastguard Worker 		else
5784*436bf2bcSAndroid Build Coastguard Worker 			print_ip6_addr(s, i, buf);
5785*436bf2bcSAndroid Build Coastguard Worker 
5786*436bf2bcSAndroid Build Coastguard Worker 		if (have_p)
5787*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_printf(s, "]:%d", ntohs(sa6->sin6_port));
5788*436bf2bcSAndroid Build Coastguard Worker 	}
5789*436bf2bcSAndroid Build Coastguard Worker 
5790*436bf2bcSAndroid Build Coastguard Worker 	return rc;
5791*436bf2bcSAndroid Build Coastguard Worker }
5792*436bf2bcSAndroid Build Coastguard Worker 
print_ip_arg(struct trace_seq * s,const char * ptr,void * data,int size,struct tep_event * event,struct tep_print_arg * arg)5793*436bf2bcSAndroid Build Coastguard Worker static int print_ip_arg(struct trace_seq *s, const char *ptr,
5794*436bf2bcSAndroid Build Coastguard Worker 			void *data, int size, struct tep_event *event,
5795*436bf2bcSAndroid Build Coastguard Worker 			struct tep_print_arg *arg)
5796*436bf2bcSAndroid Build Coastguard Worker {
5797*436bf2bcSAndroid Build Coastguard Worker 	char i = *ptr;  /* 'i' or 'I' */
5798*436bf2bcSAndroid Build Coastguard Worker 	int rc = 1;
5799*436bf2bcSAndroid Build Coastguard Worker 
5800*436bf2bcSAndroid Build Coastguard Worker 	/* IP version */
5801*436bf2bcSAndroid Build Coastguard Worker 	ptr++;
5802*436bf2bcSAndroid Build Coastguard Worker 
5803*436bf2bcSAndroid Build Coastguard Worker 	switch (*ptr) {
5804*436bf2bcSAndroid Build Coastguard Worker 	case '4':
5805*436bf2bcSAndroid Build Coastguard Worker 		rc += print_ipv4_arg(s, ptr + 1, i, data, size, event, arg);
5806*436bf2bcSAndroid Build Coastguard Worker 		break;
5807*436bf2bcSAndroid Build Coastguard Worker 	case '6':
5808*436bf2bcSAndroid Build Coastguard Worker 		rc += print_ipv6_arg(s, ptr + 1, i, data, size, event, arg);
5809*436bf2bcSAndroid Build Coastguard Worker 		break;
5810*436bf2bcSAndroid Build Coastguard Worker 	case 'S':
5811*436bf2bcSAndroid Build Coastguard Worker 		rc += print_ipsa_arg(s, ptr + 1, i, data, size, event, arg);
5812*436bf2bcSAndroid Build Coastguard Worker 		break;
5813*436bf2bcSAndroid Build Coastguard Worker 	default:
5814*436bf2bcSAndroid Build Coastguard Worker 		return 0;
5815*436bf2bcSAndroid Build Coastguard Worker 	}
5816*436bf2bcSAndroid Build Coastguard Worker 
5817*436bf2bcSAndroid Build Coastguard Worker 	return rc;
5818*436bf2bcSAndroid Build Coastguard Worker }
5819*436bf2bcSAndroid Build Coastguard Worker 
5820*436bf2bcSAndroid Build Coastguard Worker static const int guid_index[16] = {3, 2, 1, 0, 5, 4, 7, 6, 8, 9, 10, 11, 12, 13, 14, 15};
5821*436bf2bcSAndroid Build Coastguard Worker static const int uuid_index[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
5822*436bf2bcSAndroid Build Coastguard Worker 
print_uuid_arg(struct trace_seq * s,const char * ptr,void * data,int size,struct tep_event * event,struct tep_print_arg * arg)5823*436bf2bcSAndroid Build Coastguard Worker static int print_uuid_arg(struct trace_seq *s, const char *ptr,
5824*436bf2bcSAndroid Build Coastguard Worker 			void *data, int size, struct tep_event *event,
5825*436bf2bcSAndroid Build Coastguard Worker 			struct tep_print_arg *arg)
5826*436bf2bcSAndroid Build Coastguard Worker {
5827*436bf2bcSAndroid Build Coastguard Worker 	const int *index = uuid_index;
5828*436bf2bcSAndroid Build Coastguard Worker 	char *format = "%02x";
5829*436bf2bcSAndroid Build Coastguard Worker 	int ret = 0;
5830*436bf2bcSAndroid Build Coastguard Worker 	char *buf;
5831*436bf2bcSAndroid Build Coastguard Worker 	int i;
5832*436bf2bcSAndroid Build Coastguard Worker 
5833*436bf2bcSAndroid Build Coastguard Worker 	switch (*(ptr + 1)) {
5834*436bf2bcSAndroid Build Coastguard Worker 	case 'L':
5835*436bf2bcSAndroid Build Coastguard Worker 		format = "%02X";
5836*436bf2bcSAndroid Build Coastguard Worker 		/* fall through */
5837*436bf2bcSAndroid Build Coastguard Worker 	case 'l':
5838*436bf2bcSAndroid Build Coastguard Worker 		index = guid_index;
5839*436bf2bcSAndroid Build Coastguard Worker 		ret++;
5840*436bf2bcSAndroid Build Coastguard Worker 		break;
5841*436bf2bcSAndroid Build Coastguard Worker 	case 'B':
5842*436bf2bcSAndroid Build Coastguard Worker 		format = "%02X";
5843*436bf2bcSAndroid Build Coastguard Worker 		/* fall through */
5844*436bf2bcSAndroid Build Coastguard Worker 	case 'b':
5845*436bf2bcSAndroid Build Coastguard Worker 		ret++;
5846*436bf2bcSAndroid Build Coastguard Worker 		break;
5847*436bf2bcSAndroid Build Coastguard Worker 	}
5848*436bf2bcSAndroid Build Coastguard Worker 
5849*436bf2bcSAndroid Build Coastguard Worker 	if (arg->type == TEP_PRINT_FUNC) {
5850*436bf2bcSAndroid Build Coastguard Worker 		process_defined_func(s, data, size, event, arg);
5851*436bf2bcSAndroid Build Coastguard Worker 		return ret;
5852*436bf2bcSAndroid Build Coastguard Worker 	}
5853*436bf2bcSAndroid Build Coastguard Worker 
5854*436bf2bcSAndroid Build Coastguard Worker 	/* evaluate if the arg has a type cast */
5855*436bf2bcSAndroid Build Coastguard Worker 	while (arg->type == TEP_PRINT_TYPE)
5856*436bf2bcSAndroid Build Coastguard Worker 		arg = arg->typecast.item;
5857*436bf2bcSAndroid Build Coastguard Worker 
5858*436bf2bcSAndroid Build Coastguard Worker 	if (arg->type != TEP_PRINT_FIELD) {
5859*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_printf(s, "ARG TYPE NOT FIELD BUT %d", arg->type);
5860*436bf2bcSAndroid Build Coastguard Worker 		return ret;
5861*436bf2bcSAndroid Build Coastguard Worker 	}
5862*436bf2bcSAndroid Build Coastguard Worker 
5863*436bf2bcSAndroid Build Coastguard Worker 	if (!arg->field.field) {
5864*436bf2bcSAndroid Build Coastguard Worker 		arg->field.field =
5865*436bf2bcSAndroid Build Coastguard Worker 			tep_find_any_field(event, arg->field.name);
5866*436bf2bcSAndroid Build Coastguard Worker 		if (!arg->field.field) {
5867*436bf2bcSAndroid Build Coastguard Worker 			do_warning("%s: field %s not found",
5868*436bf2bcSAndroid Build Coastguard Worker 				   __func__, arg->field.name);
5869*436bf2bcSAndroid Build Coastguard Worker 			return ret;
5870*436bf2bcSAndroid Build Coastguard Worker 		}
5871*436bf2bcSAndroid Build Coastguard Worker 	}
5872*436bf2bcSAndroid Build Coastguard Worker 
5873*436bf2bcSAndroid Build Coastguard Worker 	if (arg->field.field->size != 16) {
5874*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_printf(s, "INVALIDUUID");
5875*436bf2bcSAndroid Build Coastguard Worker 		return ret;
5876*436bf2bcSAndroid Build Coastguard Worker 	}
5877*436bf2bcSAndroid Build Coastguard Worker 
5878*436bf2bcSAndroid Build Coastguard Worker 	buf = data + arg->field.field->offset;
5879*436bf2bcSAndroid Build Coastguard Worker 
5880*436bf2bcSAndroid Build Coastguard Worker 	for (i = 0; i < 16; i++) {
5881*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_printf(s, format, buf[index[i]] & 0xff);
5882*436bf2bcSAndroid Build Coastguard Worker 		switch (i) {
5883*436bf2bcSAndroid Build Coastguard Worker 		case 3:
5884*436bf2bcSAndroid Build Coastguard Worker 		case 5:
5885*436bf2bcSAndroid Build Coastguard Worker 		case 7:
5886*436bf2bcSAndroid Build Coastguard Worker 		case 9:
5887*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_printf(s, "-");
5888*436bf2bcSAndroid Build Coastguard Worker 			break;
5889*436bf2bcSAndroid Build Coastguard Worker 		}
5890*436bf2bcSAndroid Build Coastguard Worker 	}
5891*436bf2bcSAndroid Build Coastguard Worker 
5892*436bf2bcSAndroid Build Coastguard Worker 	return ret;
5893*436bf2bcSAndroid Build Coastguard Worker }
5894*436bf2bcSAndroid Build Coastguard Worker 
print_raw_buff_arg(struct trace_seq * s,const char * ptr,void * data,int size,struct tep_event * event,struct tep_print_arg * arg,int print_len)5895*436bf2bcSAndroid Build Coastguard Worker static int print_raw_buff_arg(struct trace_seq *s, const char *ptr,
5896*436bf2bcSAndroid Build Coastguard Worker 			      void *data, int size, struct tep_event *event,
5897*436bf2bcSAndroid Build Coastguard Worker 			      struct tep_print_arg *arg, int print_len)
5898*436bf2bcSAndroid Build Coastguard Worker {
5899*436bf2bcSAndroid Build Coastguard Worker 	unsigned int offset, arr_len;
5900*436bf2bcSAndroid Build Coastguard Worker 	int plen = print_len;
5901*436bf2bcSAndroid Build Coastguard Worker 	char *delim = " ";
5902*436bf2bcSAndroid Build Coastguard Worker 	int ret = 0;
5903*436bf2bcSAndroid Build Coastguard Worker 	char *buf;
5904*436bf2bcSAndroid Build Coastguard Worker 	int i;
5905*436bf2bcSAndroid Build Coastguard Worker 
5906*436bf2bcSAndroid Build Coastguard Worker 	switch (*(ptr + 1)) {
5907*436bf2bcSAndroid Build Coastguard Worker 	case 'C':
5908*436bf2bcSAndroid Build Coastguard Worker 		delim = ":";
5909*436bf2bcSAndroid Build Coastguard Worker 		ret++;
5910*436bf2bcSAndroid Build Coastguard Worker 		break;
5911*436bf2bcSAndroid Build Coastguard Worker 	case 'D':
5912*436bf2bcSAndroid Build Coastguard Worker 		delim = "-";
5913*436bf2bcSAndroid Build Coastguard Worker 		ret++;
5914*436bf2bcSAndroid Build Coastguard Worker 		break;
5915*436bf2bcSAndroid Build Coastguard Worker 	case 'N':
5916*436bf2bcSAndroid Build Coastguard Worker 		delim = "";
5917*436bf2bcSAndroid Build Coastguard Worker 		ret++;
5918*436bf2bcSAndroid Build Coastguard Worker 		break;
5919*436bf2bcSAndroid Build Coastguard Worker 	}
5920*436bf2bcSAndroid Build Coastguard Worker 
5921*436bf2bcSAndroid Build Coastguard Worker 	if (arg->type == TEP_PRINT_FUNC) {
5922*436bf2bcSAndroid Build Coastguard Worker 		process_defined_func(s, data, size, event, arg);
5923*436bf2bcSAndroid Build Coastguard Worker 		return ret;
5924*436bf2bcSAndroid Build Coastguard Worker 	}
5925*436bf2bcSAndroid Build Coastguard Worker 
5926*436bf2bcSAndroid Build Coastguard Worker 	if (arg->type != TEP_PRINT_DYNAMIC_ARRAY) {
5927*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_printf(s, "ARG TYPE NOT FIELD BUT %d", arg->type);
5928*436bf2bcSAndroid Build Coastguard Worker 		return ret;
5929*436bf2bcSAndroid Build Coastguard Worker 	}
5930*436bf2bcSAndroid Build Coastguard Worker 
5931*436bf2bcSAndroid Build Coastguard Worker 	dynamic_offset_field(event->tep, arg->dynarray.field, data, size,
5932*436bf2bcSAndroid Build Coastguard Worker 			     &offset, &arr_len);
5933*436bf2bcSAndroid Build Coastguard Worker 	buf = data + offset;
5934*436bf2bcSAndroid Build Coastguard Worker 
5935*436bf2bcSAndroid Build Coastguard Worker 	if (arr_len < plen)
5936*436bf2bcSAndroid Build Coastguard Worker 		plen = arr_len;
5937*436bf2bcSAndroid Build Coastguard Worker 
5938*436bf2bcSAndroid Build Coastguard Worker 	if (plen < 1)
5939*436bf2bcSAndroid Build Coastguard Worker 		return ret;
5940*436bf2bcSAndroid Build Coastguard Worker 
5941*436bf2bcSAndroid Build Coastguard Worker 	trace_seq_printf(s, "%02x", buf[0] & 0xff);
5942*436bf2bcSAndroid Build Coastguard Worker 	for (i = 1; i < plen; i++)
5943*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_printf(s, "%s%02x", delim, buf[i] & 0xff);
5944*436bf2bcSAndroid Build Coastguard Worker 
5945*436bf2bcSAndroid Build Coastguard Worker 	return ret;
5946*436bf2bcSAndroid Build Coastguard Worker }
5947*436bf2bcSAndroid Build Coastguard Worker 
is_printable_array(char * p,unsigned int len)5948*436bf2bcSAndroid Build Coastguard Worker static int is_printable_array(char *p, unsigned int len)
5949*436bf2bcSAndroid Build Coastguard Worker {
5950*436bf2bcSAndroid Build Coastguard Worker 	unsigned int i;
5951*436bf2bcSAndroid Build Coastguard Worker 
5952*436bf2bcSAndroid Build Coastguard Worker 	for (i = 0; i < len && p[i]; i++)
5953*436bf2bcSAndroid Build Coastguard Worker 		if (!isprint(p[i]) && !isspace(p[i]))
5954*436bf2bcSAndroid Build Coastguard Worker 		    return 0;
5955*436bf2bcSAndroid Build Coastguard Worker 	return 1;
5956*436bf2bcSAndroid Build Coastguard Worker }
5957*436bf2bcSAndroid Build Coastguard Worker 
print_field_raw(struct trace_seq * s,void * data,int size,struct tep_format_field * field)5958*436bf2bcSAndroid Build Coastguard Worker static void print_field_raw(struct trace_seq *s, void *data, int size,
5959*436bf2bcSAndroid Build Coastguard Worker 			     struct tep_format_field *field)
5960*436bf2bcSAndroid Build Coastguard Worker {
5961*436bf2bcSAndroid Build Coastguard Worker 	struct tep_handle *tep = field->event->tep;
5962*436bf2bcSAndroid Build Coastguard Worker 	unsigned int offset, len, i;
5963*436bf2bcSAndroid Build Coastguard Worker 	unsigned long long val;
5964*436bf2bcSAndroid Build Coastguard Worker 
5965*436bf2bcSAndroid Build Coastguard Worker 	if (field->flags & TEP_FIELD_IS_ARRAY) {
5966*436bf2bcSAndroid Build Coastguard Worker 		if (field->flags & TEP_FIELD_IS_DYNAMIC) {
5967*436bf2bcSAndroid Build Coastguard Worker 			dynamic_offset_field(tep, field, data, size, &offset, &len);
5968*436bf2bcSAndroid Build Coastguard Worker 		} else {
5969*436bf2bcSAndroid Build Coastguard Worker 			offset = field->offset;
5970*436bf2bcSAndroid Build Coastguard Worker 			len = field->size;
5971*436bf2bcSAndroid Build Coastguard Worker 		}
5972*436bf2bcSAndroid Build Coastguard Worker 		if (field->flags & TEP_FIELD_IS_STRING &&
5973*436bf2bcSAndroid Build Coastguard Worker 		    is_printable_array(data + offset, len)) {
5974*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_printf(s, "%s", (char *)data + offset);
5975*436bf2bcSAndroid Build Coastguard Worker 		} else {
5976*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_puts(s, "ARRAY[");
5977*436bf2bcSAndroid Build Coastguard Worker 			for (i = 0; i < len; i++) {
5978*436bf2bcSAndroid Build Coastguard Worker 				if (i)
5979*436bf2bcSAndroid Build Coastguard Worker 					trace_seq_puts(s, ", ");
5980*436bf2bcSAndroid Build Coastguard Worker 				trace_seq_printf(s, "%02x",
5981*436bf2bcSAndroid Build Coastguard Worker 						 *((unsigned char *)data + offset + i));
5982*436bf2bcSAndroid Build Coastguard Worker 			}
5983*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_putc(s, ']');
5984*436bf2bcSAndroid Build Coastguard Worker 			field->flags &= ~TEP_FIELD_IS_STRING;
5985*436bf2bcSAndroid Build Coastguard Worker 		}
5986*436bf2bcSAndroid Build Coastguard Worker 	} else {
5987*436bf2bcSAndroid Build Coastguard Worker 		val = tep_read_number(tep, data + field->offset,
5988*436bf2bcSAndroid Build Coastguard Worker 				      field->size);
5989*436bf2bcSAndroid Build Coastguard Worker 		if (field->flags & TEP_FIELD_IS_POINTER) {
5990*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_printf(s, "0x%llx", val);
5991*436bf2bcSAndroid Build Coastguard Worker 		} else if (field->flags & TEP_FIELD_IS_SIGNED) {
5992*436bf2bcSAndroid Build Coastguard Worker 			switch (field->size) {
5993*436bf2bcSAndroid Build Coastguard Worker 			case 4:
5994*436bf2bcSAndroid Build Coastguard Worker 				/*
5995*436bf2bcSAndroid Build Coastguard Worker 				 * If field is long then print it in hex.
5996*436bf2bcSAndroid Build Coastguard Worker 				 * A long usually stores pointers.
5997*436bf2bcSAndroid Build Coastguard Worker 				 */
5998*436bf2bcSAndroid Build Coastguard Worker 				if (field->flags & TEP_FIELD_IS_LONG)
5999*436bf2bcSAndroid Build Coastguard Worker 					trace_seq_printf(s, "0x%x", (int)val);
6000*436bf2bcSAndroid Build Coastguard Worker 				else
6001*436bf2bcSAndroid Build Coastguard Worker 					trace_seq_printf(s, "%d", (int)val);
6002*436bf2bcSAndroid Build Coastguard Worker 				break;
6003*436bf2bcSAndroid Build Coastguard Worker 			case 2:
6004*436bf2bcSAndroid Build Coastguard Worker 				trace_seq_printf(s, "%2d", (short)val);
6005*436bf2bcSAndroid Build Coastguard Worker 				break;
6006*436bf2bcSAndroid Build Coastguard Worker 			case 1:
6007*436bf2bcSAndroid Build Coastguard Worker 				trace_seq_printf(s, "%1d", (char)val);
6008*436bf2bcSAndroid Build Coastguard Worker 				break;
6009*436bf2bcSAndroid Build Coastguard Worker 			default:
6010*436bf2bcSAndroid Build Coastguard Worker 				trace_seq_printf(s, "%lld", val);
6011*436bf2bcSAndroid Build Coastguard Worker 			}
6012*436bf2bcSAndroid Build Coastguard Worker 		} else {
6013*436bf2bcSAndroid Build Coastguard Worker 			if (field->flags & TEP_FIELD_IS_LONG)
6014*436bf2bcSAndroid Build Coastguard Worker 				trace_seq_printf(s, "0x%llx", val);
6015*436bf2bcSAndroid Build Coastguard Worker 			else
6016*436bf2bcSAndroid Build Coastguard Worker 				trace_seq_printf(s, "%llu", val);
6017*436bf2bcSAndroid Build Coastguard Worker 		}
6018*436bf2bcSAndroid Build Coastguard Worker 	}
6019*436bf2bcSAndroid Build Coastguard Worker 	trace_seq_terminate(s);
6020*436bf2bcSAndroid Build Coastguard Worker }
6021*436bf2bcSAndroid Build Coastguard Worker 
6022*436bf2bcSAndroid Build Coastguard Worker static int print_parse_data(struct tep_print_parse *parse, struct trace_seq *s,
6023*436bf2bcSAndroid Build Coastguard Worker 			    void *data, int size, struct tep_event *event, bool raw);
6024*436bf2bcSAndroid Build Coastguard Worker 
print_field(struct trace_seq * s,void * data,int size,struct tep_format_field * field,struct tep_print_parse ** parse_ptr,bool raw)6025*436bf2bcSAndroid Build Coastguard Worker static inline void print_field(struct trace_seq *s, void *data, int size,
6026*436bf2bcSAndroid Build Coastguard Worker 				    struct tep_format_field *field,
6027*436bf2bcSAndroid Build Coastguard Worker 				    struct tep_print_parse **parse_ptr, bool raw)
6028*436bf2bcSAndroid Build Coastguard Worker {
6029*436bf2bcSAndroid Build Coastguard Worker 	struct tep_event *event = field->event;
6030*436bf2bcSAndroid Build Coastguard Worker 	struct tep_print_parse *start_parse;
6031*436bf2bcSAndroid Build Coastguard Worker 	struct tep_print_parse *parse;
6032*436bf2bcSAndroid Build Coastguard Worker 	struct tep_print_arg *arg;
6033*436bf2bcSAndroid Build Coastguard Worker 	bool has_0x = false;
6034*436bf2bcSAndroid Build Coastguard Worker 
6035*436bf2bcSAndroid Build Coastguard Worker 	parse = parse_ptr ? *parse_ptr : event->print_fmt.print_cache;
6036*436bf2bcSAndroid Build Coastguard Worker 
6037*436bf2bcSAndroid Build Coastguard Worker 	if (!parse || event->flags & TEP_EVENT_FL_FAILED)
6038*436bf2bcSAndroid Build Coastguard Worker 		goto out;
6039*436bf2bcSAndroid Build Coastguard Worker 
6040*436bf2bcSAndroid Build Coastguard Worker 	if (field->flags & (TEP_FIELD_IS_ARRAY | TEP_FIELD_IS_STRING))
6041*436bf2bcSAndroid Build Coastguard Worker 		goto out;
6042*436bf2bcSAndroid Build Coastguard Worker 
6043*436bf2bcSAndroid Build Coastguard Worker 	start_parse = parse;
6044*436bf2bcSAndroid Build Coastguard Worker 	do {
6045*436bf2bcSAndroid Build Coastguard Worker 		if (parse->type == PRINT_FMT_STRING) {
6046*436bf2bcSAndroid Build Coastguard Worker 			int len = strlen(parse->format);
6047*436bf2bcSAndroid Build Coastguard Worker 
6048*436bf2bcSAndroid Build Coastguard Worker 			if (len > 1 &&
6049*436bf2bcSAndroid Build Coastguard Worker 			    strcmp(parse->format + (len -2), "0x") == 0)
6050*436bf2bcSAndroid Build Coastguard Worker 				has_0x = true;
6051*436bf2bcSAndroid Build Coastguard Worker 			else
6052*436bf2bcSAndroid Build Coastguard Worker 				has_0x = false;
6053*436bf2bcSAndroid Build Coastguard Worker 
6054*436bf2bcSAndroid Build Coastguard Worker 			goto next;
6055*436bf2bcSAndroid Build Coastguard Worker 		}
6056*436bf2bcSAndroid Build Coastguard Worker 
6057*436bf2bcSAndroid Build Coastguard Worker 		arg = parse->arg;
6058*436bf2bcSAndroid Build Coastguard Worker 
6059*436bf2bcSAndroid Build Coastguard Worker 		while (arg && arg->type == TEP_PRINT_TYPE)
6060*436bf2bcSAndroid Build Coastguard Worker 			arg = arg->typecast.item;
6061*436bf2bcSAndroid Build Coastguard Worker 
6062*436bf2bcSAndroid Build Coastguard Worker 		if (!arg || arg->type != TEP_PRINT_FIELD ||
6063*436bf2bcSAndroid Build Coastguard Worker 		    arg->field.field != field) {
6064*436bf2bcSAndroid Build Coastguard Worker 			has_0x = false;
6065*436bf2bcSAndroid Build Coastguard Worker 			goto next;
6066*436bf2bcSAndroid Build Coastguard Worker 		}
6067*436bf2bcSAndroid Build Coastguard Worker 
6068*436bf2bcSAndroid Build Coastguard Worker 		if (has_0x)
6069*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_puts(s, "0x");
6070*436bf2bcSAndroid Build Coastguard Worker 
6071*436bf2bcSAndroid Build Coastguard Worker 		print_parse_data(parse, s, data, size, event, raw);
6072*436bf2bcSAndroid Build Coastguard Worker 
6073*436bf2bcSAndroid Build Coastguard Worker 		if (parse_ptr)
6074*436bf2bcSAndroid Build Coastguard Worker 			*parse_ptr = parse->next;
6075*436bf2bcSAndroid Build Coastguard Worker 
6076*436bf2bcSAndroid Build Coastguard Worker 		return;
6077*436bf2bcSAndroid Build Coastguard Worker 
6078*436bf2bcSAndroid Build Coastguard Worker  next:
6079*436bf2bcSAndroid Build Coastguard Worker 		parse = parse->next ? parse->next :
6080*436bf2bcSAndroid Build Coastguard Worker 				      event->print_fmt.print_cache;
6081*436bf2bcSAndroid Build Coastguard Worker 	} while (parse != start_parse);
6082*436bf2bcSAndroid Build Coastguard Worker 
6083*436bf2bcSAndroid Build Coastguard Worker  out:
6084*436bf2bcSAndroid Build Coastguard Worker 	/* Not found. */
6085*436bf2bcSAndroid Build Coastguard Worker 	print_field_raw(s, data, size, field);
6086*436bf2bcSAndroid Build Coastguard Worker }
6087*436bf2bcSAndroid Build Coastguard Worker 
6088*436bf2bcSAndroid Build Coastguard Worker /**
6089*436bf2bcSAndroid Build Coastguard Worker  * tep_print_field_content - write out the raw content of a field
6090*436bf2bcSAndroid Build Coastguard Worker  * @s:    The trace_seq to write the content into
6091*436bf2bcSAndroid Build Coastguard Worker  * @data: The payload to extract the field from.
6092*436bf2bcSAndroid Build Coastguard Worker  * @size: The size of the payload.
6093*436bf2bcSAndroid Build Coastguard Worker  * @field: The field to extract
6094*436bf2bcSAndroid Build Coastguard Worker  *
6095*436bf2bcSAndroid Build Coastguard Worker  * Use @field to find the field content from within @data and write it
6096*436bf2bcSAndroid Build Coastguard Worker  * in human readable format into @s.
6097*436bf2bcSAndroid Build Coastguard Worker  *
6098*436bf2bcSAndroid Build Coastguard Worker  * It will not write anything on error (s->len will not move)
6099*436bf2bcSAndroid Build Coastguard Worker  */
tep_print_field_content(struct trace_seq * s,void * data,int size,struct tep_format_field * field)6100*436bf2bcSAndroid Build Coastguard Worker void tep_print_field_content(struct trace_seq *s, void *data, int size,
6101*436bf2bcSAndroid Build Coastguard Worker 			     struct tep_format_field *field)
6102*436bf2bcSAndroid Build Coastguard Worker {
6103*436bf2bcSAndroid Build Coastguard Worker 	print_field(s, data, size, field, NULL, false);
6104*436bf2bcSAndroid Build Coastguard Worker }
6105*436bf2bcSAndroid Build Coastguard Worker 
6106*436bf2bcSAndroid Build Coastguard Worker /** DEPRECATED **/
tep_print_field(struct trace_seq * s,void * data,struct tep_format_field * field)6107*436bf2bcSAndroid Build Coastguard Worker void tep_print_field(struct trace_seq *s, void *data,
6108*436bf2bcSAndroid Build Coastguard Worker 		     struct tep_format_field *field)
6109*436bf2bcSAndroid Build Coastguard Worker {
6110*436bf2bcSAndroid Build Coastguard Worker 	/* unsafe to use, should pass in size */
6111*436bf2bcSAndroid Build Coastguard Worker 	print_field(s, data, 4096, field, NULL, false);
6112*436bf2bcSAndroid Build Coastguard Worker }
6113*436bf2bcSAndroid Build Coastguard Worker 
6114*436bf2bcSAndroid Build Coastguard Worker static inline void
print_selected_fields(struct trace_seq * s,void * data,int size,struct tep_event * event,unsigned long long ignore_mask,bool raw)6115*436bf2bcSAndroid Build Coastguard Worker print_selected_fields(struct trace_seq *s, void *data, int size,
6116*436bf2bcSAndroid Build Coastguard Worker 		      struct tep_event *event,
6117*436bf2bcSAndroid Build Coastguard Worker 		      unsigned long long ignore_mask, bool raw)
6118*436bf2bcSAndroid Build Coastguard Worker {
6119*436bf2bcSAndroid Build Coastguard Worker 	struct tep_print_parse *parse = event->print_fmt.print_cache;
6120*436bf2bcSAndroid Build Coastguard Worker 	struct tep_format_field *field;
6121*436bf2bcSAndroid Build Coastguard Worker 	unsigned long long field_mask = 1;
6122*436bf2bcSAndroid Build Coastguard Worker 
6123*436bf2bcSAndroid Build Coastguard Worker 	field = event->format.fields;
6124*436bf2bcSAndroid Build Coastguard Worker 	for(; field; field = field->next, field_mask <<= 1) {
6125*436bf2bcSAndroid Build Coastguard Worker 		if (field_mask & ignore_mask)
6126*436bf2bcSAndroid Build Coastguard Worker 			continue;
6127*436bf2bcSAndroid Build Coastguard Worker 
6128*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_printf(s, " %s=", field->name);
6129*436bf2bcSAndroid Build Coastguard Worker 		print_field(s, data, size, field, &parse, raw);
6130*436bf2bcSAndroid Build Coastguard Worker 	}
6131*436bf2bcSAndroid Build Coastguard Worker }
6132*436bf2bcSAndroid Build Coastguard Worker 
tep_print_fields(struct trace_seq * s,void * data,int size,struct tep_event * event)6133*436bf2bcSAndroid Build Coastguard Worker void tep_print_fields(struct trace_seq *s, void *data,
6134*436bf2bcSAndroid Build Coastguard Worker 		      int size, struct tep_event *event)
6135*436bf2bcSAndroid Build Coastguard Worker {
6136*436bf2bcSAndroid Build Coastguard Worker 	print_selected_fields(s, data, size, event, 0, false);
6137*436bf2bcSAndroid Build Coastguard Worker }
6138*436bf2bcSAndroid Build Coastguard Worker 
6139*436bf2bcSAndroid Build Coastguard Worker /**
6140*436bf2bcSAndroid Build Coastguard Worker  * tep_record_print_fields - print the field name followed by the
6141*436bf2bcSAndroid Build Coastguard Worker  * record's field value.
6142*436bf2bcSAndroid Build Coastguard Worker  * @s: The seq to print to
6143*436bf2bcSAndroid Build Coastguard Worker  * @record: The record to get the event from
6144*436bf2bcSAndroid Build Coastguard Worker  * @event: The event that the field is for
6145*436bf2bcSAndroid Build Coastguard Worker  */
tep_record_print_fields(struct trace_seq * s,struct tep_record * record,struct tep_event * event)6146*436bf2bcSAndroid Build Coastguard Worker void tep_record_print_fields(struct trace_seq *s,
6147*436bf2bcSAndroid Build Coastguard Worker 			     struct tep_record *record,
6148*436bf2bcSAndroid Build Coastguard Worker 			     struct tep_event *event)
6149*436bf2bcSAndroid Build Coastguard Worker {
6150*436bf2bcSAndroid Build Coastguard Worker 	print_selected_fields(s, record->data, record->size, event, 0, false);
6151*436bf2bcSAndroid Build Coastguard Worker }
6152*436bf2bcSAndroid Build Coastguard Worker 
6153*436bf2bcSAndroid Build Coastguard Worker /**
6154*436bf2bcSAndroid Build Coastguard Worker  * tep_record_print_selected_fields - print the field name followed by the
6155*436bf2bcSAndroid Build Coastguard Worker  * record's field value for a selected subset of record fields.
6156*436bf2bcSAndroid Build Coastguard Worker  * @s: The seq to print to
6157*436bf2bcSAndroid Build Coastguard Worker  * @record: The record to get the event from
6158*436bf2bcSAndroid Build Coastguard Worker  * @event: The event that the field is for
6159*436bf2bcSAndroid Build Coastguard Worker  * @select_mask: Bit mask defining the fields to print
6160*436bf2bcSAndroid Build Coastguard Worker  */
tep_record_print_selected_fields(struct trace_seq * s,struct tep_record * record,struct tep_event * event,unsigned long long select_mask)6161*436bf2bcSAndroid Build Coastguard Worker void tep_record_print_selected_fields(struct trace_seq *s,
6162*436bf2bcSAndroid Build Coastguard Worker 				      struct tep_record *record,
6163*436bf2bcSAndroid Build Coastguard Worker 				      struct tep_event *event,
6164*436bf2bcSAndroid Build Coastguard Worker 				      unsigned long long select_mask)
6165*436bf2bcSAndroid Build Coastguard Worker {
6166*436bf2bcSAndroid Build Coastguard Worker 	unsigned long long ignore_mask = ~select_mask;
6167*436bf2bcSAndroid Build Coastguard Worker 
6168*436bf2bcSAndroid Build Coastguard Worker 	print_selected_fields(s, record->data, record->size, event, ignore_mask, false);
6169*436bf2bcSAndroid Build Coastguard Worker }
6170*436bf2bcSAndroid Build Coastguard Worker 
print_function(struct trace_seq * s,const char * format,void * data,int size,struct tep_event * event,struct tep_print_arg * arg,bool raw)6171*436bf2bcSAndroid Build Coastguard Worker static int print_function(struct trace_seq *s, const char *format,
6172*436bf2bcSAndroid Build Coastguard Worker 			  void *data, int size, struct tep_event *event,
6173*436bf2bcSAndroid Build Coastguard Worker 			  struct tep_print_arg *arg, bool raw)
6174*436bf2bcSAndroid Build Coastguard Worker {
6175*436bf2bcSAndroid Build Coastguard Worker 	struct func_map *func;
6176*436bf2bcSAndroid Build Coastguard Worker 	unsigned long long val;
6177*436bf2bcSAndroid Build Coastguard Worker 
6178*436bf2bcSAndroid Build Coastguard Worker 	val = eval_num_arg(data, size, event, arg);
6179*436bf2bcSAndroid Build Coastguard Worker 	func = find_func(event->tep, val);
6180*436bf2bcSAndroid Build Coastguard Worker 	if (func) {
6181*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_puts(s, func->func);
6182*436bf2bcSAndroid Build Coastguard Worker 		if (*format == 'F' || *format == 'S')
6183*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_printf(s, "+0x%llx", val - func->addr);
6184*436bf2bcSAndroid Build Coastguard Worker 	}
6185*436bf2bcSAndroid Build Coastguard Worker 
6186*436bf2bcSAndroid Build Coastguard Worker 	if (!func || raw) {
6187*436bf2bcSAndroid Build Coastguard Worker 		if (raw)
6188*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_puts(s, " (");
6189*436bf2bcSAndroid Build Coastguard Worker 		if (event->tep->long_size == 4)
6190*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_printf(s, "0x%lx", (long)val);
6191*436bf2bcSAndroid Build Coastguard Worker 		else
6192*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_printf(s, "0x%llx", (long long)val);
6193*436bf2bcSAndroid Build Coastguard Worker 		if (raw)
6194*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_puts(s, ")");
6195*436bf2bcSAndroid Build Coastguard Worker 	}
6196*436bf2bcSAndroid Build Coastguard Worker 
6197*436bf2bcSAndroid Build Coastguard Worker 	return 0;
6198*436bf2bcSAndroid Build Coastguard Worker }
6199*436bf2bcSAndroid Build Coastguard Worker 
print_arg_pointer(struct trace_seq * s,const char * format,int plen,void * data,int size,struct tep_event * event,struct tep_print_arg * arg,bool raw)6200*436bf2bcSAndroid Build Coastguard Worker static int print_arg_pointer(struct trace_seq *s, const char *format, int plen,
6201*436bf2bcSAndroid Build Coastguard Worker 			     void *data, int size,
6202*436bf2bcSAndroid Build Coastguard Worker 			     struct tep_event *event, struct tep_print_arg *arg,
6203*436bf2bcSAndroid Build Coastguard Worker 			     bool raw)
6204*436bf2bcSAndroid Build Coastguard Worker {
6205*436bf2bcSAndroid Build Coastguard Worker 	unsigned long long val;
6206*436bf2bcSAndroid Build Coastguard Worker 	int ret = 1;
6207*436bf2bcSAndroid Build Coastguard Worker 
6208*436bf2bcSAndroid Build Coastguard Worker 	if (arg->type == TEP_PRINT_BSTRING) {
6209*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_puts(s, arg->string.string);
6210*436bf2bcSAndroid Build Coastguard Worker 		return 0;
6211*436bf2bcSAndroid Build Coastguard Worker 	}
6212*436bf2bcSAndroid Build Coastguard Worker 	while (*format) {
6213*436bf2bcSAndroid Build Coastguard Worker 		if (*format == 'p') {
6214*436bf2bcSAndroid Build Coastguard Worker 			format++;
6215*436bf2bcSAndroid Build Coastguard Worker 			break;
6216*436bf2bcSAndroid Build Coastguard Worker 		}
6217*436bf2bcSAndroid Build Coastguard Worker 		format++;
6218*436bf2bcSAndroid Build Coastguard Worker 	}
6219*436bf2bcSAndroid Build Coastguard Worker 
6220*436bf2bcSAndroid Build Coastguard Worker 	switch (*format) {
6221*436bf2bcSAndroid Build Coastguard Worker 	case 'F':
6222*436bf2bcSAndroid Build Coastguard Worker 	case 'f':
6223*436bf2bcSAndroid Build Coastguard Worker 	case 'S':
6224*436bf2bcSAndroid Build Coastguard Worker 	case 's':
6225*436bf2bcSAndroid Build Coastguard Worker 		ret += print_function(s, format, data, size, event, arg, raw);
6226*436bf2bcSAndroid Build Coastguard Worker 		break;
6227*436bf2bcSAndroid Build Coastguard Worker 	case 'M':
6228*436bf2bcSAndroid Build Coastguard Worker 	case 'm':
6229*436bf2bcSAndroid Build Coastguard Worker 		ret += print_mac_arg(s, format, data, size, event, arg);
6230*436bf2bcSAndroid Build Coastguard Worker 		break;
6231*436bf2bcSAndroid Build Coastguard Worker 	case 'I':
6232*436bf2bcSAndroid Build Coastguard Worker 	case 'i':
6233*436bf2bcSAndroid Build Coastguard Worker 		ret += print_ip_arg(s, format, data, size, event, arg);
6234*436bf2bcSAndroid Build Coastguard Worker 		break;
6235*436bf2bcSAndroid Build Coastguard Worker 	case 'U':
6236*436bf2bcSAndroid Build Coastguard Worker 		ret += print_uuid_arg(s, format, data, size, event, arg);
6237*436bf2bcSAndroid Build Coastguard Worker 		break;
6238*436bf2bcSAndroid Build Coastguard Worker 	case 'h':
6239*436bf2bcSAndroid Build Coastguard Worker 		ret += print_raw_buff_arg(s, format, data, size, event, arg, plen);
6240*436bf2bcSAndroid Build Coastguard Worker 		break;
6241*436bf2bcSAndroid Build Coastguard Worker 	default:
6242*436bf2bcSAndroid Build Coastguard Worker 		ret = 0;
6243*436bf2bcSAndroid Build Coastguard Worker 		val = eval_num_arg(data, size, event, arg);
6244*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_printf(s, "%p", (void *)(intptr_t)val);
6245*436bf2bcSAndroid Build Coastguard Worker 		break;
6246*436bf2bcSAndroid Build Coastguard Worker 	}
6247*436bf2bcSAndroid Build Coastguard Worker 
6248*436bf2bcSAndroid Build Coastguard Worker 	return ret;
6249*436bf2bcSAndroid Build Coastguard Worker 
6250*436bf2bcSAndroid Build Coastguard Worker }
6251*436bf2bcSAndroid Build Coastguard Worker 
print_arg_number(struct trace_seq * s,const char * format,int plen,void * data,int size,int ls,struct tep_event * event,struct tep_print_arg * arg)6252*436bf2bcSAndroid Build Coastguard Worker static int print_arg_number(struct trace_seq *s, const char *format, int plen,
6253*436bf2bcSAndroid Build Coastguard Worker 			    void *data, int size, int ls,
6254*436bf2bcSAndroid Build Coastguard Worker 			    struct tep_event *event, struct tep_print_arg *arg)
6255*436bf2bcSAndroid Build Coastguard Worker {
6256*436bf2bcSAndroid Build Coastguard Worker 	unsigned long long val;
6257*436bf2bcSAndroid Build Coastguard Worker 
6258*436bf2bcSAndroid Build Coastguard Worker 	val = eval_num_arg(data, size, event, arg);
6259*436bf2bcSAndroid Build Coastguard Worker 
6260*436bf2bcSAndroid Build Coastguard Worker 	switch (ls) {
6261*436bf2bcSAndroid Build Coastguard Worker 	case -2:
6262*436bf2bcSAndroid Build Coastguard Worker 		if (plen >= 0)
6263*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_printf(s, format, plen, (char)val);
6264*436bf2bcSAndroid Build Coastguard Worker 		else
6265*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_printf(s, format, (char)val);
6266*436bf2bcSAndroid Build Coastguard Worker 		break;
6267*436bf2bcSAndroid Build Coastguard Worker 	case -1:
6268*436bf2bcSAndroid Build Coastguard Worker 		if (plen >= 0)
6269*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_printf(s, format, plen, (short)val);
6270*436bf2bcSAndroid Build Coastguard Worker 		else
6271*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_printf(s, format, (short)val);
6272*436bf2bcSAndroid Build Coastguard Worker 		break;
6273*436bf2bcSAndroid Build Coastguard Worker 	case 0:
6274*436bf2bcSAndroid Build Coastguard Worker 		if (plen >= 0)
6275*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_printf(s, format, plen, (int)val);
6276*436bf2bcSAndroid Build Coastguard Worker 		else
6277*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_printf(s, format, (int)val);
6278*436bf2bcSAndroid Build Coastguard Worker 		break;
6279*436bf2bcSAndroid Build Coastguard Worker 	case 1:
6280*436bf2bcSAndroid Build Coastguard Worker 		if (plen >= 0)
6281*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_printf(s, format, plen, (long)val);
6282*436bf2bcSAndroid Build Coastguard Worker 		else
6283*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_printf(s, format, (long)val);
6284*436bf2bcSAndroid Build Coastguard Worker 		break;
6285*436bf2bcSAndroid Build Coastguard Worker 	case 2:
6286*436bf2bcSAndroid Build Coastguard Worker 		if (plen >= 0)
6287*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_printf(s, format, plen, (long long)val);
6288*436bf2bcSAndroid Build Coastguard Worker 		else
6289*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_printf(s, format, (long long)val);
6290*436bf2bcSAndroid Build Coastguard Worker 		break;
6291*436bf2bcSAndroid Build Coastguard Worker 	default:
6292*436bf2bcSAndroid Build Coastguard Worker 		do_warning_event(event, "bad count (%d)", ls);
6293*436bf2bcSAndroid Build Coastguard Worker 		event->flags |= TEP_EVENT_FL_FAILED;
6294*436bf2bcSAndroid Build Coastguard Worker 	}
6295*436bf2bcSAndroid Build Coastguard Worker 	return 0;
6296*436bf2bcSAndroid Build Coastguard Worker }
6297*436bf2bcSAndroid Build Coastguard Worker 
6298*436bf2bcSAndroid Build Coastguard Worker 
print_arg_string(struct trace_seq * s,const char * format,int plen,void * data,int size,struct tep_event * event,struct tep_print_arg * arg)6299*436bf2bcSAndroid Build Coastguard Worker static void print_arg_string(struct trace_seq *s, const char *format, int plen,
6300*436bf2bcSAndroid Build Coastguard Worker 			     void *data, int size,
6301*436bf2bcSAndroid Build Coastguard Worker 			     struct tep_event *event, struct tep_print_arg *arg)
6302*436bf2bcSAndroid Build Coastguard Worker {
6303*436bf2bcSAndroid Build Coastguard Worker 	struct trace_seq p;
6304*436bf2bcSAndroid Build Coastguard Worker 
6305*436bf2bcSAndroid Build Coastguard Worker 	/* Use helper trace_seq */
6306*436bf2bcSAndroid Build Coastguard Worker 	trace_seq_init(&p);
6307*436bf2bcSAndroid Build Coastguard Worker 	print_str_arg(&p, data, size, event,
6308*436bf2bcSAndroid Build Coastguard Worker 		      format, plen, arg);
6309*436bf2bcSAndroid Build Coastguard Worker 	trace_seq_terminate(&p);
6310*436bf2bcSAndroid Build Coastguard Worker 	trace_seq_puts(s, p.buffer);
6311*436bf2bcSAndroid Build Coastguard Worker 	trace_seq_destroy(&p);
6312*436bf2bcSAndroid Build Coastguard Worker }
6313*436bf2bcSAndroid Build Coastguard Worker 
parse_arg_format_pointer(const char * format)6314*436bf2bcSAndroid Build Coastguard Worker static int parse_arg_format_pointer(const char *format)
6315*436bf2bcSAndroid Build Coastguard Worker {
6316*436bf2bcSAndroid Build Coastguard Worker 	int ret = 0;
6317*436bf2bcSAndroid Build Coastguard Worker 	int index;
6318*436bf2bcSAndroid Build Coastguard Worker 	int loop;
6319*436bf2bcSAndroid Build Coastguard Worker 
6320*436bf2bcSAndroid Build Coastguard Worker 	switch (*format) {
6321*436bf2bcSAndroid Build Coastguard Worker 	case 'F':
6322*436bf2bcSAndroid Build Coastguard Worker 	case 'S':
6323*436bf2bcSAndroid Build Coastguard Worker 	case 'f':
6324*436bf2bcSAndroid Build Coastguard Worker 	case 's':
6325*436bf2bcSAndroid Build Coastguard Worker 		ret++;
6326*436bf2bcSAndroid Build Coastguard Worker 		break;
6327*436bf2bcSAndroid Build Coastguard Worker 	case 'M':
6328*436bf2bcSAndroid Build Coastguard Worker 	case 'm':
6329*436bf2bcSAndroid Build Coastguard Worker 		/* [mM]R , [mM]F */
6330*436bf2bcSAndroid Build Coastguard Worker 		switch (format[1]) {
6331*436bf2bcSAndroid Build Coastguard Worker 		case 'R':
6332*436bf2bcSAndroid Build Coastguard Worker 		case 'F':
6333*436bf2bcSAndroid Build Coastguard Worker 			ret++;
6334*436bf2bcSAndroid Build Coastguard Worker 			break;
6335*436bf2bcSAndroid Build Coastguard Worker 		}
6336*436bf2bcSAndroid Build Coastguard Worker 		ret++;
6337*436bf2bcSAndroid Build Coastguard Worker 		break;
6338*436bf2bcSAndroid Build Coastguard Worker 	case 'I':
6339*436bf2bcSAndroid Build Coastguard Worker 	case 'i':
6340*436bf2bcSAndroid Build Coastguard Worker 		index = 2;
6341*436bf2bcSAndroid Build Coastguard Worker 		loop = 1;
6342*436bf2bcSAndroid Build Coastguard Worker 		switch (format[1]) {
6343*436bf2bcSAndroid Build Coastguard Worker 		case 'S':
6344*436bf2bcSAndroid Build Coastguard Worker 			/*[S][pfs]*/
6345*436bf2bcSAndroid Build Coastguard Worker 			while (loop) {
6346*436bf2bcSAndroid Build Coastguard Worker 				switch (format[index]) {
6347*436bf2bcSAndroid Build Coastguard Worker 				case 'p':
6348*436bf2bcSAndroid Build Coastguard Worker 				case 'f':
6349*436bf2bcSAndroid Build Coastguard Worker 				case 's':
6350*436bf2bcSAndroid Build Coastguard Worker 					ret++;
6351*436bf2bcSAndroid Build Coastguard Worker 					index++;
6352*436bf2bcSAndroid Build Coastguard Worker 					break;
6353*436bf2bcSAndroid Build Coastguard Worker 				default:
6354*436bf2bcSAndroid Build Coastguard Worker 					loop = 0;
6355*436bf2bcSAndroid Build Coastguard Worker 					break;
6356*436bf2bcSAndroid Build Coastguard Worker 				}
6357*436bf2bcSAndroid Build Coastguard Worker 			}
6358*436bf2bcSAndroid Build Coastguard Worker 			/* fall through */
6359*436bf2bcSAndroid Build Coastguard Worker 		case '4':
6360*436bf2bcSAndroid Build Coastguard Worker 			/* [4S][hnbl] */
6361*436bf2bcSAndroid Build Coastguard Worker 			switch (format[index]) {
6362*436bf2bcSAndroid Build Coastguard Worker 			case 'h':
6363*436bf2bcSAndroid Build Coastguard Worker 			case 'n':
6364*436bf2bcSAndroid Build Coastguard Worker 			case 'l':
6365*436bf2bcSAndroid Build Coastguard Worker 			case 'b':
6366*436bf2bcSAndroid Build Coastguard Worker 				ret++;
6367*436bf2bcSAndroid Build Coastguard Worker 				index++;
6368*436bf2bcSAndroid Build Coastguard Worker 				break;
6369*436bf2bcSAndroid Build Coastguard Worker 			}
6370*436bf2bcSAndroid Build Coastguard Worker 			if (format[1] == '4') {
6371*436bf2bcSAndroid Build Coastguard Worker 				ret++;
6372*436bf2bcSAndroid Build Coastguard Worker 				break;
6373*436bf2bcSAndroid Build Coastguard Worker 			}
6374*436bf2bcSAndroid Build Coastguard Worker 			/* fall through */
6375*436bf2bcSAndroid Build Coastguard Worker 		case '6':
6376*436bf2bcSAndroid Build Coastguard Worker 			/* [6S]c */
6377*436bf2bcSAndroid Build Coastguard Worker 			if (format[index] == 'c')
6378*436bf2bcSAndroid Build Coastguard Worker 				ret++;
6379*436bf2bcSAndroid Build Coastguard Worker 			ret++;
6380*436bf2bcSAndroid Build Coastguard Worker 			break;
6381*436bf2bcSAndroid Build Coastguard Worker 		}
6382*436bf2bcSAndroid Build Coastguard Worker 		ret++;
6383*436bf2bcSAndroid Build Coastguard Worker 		break;
6384*436bf2bcSAndroid Build Coastguard Worker 	case 'U':
6385*436bf2bcSAndroid Build Coastguard Worker 		switch (format[1]) {
6386*436bf2bcSAndroid Build Coastguard Worker 		case 'L':
6387*436bf2bcSAndroid Build Coastguard Worker 		case 'l':
6388*436bf2bcSAndroid Build Coastguard Worker 		case 'B':
6389*436bf2bcSAndroid Build Coastguard Worker 		case 'b':
6390*436bf2bcSAndroid Build Coastguard Worker 			ret++;
6391*436bf2bcSAndroid Build Coastguard Worker 			break;
6392*436bf2bcSAndroid Build Coastguard Worker 		}
6393*436bf2bcSAndroid Build Coastguard Worker 		ret++;
6394*436bf2bcSAndroid Build Coastguard Worker 		break;
6395*436bf2bcSAndroid Build Coastguard Worker 	case 'h':
6396*436bf2bcSAndroid Build Coastguard Worker 		switch (format[1]) {
6397*436bf2bcSAndroid Build Coastguard Worker 		case 'C':
6398*436bf2bcSAndroid Build Coastguard Worker 		case 'D':
6399*436bf2bcSAndroid Build Coastguard Worker 		case 'N':
6400*436bf2bcSAndroid Build Coastguard Worker 			ret++;
6401*436bf2bcSAndroid Build Coastguard Worker 			break;
6402*436bf2bcSAndroid Build Coastguard Worker 		}
6403*436bf2bcSAndroid Build Coastguard Worker 		ret++;
6404*436bf2bcSAndroid Build Coastguard Worker 		break;
6405*436bf2bcSAndroid Build Coastguard Worker 	default:
6406*436bf2bcSAndroid Build Coastguard Worker 		break;
6407*436bf2bcSAndroid Build Coastguard Worker 	}
6408*436bf2bcSAndroid Build Coastguard Worker 
6409*436bf2bcSAndroid Build Coastguard Worker 	return ret;
6410*436bf2bcSAndroid Build Coastguard Worker }
6411*436bf2bcSAndroid Build Coastguard Worker 
free_parse_args(struct tep_print_parse * arg)6412*436bf2bcSAndroid Build Coastguard Worker static void free_parse_args(struct tep_print_parse *arg)
6413*436bf2bcSAndroid Build Coastguard Worker {
6414*436bf2bcSAndroid Build Coastguard Worker 	struct tep_print_parse *del;
6415*436bf2bcSAndroid Build Coastguard Worker 
6416*436bf2bcSAndroid Build Coastguard Worker 	while (arg) {
6417*436bf2bcSAndroid Build Coastguard Worker 		del = arg;
6418*436bf2bcSAndroid Build Coastguard Worker 		arg = del->next;
6419*436bf2bcSAndroid Build Coastguard Worker 		free(del->format);
6420*436bf2bcSAndroid Build Coastguard Worker 		free(del);
6421*436bf2bcSAndroid Build Coastguard Worker 	}
6422*436bf2bcSAndroid Build Coastguard Worker }
6423*436bf2bcSAndroid Build Coastguard Worker 
parse_arg_add(struct tep_print_parse ** parse,char * format,enum tep_print_parse_type type,struct tep_print_arg * arg,struct tep_print_arg * len_as_arg,int ls)6424*436bf2bcSAndroid Build Coastguard Worker static int parse_arg_add(struct tep_print_parse **parse, char *format,
6425*436bf2bcSAndroid Build Coastguard Worker 			 enum tep_print_parse_type type,
6426*436bf2bcSAndroid Build Coastguard Worker 			 struct tep_print_arg *arg,
6427*436bf2bcSAndroid Build Coastguard Worker 			 struct tep_print_arg *len_as_arg,
6428*436bf2bcSAndroid Build Coastguard Worker 			 int ls)
6429*436bf2bcSAndroid Build Coastguard Worker {
6430*436bf2bcSAndroid Build Coastguard Worker 	struct tep_print_parse *parg = NULL;
6431*436bf2bcSAndroid Build Coastguard Worker 
6432*436bf2bcSAndroid Build Coastguard Worker 	parg = calloc(1, sizeof(*parg));
6433*436bf2bcSAndroid Build Coastguard Worker 	if (!parg)
6434*436bf2bcSAndroid Build Coastguard Worker 		goto error;
6435*436bf2bcSAndroid Build Coastguard Worker 	parg->format = strdup(format);
6436*436bf2bcSAndroid Build Coastguard Worker 	if (!parg->format)
6437*436bf2bcSAndroid Build Coastguard Worker 		goto error;
6438*436bf2bcSAndroid Build Coastguard Worker 	parg->type = type;
6439*436bf2bcSAndroid Build Coastguard Worker 	parg->arg = arg;
6440*436bf2bcSAndroid Build Coastguard Worker 	parg->len_as_arg = len_as_arg;
6441*436bf2bcSAndroid Build Coastguard Worker 	parg->ls = ls;
6442*436bf2bcSAndroid Build Coastguard Worker 	*parse = parg;
6443*436bf2bcSAndroid Build Coastguard Worker 	return 0;
6444*436bf2bcSAndroid Build Coastguard Worker error:
6445*436bf2bcSAndroid Build Coastguard Worker 	if (parg) {
6446*436bf2bcSAndroid Build Coastguard Worker 		free(parg->format);
6447*436bf2bcSAndroid Build Coastguard Worker 		free(parg);
6448*436bf2bcSAndroid Build Coastguard Worker 	}
6449*436bf2bcSAndroid Build Coastguard Worker 	return -1;
6450*436bf2bcSAndroid Build Coastguard Worker }
6451*436bf2bcSAndroid Build Coastguard Worker 
parse_arg_format(struct tep_print_parse ** parse,struct tep_event * event,const char * format,struct tep_print_arg ** arg)6452*436bf2bcSAndroid Build Coastguard Worker static int parse_arg_format(struct tep_print_parse **parse,
6453*436bf2bcSAndroid Build Coastguard Worker 			    struct tep_event *event,
6454*436bf2bcSAndroid Build Coastguard Worker 			    const char *format, struct tep_print_arg **arg)
6455*436bf2bcSAndroid Build Coastguard Worker {
6456*436bf2bcSAndroid Build Coastguard Worker 	struct tep_print_arg *len_arg = NULL;
6457*436bf2bcSAndroid Build Coastguard Worker 	char print_format[32];
6458*436bf2bcSAndroid Build Coastguard Worker 	const char *start = format;
6459*436bf2bcSAndroid Build Coastguard Worker 	int ret = 0;
6460*436bf2bcSAndroid Build Coastguard Worker 	int ls = 0;
6461*436bf2bcSAndroid Build Coastguard Worker 	int res;
6462*436bf2bcSAndroid Build Coastguard Worker 	int len;
6463*436bf2bcSAndroid Build Coastguard Worker 
6464*436bf2bcSAndroid Build Coastguard Worker 	format++;
6465*436bf2bcSAndroid Build Coastguard Worker 	ret++;
6466*436bf2bcSAndroid Build Coastguard Worker 	for (; *format; format++) {
6467*436bf2bcSAndroid Build Coastguard Worker 		switch (*format) {
6468*436bf2bcSAndroid Build Coastguard Worker 		case '#':
6469*436bf2bcSAndroid Build Coastguard Worker 			/* FIXME: need to handle properly */
6470*436bf2bcSAndroid Build Coastguard Worker 			break;
6471*436bf2bcSAndroid Build Coastguard Worker 		case 'h':
6472*436bf2bcSAndroid Build Coastguard Worker 			ls--;
6473*436bf2bcSAndroid Build Coastguard Worker 			break;
6474*436bf2bcSAndroid Build Coastguard Worker 		case 'l':
6475*436bf2bcSAndroid Build Coastguard Worker 			ls++;
6476*436bf2bcSAndroid Build Coastguard Worker 			break;
6477*436bf2bcSAndroid Build Coastguard Worker 		case 'L':
6478*436bf2bcSAndroid Build Coastguard Worker 			ls = 2;
6479*436bf2bcSAndroid Build Coastguard Worker 			break;
6480*436bf2bcSAndroid Build Coastguard Worker 		case 'z':
6481*436bf2bcSAndroid Build Coastguard Worker 		case 'Z':
6482*436bf2bcSAndroid Build Coastguard Worker 			ls = 1;
6483*436bf2bcSAndroid Build Coastguard Worker 			break;
6484*436bf2bcSAndroid Build Coastguard Worker 		case '.':
6485*436bf2bcSAndroid Build Coastguard Worker 		case '0' ... '9':
6486*436bf2bcSAndroid Build Coastguard Worker 		case '-':
6487*436bf2bcSAndroid Build Coastguard Worker 		case '+':
6488*436bf2bcSAndroid Build Coastguard Worker 			break;
6489*436bf2bcSAndroid Build Coastguard Worker 		case '*':
6490*436bf2bcSAndroid Build Coastguard Worker 			/* The argument is the length. */
6491*436bf2bcSAndroid Build Coastguard Worker 			if (!*arg) {
6492*436bf2bcSAndroid Build Coastguard Worker 				do_warning_event(event, "no argument match");
6493*436bf2bcSAndroid Build Coastguard Worker 				event->flags |= TEP_EVENT_FL_FAILED;
6494*436bf2bcSAndroid Build Coastguard Worker 				goto out_failed;
6495*436bf2bcSAndroid Build Coastguard Worker 			}
6496*436bf2bcSAndroid Build Coastguard Worker 			if (len_arg) {
6497*436bf2bcSAndroid Build Coastguard Worker 				do_warning_event(event, "argument already matched");
6498*436bf2bcSAndroid Build Coastguard Worker 				event->flags |= TEP_EVENT_FL_FAILED;
6499*436bf2bcSAndroid Build Coastguard Worker 				goto out_failed;
6500*436bf2bcSAndroid Build Coastguard Worker 			}
6501*436bf2bcSAndroid Build Coastguard Worker 			len_arg = *arg;
6502*436bf2bcSAndroid Build Coastguard Worker 			*arg = (*arg)->next;
6503*436bf2bcSAndroid Build Coastguard Worker 			break;
6504*436bf2bcSAndroid Build Coastguard Worker 		case 'p':
6505*436bf2bcSAndroid Build Coastguard Worker 			if (!*arg) {
6506*436bf2bcSAndroid Build Coastguard Worker 				do_warning_event(event, "no argument match");
6507*436bf2bcSAndroid Build Coastguard Worker 				event->flags |= TEP_EVENT_FL_FAILED;
6508*436bf2bcSAndroid Build Coastguard Worker 				goto out_failed;
6509*436bf2bcSAndroid Build Coastguard Worker 			}
6510*436bf2bcSAndroid Build Coastguard Worker 			res = parse_arg_format_pointer(format + 1);
6511*436bf2bcSAndroid Build Coastguard Worker 			if (res > 0) {
6512*436bf2bcSAndroid Build Coastguard Worker 				format += res;
6513*436bf2bcSAndroid Build Coastguard Worker 				ret += res;
6514*436bf2bcSAndroid Build Coastguard Worker 			}
6515*436bf2bcSAndroid Build Coastguard Worker 			len = ((unsigned long)format + 1) -
6516*436bf2bcSAndroid Build Coastguard Worker 				(unsigned long)start;
6517*436bf2bcSAndroid Build Coastguard Worker 			/* should never happen */
6518*436bf2bcSAndroid Build Coastguard Worker 			if (len > 31) {
6519*436bf2bcSAndroid Build Coastguard Worker 				do_warning_event(event, "bad format!");
6520*436bf2bcSAndroid Build Coastguard Worker 				event->flags |= TEP_EVENT_FL_FAILED;
6521*436bf2bcSAndroid Build Coastguard Worker 				len = 31;
6522*436bf2bcSAndroid Build Coastguard Worker 			}
6523*436bf2bcSAndroid Build Coastguard Worker 			memcpy(print_format, start, len);
6524*436bf2bcSAndroid Build Coastguard Worker 			print_format[len] = 0;
6525*436bf2bcSAndroid Build Coastguard Worker 
6526*436bf2bcSAndroid Build Coastguard Worker 			parse_arg_add(parse, print_format,
6527*436bf2bcSAndroid Build Coastguard Worker 				      PRINT_FMT_ARG_POINTER, *arg, len_arg, ls);
6528*436bf2bcSAndroid Build Coastguard Worker 			*arg = (*arg)->next;
6529*436bf2bcSAndroid Build Coastguard Worker 			ret++;
6530*436bf2bcSAndroid Build Coastguard Worker 			return ret;
6531*436bf2bcSAndroid Build Coastguard Worker 		case 'c':
6532*436bf2bcSAndroid Build Coastguard Worker 		case 'd':
6533*436bf2bcSAndroid Build Coastguard Worker 		case 'u':
6534*436bf2bcSAndroid Build Coastguard Worker 		case 'i':
6535*436bf2bcSAndroid Build Coastguard Worker 		case 'x':
6536*436bf2bcSAndroid Build Coastguard Worker 		case 'X':
6537*436bf2bcSAndroid Build Coastguard Worker 		case 'o':
6538*436bf2bcSAndroid Build Coastguard Worker 			if (!*arg) {
6539*436bf2bcSAndroid Build Coastguard Worker 				do_warning_event(event, "no argument match");
6540*436bf2bcSAndroid Build Coastguard Worker 				event->flags |= TEP_EVENT_FL_FAILED;
6541*436bf2bcSAndroid Build Coastguard Worker 				goto out_failed;
6542*436bf2bcSAndroid Build Coastguard Worker 			}
6543*436bf2bcSAndroid Build Coastguard Worker 
6544*436bf2bcSAndroid Build Coastguard Worker 			len = ((unsigned long)format + 1) -
6545*436bf2bcSAndroid Build Coastguard Worker 				(unsigned long)start;
6546*436bf2bcSAndroid Build Coastguard Worker 
6547*436bf2bcSAndroid Build Coastguard Worker 			/* should never happen */
6548*436bf2bcSAndroid Build Coastguard Worker 			if (len > 30) {
6549*436bf2bcSAndroid Build Coastguard Worker 				do_warning_event(event, "bad format!");
6550*436bf2bcSAndroid Build Coastguard Worker 				event->flags |= TEP_EVENT_FL_FAILED;
6551*436bf2bcSAndroid Build Coastguard Worker 				len = 31;
6552*436bf2bcSAndroid Build Coastguard Worker 			}
6553*436bf2bcSAndroid Build Coastguard Worker 			memcpy(print_format, start, len);
6554*436bf2bcSAndroid Build Coastguard Worker 			print_format[len] = 0;
6555*436bf2bcSAndroid Build Coastguard Worker 
6556*436bf2bcSAndroid Build Coastguard Worker 			if (event->tep->long_size == 8 && ls == 1 &&
6557*436bf2bcSAndroid Build Coastguard Worker 			    sizeof(long) != 8) {
6558*436bf2bcSAndroid Build Coastguard Worker 				char *p;
6559*436bf2bcSAndroid Build Coastguard Worker 
6560*436bf2bcSAndroid Build Coastguard Worker 				/* make %l into %ll */
6561*436bf2bcSAndroid Build Coastguard Worker 				if (ls == 1 && (p = strchr(print_format, 'l')))
6562*436bf2bcSAndroid Build Coastguard Worker 					memmove(p+1, p, strlen(p)+1);
6563*436bf2bcSAndroid Build Coastguard Worker 				ls = 2;
6564*436bf2bcSAndroid Build Coastguard Worker 			}
6565*436bf2bcSAndroid Build Coastguard Worker 			if (ls < -2 || ls > 2) {
6566*436bf2bcSAndroid Build Coastguard Worker 				do_warning_event(event, "bad count (%d)", ls);
6567*436bf2bcSAndroid Build Coastguard Worker 				event->flags |= TEP_EVENT_FL_FAILED;
6568*436bf2bcSAndroid Build Coastguard Worker 			}
6569*436bf2bcSAndroid Build Coastguard Worker 			parse_arg_add(parse, print_format,
6570*436bf2bcSAndroid Build Coastguard Worker 				      PRINT_FMT_ARG_DIGIT, *arg, len_arg, ls);
6571*436bf2bcSAndroid Build Coastguard Worker 			*arg = (*arg)->next;
6572*436bf2bcSAndroid Build Coastguard Worker 			ret++;
6573*436bf2bcSAndroid Build Coastguard Worker 			return ret;
6574*436bf2bcSAndroid Build Coastguard Worker 		case 's':
6575*436bf2bcSAndroid Build Coastguard Worker 			if (!*arg) {
6576*436bf2bcSAndroid Build Coastguard Worker 				do_warning_event(event, "no matching argument");
6577*436bf2bcSAndroid Build Coastguard Worker 				event->flags |= TEP_EVENT_FL_FAILED;
6578*436bf2bcSAndroid Build Coastguard Worker 				goto out_failed;
6579*436bf2bcSAndroid Build Coastguard Worker 			}
6580*436bf2bcSAndroid Build Coastguard Worker 
6581*436bf2bcSAndroid Build Coastguard Worker 			len = ((unsigned long)format + 1) -
6582*436bf2bcSAndroid Build Coastguard Worker 				(unsigned long)start;
6583*436bf2bcSAndroid Build Coastguard Worker 
6584*436bf2bcSAndroid Build Coastguard Worker 			/* should never happen */
6585*436bf2bcSAndroid Build Coastguard Worker 			if (len > 31) {
6586*436bf2bcSAndroid Build Coastguard Worker 				do_warning_event(event, "bad format!");
6587*436bf2bcSAndroid Build Coastguard Worker 				event->flags |= TEP_EVENT_FL_FAILED;
6588*436bf2bcSAndroid Build Coastguard Worker 				len = 31;
6589*436bf2bcSAndroid Build Coastguard Worker 			}
6590*436bf2bcSAndroid Build Coastguard Worker 
6591*436bf2bcSAndroid Build Coastguard Worker 			memcpy(print_format, start, len);
6592*436bf2bcSAndroid Build Coastguard Worker 			print_format[len] = 0;
6593*436bf2bcSAndroid Build Coastguard Worker 
6594*436bf2bcSAndroid Build Coastguard Worker 			parse_arg_add(parse, print_format,
6595*436bf2bcSAndroid Build Coastguard Worker 					PRINT_FMT_ARG_STRING, *arg, len_arg, 0);
6596*436bf2bcSAndroid Build Coastguard Worker 			*arg = (*arg)->next;
6597*436bf2bcSAndroid Build Coastguard Worker 			ret++;
6598*436bf2bcSAndroid Build Coastguard Worker 			return ret;
6599*436bf2bcSAndroid Build Coastguard Worker 		default:
6600*436bf2bcSAndroid Build Coastguard Worker 			snprintf(print_format, 32, ">%c<", *format);
6601*436bf2bcSAndroid Build Coastguard Worker 			parse_arg_add(parse, print_format,
6602*436bf2bcSAndroid Build Coastguard Worker 					PRINT_FMT_STRING, NULL, NULL, 0);
6603*436bf2bcSAndroid Build Coastguard Worker 			ret++;
6604*436bf2bcSAndroid Build Coastguard Worker 			return ret;
6605*436bf2bcSAndroid Build Coastguard Worker 		}
6606*436bf2bcSAndroid Build Coastguard Worker 		ret++;
6607*436bf2bcSAndroid Build Coastguard Worker 	}
6608*436bf2bcSAndroid Build Coastguard Worker 
6609*436bf2bcSAndroid Build Coastguard Worker out_failed:
6610*436bf2bcSAndroid Build Coastguard Worker 	return ret;
6611*436bf2bcSAndroid Build Coastguard Worker 
6612*436bf2bcSAndroid Build Coastguard Worker }
6613*436bf2bcSAndroid Build Coastguard Worker 
parse_arg_string(struct tep_print_parse ** parse,const char * format)6614*436bf2bcSAndroid Build Coastguard Worker static int parse_arg_string(struct tep_print_parse **parse, const char *format)
6615*436bf2bcSAndroid Build Coastguard Worker {
6616*436bf2bcSAndroid Build Coastguard Worker 	struct trace_seq s;
6617*436bf2bcSAndroid Build Coastguard Worker 	int ret = 0;
6618*436bf2bcSAndroid Build Coastguard Worker 
6619*436bf2bcSAndroid Build Coastguard Worker 	trace_seq_init(&s);
6620*436bf2bcSAndroid Build Coastguard Worker 	for (; *format; format++) {
6621*436bf2bcSAndroid Build Coastguard Worker 		if (*format == '\\') {
6622*436bf2bcSAndroid Build Coastguard Worker 			format++;
6623*436bf2bcSAndroid Build Coastguard Worker 			ret++;
6624*436bf2bcSAndroid Build Coastguard Worker 			switch (*format) {
6625*436bf2bcSAndroid Build Coastguard Worker 			case 'n':
6626*436bf2bcSAndroid Build Coastguard Worker 				trace_seq_putc(&s, '\n');
6627*436bf2bcSAndroid Build Coastguard Worker 				break;
6628*436bf2bcSAndroid Build Coastguard Worker 			case 't':
6629*436bf2bcSAndroid Build Coastguard Worker 				trace_seq_putc(&s, '\t');
6630*436bf2bcSAndroid Build Coastguard Worker 				break;
6631*436bf2bcSAndroid Build Coastguard Worker 			case 'r':
6632*436bf2bcSAndroid Build Coastguard Worker 				trace_seq_putc(&s, '\r');
6633*436bf2bcSAndroid Build Coastguard Worker 				break;
6634*436bf2bcSAndroid Build Coastguard Worker 			case '\\':
6635*436bf2bcSAndroid Build Coastguard Worker 				trace_seq_putc(&s, '\\');
6636*436bf2bcSAndroid Build Coastguard Worker 				break;
6637*436bf2bcSAndroid Build Coastguard Worker 			default:
6638*436bf2bcSAndroid Build Coastguard Worker 				trace_seq_putc(&s, *format);
6639*436bf2bcSAndroid Build Coastguard Worker 				break;
6640*436bf2bcSAndroid Build Coastguard Worker 			}
6641*436bf2bcSAndroid Build Coastguard Worker 		} else if (*format == '%') {
6642*436bf2bcSAndroid Build Coastguard Worker 			if (*(format + 1) == '%') {
6643*436bf2bcSAndroid Build Coastguard Worker 				trace_seq_putc(&s, '%');
6644*436bf2bcSAndroid Build Coastguard Worker 				format++;
6645*436bf2bcSAndroid Build Coastguard Worker 				ret++;
6646*436bf2bcSAndroid Build Coastguard Worker 			} else
6647*436bf2bcSAndroid Build Coastguard Worker 				break;
6648*436bf2bcSAndroid Build Coastguard Worker 		} else
6649*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_putc(&s, *format);
6650*436bf2bcSAndroid Build Coastguard Worker 
6651*436bf2bcSAndroid Build Coastguard Worker 		ret++;
6652*436bf2bcSAndroid Build Coastguard Worker 	}
6653*436bf2bcSAndroid Build Coastguard Worker 	trace_seq_terminate(&s);
6654*436bf2bcSAndroid Build Coastguard Worker 	parse_arg_add(parse, s.buffer, PRINT_FMT_STRING, NULL, NULL, 0);
6655*436bf2bcSAndroid Build Coastguard Worker 	trace_seq_destroy(&s);
6656*436bf2bcSAndroid Build Coastguard Worker 
6657*436bf2bcSAndroid Build Coastguard Worker 	return ret;
6658*436bf2bcSAndroid Build Coastguard Worker }
6659*436bf2bcSAndroid Build Coastguard Worker 
6660*436bf2bcSAndroid Build Coastguard Worker static struct tep_print_parse *
parse_args(struct tep_event * event,const char * format,struct tep_print_arg * arg)6661*436bf2bcSAndroid Build Coastguard Worker parse_args(struct tep_event *event, const char *format, struct tep_print_arg *arg)
6662*436bf2bcSAndroid Build Coastguard Worker {
6663*436bf2bcSAndroid Build Coastguard Worker 	struct tep_print_parse *parse_ret = NULL;
6664*436bf2bcSAndroid Build Coastguard Worker 	struct tep_print_parse **parse = NULL;
6665*436bf2bcSAndroid Build Coastguard Worker 	int ret;
6666*436bf2bcSAndroid Build Coastguard Worker 	int len;
6667*436bf2bcSAndroid Build Coastguard Worker 
6668*436bf2bcSAndroid Build Coastguard Worker 	len = strlen(format);
6669*436bf2bcSAndroid Build Coastguard Worker 	while (*format) {
6670*436bf2bcSAndroid Build Coastguard Worker 		if (!parse_ret)
6671*436bf2bcSAndroid Build Coastguard Worker 			parse = &parse_ret;
6672*436bf2bcSAndroid Build Coastguard Worker 		if (*format == '%' && *(format + 1) != '%')
6673*436bf2bcSAndroid Build Coastguard Worker 			ret = parse_arg_format(parse, event, format, &arg);
6674*436bf2bcSAndroid Build Coastguard Worker 		else
6675*436bf2bcSAndroid Build Coastguard Worker 			ret = parse_arg_string(parse, format);
6676*436bf2bcSAndroid Build Coastguard Worker 		if (*parse)
6677*436bf2bcSAndroid Build Coastguard Worker 			parse = &((*parse)->next);
6678*436bf2bcSAndroid Build Coastguard Worker 
6679*436bf2bcSAndroid Build Coastguard Worker 		len -= ret;
6680*436bf2bcSAndroid Build Coastguard Worker 		if (len > 0)
6681*436bf2bcSAndroid Build Coastguard Worker 			format += ret;
6682*436bf2bcSAndroid Build Coastguard Worker 		else
6683*436bf2bcSAndroid Build Coastguard Worker 			break;
6684*436bf2bcSAndroid Build Coastguard Worker 	}
6685*436bf2bcSAndroid Build Coastguard Worker 	return parse_ret;
6686*436bf2bcSAndroid Build Coastguard Worker }
6687*436bf2bcSAndroid Build Coastguard Worker 
print_parse_data(struct tep_print_parse * parse,struct trace_seq * s,void * data,int size,struct tep_event * event,bool raw)6688*436bf2bcSAndroid Build Coastguard Worker static int print_parse_data(struct tep_print_parse *parse, struct trace_seq *s,
6689*436bf2bcSAndroid Build Coastguard Worker 			    void *data, int size, struct tep_event *event, bool raw)
6690*436bf2bcSAndroid Build Coastguard Worker {
6691*436bf2bcSAndroid Build Coastguard Worker 	int len_arg;
6692*436bf2bcSAndroid Build Coastguard Worker 
6693*436bf2bcSAndroid Build Coastguard Worker 	if (parse->len_as_arg)
6694*436bf2bcSAndroid Build Coastguard Worker 		len_arg = eval_num_arg(data, size, event, parse->len_as_arg);
6695*436bf2bcSAndroid Build Coastguard Worker 
6696*436bf2bcSAndroid Build Coastguard Worker 	switch (parse->type) {
6697*436bf2bcSAndroid Build Coastguard Worker 	case PRINT_FMT_ARG_DIGIT:
6698*436bf2bcSAndroid Build Coastguard Worker 		print_arg_number(s, parse->format,
6699*436bf2bcSAndroid Build Coastguard Worker 				 parse->len_as_arg ? len_arg : -1, data,
6700*436bf2bcSAndroid Build Coastguard Worker 				 size, parse->ls, event, parse->arg);
6701*436bf2bcSAndroid Build Coastguard Worker 		break;
6702*436bf2bcSAndroid Build Coastguard Worker 	case PRINT_FMT_ARG_POINTER:
6703*436bf2bcSAndroid Build Coastguard Worker 		print_arg_pointer(s, parse->format,
6704*436bf2bcSAndroid Build Coastguard Worker 				  parse->len_as_arg ? len_arg : 1,
6705*436bf2bcSAndroid Build Coastguard Worker 				  data, size, event, parse->arg, raw);
6706*436bf2bcSAndroid Build Coastguard Worker 		break;
6707*436bf2bcSAndroid Build Coastguard Worker 	case PRINT_FMT_ARG_STRING:
6708*436bf2bcSAndroid Build Coastguard Worker 		print_arg_string(s, parse->format,
6709*436bf2bcSAndroid Build Coastguard Worker 				 parse->len_as_arg ? len_arg : -1,
6710*436bf2bcSAndroid Build Coastguard Worker 				 data, size, event, parse->arg);
6711*436bf2bcSAndroid Build Coastguard Worker 		break;
6712*436bf2bcSAndroid Build Coastguard Worker 	case PRINT_FMT_STRING:
6713*436bf2bcSAndroid Build Coastguard Worker 	default:
6714*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_printf(s, "%s", parse->format);
6715*436bf2bcSAndroid Build Coastguard Worker 		/* Return 1 on non field. */
6716*436bf2bcSAndroid Build Coastguard Worker 		return 1;
6717*436bf2bcSAndroid Build Coastguard Worker 	}
6718*436bf2bcSAndroid Build Coastguard Worker 	/* Return 0 on field being processed. */
6719*436bf2bcSAndroid Build Coastguard Worker 	return 0;
6720*436bf2bcSAndroid Build Coastguard Worker }
6721*436bf2bcSAndroid Build Coastguard Worker 
print_event_cache(struct tep_print_parse * parse,struct trace_seq * s,void * data,int size,struct tep_event * event)6722*436bf2bcSAndroid Build Coastguard Worker static void print_event_cache(struct tep_print_parse *parse, struct trace_seq *s,
6723*436bf2bcSAndroid Build Coastguard Worker 			      void *data, int size, struct tep_event *event)
6724*436bf2bcSAndroid Build Coastguard Worker {
6725*436bf2bcSAndroid Build Coastguard Worker 	while (parse) {
6726*436bf2bcSAndroid Build Coastguard Worker 		print_parse_data(parse, s, data, size, event, false);
6727*436bf2bcSAndroid Build Coastguard Worker 		parse = parse->next;
6728*436bf2bcSAndroid Build Coastguard Worker 	}
6729*436bf2bcSAndroid Build Coastguard Worker }
6730*436bf2bcSAndroid Build Coastguard Worker 
pretty_print(struct trace_seq * s,void * data,int size,struct tep_event * event)6731*436bf2bcSAndroid Build Coastguard Worker static void pretty_print(struct trace_seq *s, void *data, int size, struct tep_event *event)
6732*436bf2bcSAndroid Build Coastguard Worker {
6733*436bf2bcSAndroid Build Coastguard Worker 	struct tep_print_parse *parse = event->print_fmt.print_cache;
6734*436bf2bcSAndroid Build Coastguard Worker 	struct tep_print_arg *args = NULL;
6735*436bf2bcSAndroid Build Coastguard Worker 	char *bprint_fmt = NULL;
6736*436bf2bcSAndroid Build Coastguard Worker 
6737*436bf2bcSAndroid Build Coastguard Worker 	if (event->flags & TEP_EVENT_FL_FAILED) {
6738*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_printf(s, "[FAILED TO PARSE]");
6739*436bf2bcSAndroid Build Coastguard Worker 		tep_print_fields(s, data, size, event);
6740*436bf2bcSAndroid Build Coastguard Worker 		return;
6741*436bf2bcSAndroid Build Coastguard Worker 	}
6742*436bf2bcSAndroid Build Coastguard Worker 
6743*436bf2bcSAndroid Build Coastguard Worker 	if (event->flags & TEP_EVENT_FL_ISBPRINT) {
6744*436bf2bcSAndroid Build Coastguard Worker 		bprint_fmt = get_bprint_format(data, size, event);
6745*436bf2bcSAndroid Build Coastguard Worker 		args = make_bprint_args(bprint_fmt, data, size, event);
6746*436bf2bcSAndroid Build Coastguard Worker 		parse = parse_args(event, bprint_fmt, args);
6747*436bf2bcSAndroid Build Coastguard Worker 	}
6748*436bf2bcSAndroid Build Coastguard Worker 
6749*436bf2bcSAndroid Build Coastguard Worker 	print_event_cache(parse, s, data, size, event);
6750*436bf2bcSAndroid Build Coastguard Worker 
6751*436bf2bcSAndroid Build Coastguard Worker 	if (event->flags & TEP_EVENT_FL_ISBPRINT) {
6752*436bf2bcSAndroid Build Coastguard Worker 		free_parse_args(parse);
6753*436bf2bcSAndroid Build Coastguard Worker 		free_args(args);
6754*436bf2bcSAndroid Build Coastguard Worker 		free(bprint_fmt);
6755*436bf2bcSAndroid Build Coastguard Worker 	}
6756*436bf2bcSAndroid Build Coastguard Worker }
6757*436bf2bcSAndroid Build Coastguard Worker 
6758*436bf2bcSAndroid Build Coastguard Worker /*
6759*436bf2bcSAndroid Build Coastguard Worker  * This parses out the Latency format (interrupts disabled,
6760*436bf2bcSAndroid Build Coastguard Worker  * need rescheduling, in hard/soft interrupt, preempt count
6761*436bf2bcSAndroid Build Coastguard Worker  * and lock depth) and places it into the trace_seq.
6762*436bf2bcSAndroid Build Coastguard Worker  */
data_latency_format(struct tep_handle * tep,struct trace_seq * s,char * format,struct tep_record * record)6763*436bf2bcSAndroid Build Coastguard Worker static void data_latency_format(struct tep_handle *tep, struct trace_seq *s,
6764*436bf2bcSAndroid Build Coastguard Worker 				char *format, struct tep_record *record)
6765*436bf2bcSAndroid Build Coastguard Worker {
6766*436bf2bcSAndroid Build Coastguard Worker 	static int check_lock_depth = 1;
6767*436bf2bcSAndroid Build Coastguard Worker 	static int check_migrate_disable = 1;
6768*436bf2bcSAndroid Build Coastguard Worker 	static int lock_depth_exists;
6769*436bf2bcSAndroid Build Coastguard Worker 	static int migrate_disable_exists;
6770*436bf2bcSAndroid Build Coastguard Worker 	unsigned int lat_flags;
6771*436bf2bcSAndroid Build Coastguard Worker 	struct trace_seq sq;
6772*436bf2bcSAndroid Build Coastguard Worker 	unsigned int pc;
6773*436bf2bcSAndroid Build Coastguard Worker 	int lock_depth = 0;
6774*436bf2bcSAndroid Build Coastguard Worker 	int migrate_disable = 0;
6775*436bf2bcSAndroid Build Coastguard Worker 	int hardirq;
6776*436bf2bcSAndroid Build Coastguard Worker 	int softirq;
6777*436bf2bcSAndroid Build Coastguard Worker 	void *data = record->data;
6778*436bf2bcSAndroid Build Coastguard Worker 
6779*436bf2bcSAndroid Build Coastguard Worker 	trace_seq_init(&sq);
6780*436bf2bcSAndroid Build Coastguard Worker 	lat_flags = parse_common_flags(tep, data);
6781*436bf2bcSAndroid Build Coastguard Worker 	pc = parse_common_pc(tep, data);
6782*436bf2bcSAndroid Build Coastguard Worker 	/* lock_depth may not always exist */
6783*436bf2bcSAndroid Build Coastguard Worker 	if (lock_depth_exists)
6784*436bf2bcSAndroid Build Coastguard Worker 		lock_depth = parse_common_lock_depth(tep, data);
6785*436bf2bcSAndroid Build Coastguard Worker 	else if (check_lock_depth) {
6786*436bf2bcSAndroid Build Coastguard Worker 		lock_depth = parse_common_lock_depth(tep, data);
6787*436bf2bcSAndroid Build Coastguard Worker 		if (lock_depth < 0)
6788*436bf2bcSAndroid Build Coastguard Worker 			check_lock_depth = 0;
6789*436bf2bcSAndroid Build Coastguard Worker 		else
6790*436bf2bcSAndroid Build Coastguard Worker 			lock_depth_exists = 1;
6791*436bf2bcSAndroid Build Coastguard Worker 	}
6792*436bf2bcSAndroid Build Coastguard Worker 
6793*436bf2bcSAndroid Build Coastguard Worker 	/* migrate_disable may not always exist */
6794*436bf2bcSAndroid Build Coastguard Worker 	if (migrate_disable_exists)
6795*436bf2bcSAndroid Build Coastguard Worker 		migrate_disable = parse_common_migrate_disable(tep, data);
6796*436bf2bcSAndroid Build Coastguard Worker 	else if (check_migrate_disable) {
6797*436bf2bcSAndroid Build Coastguard Worker 		migrate_disable = parse_common_migrate_disable(tep, data);
6798*436bf2bcSAndroid Build Coastguard Worker 		if (migrate_disable < 0)
6799*436bf2bcSAndroid Build Coastguard Worker 			check_migrate_disable = 0;
6800*436bf2bcSAndroid Build Coastguard Worker 		else
6801*436bf2bcSAndroid Build Coastguard Worker 			migrate_disable_exists = 1;
6802*436bf2bcSAndroid Build Coastguard Worker 	}
6803*436bf2bcSAndroid Build Coastguard Worker 
6804*436bf2bcSAndroid Build Coastguard Worker 	hardirq = lat_flags & TRACE_FLAG_HARDIRQ;
6805*436bf2bcSAndroid Build Coastguard Worker 	softirq = lat_flags & TRACE_FLAG_SOFTIRQ;
6806*436bf2bcSAndroid Build Coastguard Worker 
6807*436bf2bcSAndroid Build Coastguard Worker 	trace_seq_printf(&sq, "%c%c%c",
6808*436bf2bcSAndroid Build Coastguard Worker 	       (lat_flags & TRACE_FLAG_IRQS_OFF) ? 'd' :
6809*436bf2bcSAndroid Build Coastguard Worker 	       (lat_flags & TRACE_FLAG_IRQS_NOSUPPORT) ?
6810*436bf2bcSAndroid Build Coastguard Worker 	       'X' : '.',
6811*436bf2bcSAndroid Build Coastguard Worker 	       (lat_flags & TRACE_FLAG_NEED_RESCHED) ?
6812*436bf2bcSAndroid Build Coastguard Worker 	       'N' : '.',
6813*436bf2bcSAndroid Build Coastguard Worker 	       (hardirq && softirq) ? 'H' :
6814*436bf2bcSAndroid Build Coastguard Worker 	       hardirq ? 'h' : softirq ? 's' : '.');
6815*436bf2bcSAndroid Build Coastguard Worker 
6816*436bf2bcSAndroid Build Coastguard Worker 	if (pc & 0xf)
6817*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_printf(&sq, "%x", pc & 0xf);
6818*436bf2bcSAndroid Build Coastguard Worker 	else
6819*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_printf(&sq, ".");
6820*436bf2bcSAndroid Build Coastguard Worker 
6821*436bf2bcSAndroid Build Coastguard Worker 	if (pc & 0xf0)
6822*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_printf(&sq, "%x", pc >> 4);
6823*436bf2bcSAndroid Build Coastguard Worker 	else
6824*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_printf(&sq, ".");
6825*436bf2bcSAndroid Build Coastguard Worker 
6826*436bf2bcSAndroid Build Coastguard Worker 	if (migrate_disable_exists) {
6827*436bf2bcSAndroid Build Coastguard Worker 		if (migrate_disable < 0)
6828*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_printf(&sq, ".");
6829*436bf2bcSAndroid Build Coastguard Worker 		else
6830*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_printf(&sq, "%d", migrate_disable);
6831*436bf2bcSAndroid Build Coastguard Worker 	}
6832*436bf2bcSAndroid Build Coastguard Worker 
6833*436bf2bcSAndroid Build Coastguard Worker 	if (lock_depth_exists) {
6834*436bf2bcSAndroid Build Coastguard Worker 		if (lock_depth < 0)
6835*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_printf(&sq, ".");
6836*436bf2bcSAndroid Build Coastguard Worker 		else
6837*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_printf(&sq, "%d", lock_depth);
6838*436bf2bcSAndroid Build Coastguard Worker 	}
6839*436bf2bcSAndroid Build Coastguard Worker 
6840*436bf2bcSAndroid Build Coastguard Worker 	if (sq.state == TRACE_SEQ__MEM_ALLOC_FAILED) {
6841*436bf2bcSAndroid Build Coastguard Worker 		s->state = TRACE_SEQ__MEM_ALLOC_FAILED;
6842*436bf2bcSAndroid Build Coastguard Worker 		return;
6843*436bf2bcSAndroid Build Coastguard Worker 	}
6844*436bf2bcSAndroid Build Coastguard Worker 
6845*436bf2bcSAndroid Build Coastguard Worker 	trace_seq_terminate(&sq);
6846*436bf2bcSAndroid Build Coastguard Worker 	trace_seq_puts(s, sq.buffer);
6847*436bf2bcSAndroid Build Coastguard Worker 	trace_seq_destroy(&sq);
6848*436bf2bcSAndroid Build Coastguard Worker 	trace_seq_terminate(s);
6849*436bf2bcSAndroid Build Coastguard Worker }
6850*436bf2bcSAndroid Build Coastguard Worker 
6851*436bf2bcSAndroid Build Coastguard Worker /**
6852*436bf2bcSAndroid Build Coastguard Worker  * tep_data_type - parse out the given event type
6853*436bf2bcSAndroid Build Coastguard Worker  * @tep: a handle to the trace event parser context
6854*436bf2bcSAndroid Build Coastguard Worker  * @rec: the record to read from
6855*436bf2bcSAndroid Build Coastguard Worker  *
6856*436bf2bcSAndroid Build Coastguard Worker  * This returns the event id from the @rec.
6857*436bf2bcSAndroid Build Coastguard Worker  */
tep_data_type(struct tep_handle * tep,struct tep_record * rec)6858*436bf2bcSAndroid Build Coastguard Worker int tep_data_type(struct tep_handle *tep, struct tep_record *rec)
6859*436bf2bcSAndroid Build Coastguard Worker {
6860*436bf2bcSAndroid Build Coastguard Worker 	return trace_parse_common_type(tep, rec->data);
6861*436bf2bcSAndroid Build Coastguard Worker }
6862*436bf2bcSAndroid Build Coastguard Worker 
6863*436bf2bcSAndroid Build Coastguard Worker /**
6864*436bf2bcSAndroid Build Coastguard Worker  * tep_data_pid - parse the PID from record
6865*436bf2bcSAndroid Build Coastguard Worker  * @tep: a handle to the trace event parser context
6866*436bf2bcSAndroid Build Coastguard Worker  * @rec: the record to parse
6867*436bf2bcSAndroid Build Coastguard Worker  *
6868*436bf2bcSAndroid Build Coastguard Worker  * This returns the PID from a record.
6869*436bf2bcSAndroid Build Coastguard Worker  */
tep_data_pid(struct tep_handle * tep,struct tep_record * rec)6870*436bf2bcSAndroid Build Coastguard Worker int tep_data_pid(struct tep_handle *tep, struct tep_record *rec)
6871*436bf2bcSAndroid Build Coastguard Worker {
6872*436bf2bcSAndroid Build Coastguard Worker 	return parse_common_pid(tep, rec->data);
6873*436bf2bcSAndroid Build Coastguard Worker }
6874*436bf2bcSAndroid Build Coastguard Worker 
6875*436bf2bcSAndroid Build Coastguard Worker /**
6876*436bf2bcSAndroid Build Coastguard Worker  * tep_data_preempt_count - parse the preempt count from the record
6877*436bf2bcSAndroid Build Coastguard Worker  * @tep: a handle to the trace event parser context
6878*436bf2bcSAndroid Build Coastguard Worker  * @rec: the record to parse
6879*436bf2bcSAndroid Build Coastguard Worker  *
6880*436bf2bcSAndroid Build Coastguard Worker  * This returns the preempt count from a record.
6881*436bf2bcSAndroid Build Coastguard Worker  */
tep_data_preempt_count(struct tep_handle * tep,struct tep_record * rec)6882*436bf2bcSAndroid Build Coastguard Worker int tep_data_preempt_count(struct tep_handle *tep, struct tep_record *rec)
6883*436bf2bcSAndroid Build Coastguard Worker {
6884*436bf2bcSAndroid Build Coastguard Worker 	return parse_common_pc(tep, rec->data);
6885*436bf2bcSAndroid Build Coastguard Worker }
6886*436bf2bcSAndroid Build Coastguard Worker 
6887*436bf2bcSAndroid Build Coastguard Worker /**
6888*436bf2bcSAndroid Build Coastguard Worker  * tep_data_flags - parse the latency flags from the record
6889*436bf2bcSAndroid Build Coastguard Worker  * @tep: a handle to the trace event parser context
6890*436bf2bcSAndroid Build Coastguard Worker  * @rec: the record to parse
6891*436bf2bcSAndroid Build Coastguard Worker  *
6892*436bf2bcSAndroid Build Coastguard Worker  * This returns the latency flags from a record.
6893*436bf2bcSAndroid Build Coastguard Worker  *
6894*436bf2bcSAndroid Build Coastguard Worker  *  Use trace_flag_type enum for the flags (see event-parse.h).
6895*436bf2bcSAndroid Build Coastguard Worker  */
tep_data_flags(struct tep_handle * tep,struct tep_record * rec)6896*436bf2bcSAndroid Build Coastguard Worker int tep_data_flags(struct tep_handle *tep, struct tep_record *rec)
6897*436bf2bcSAndroid Build Coastguard Worker {
6898*436bf2bcSAndroid Build Coastguard Worker 	return parse_common_flags(tep, rec->data);
6899*436bf2bcSAndroid Build Coastguard Worker }
6900*436bf2bcSAndroid Build Coastguard Worker 
6901*436bf2bcSAndroid Build Coastguard Worker /**
6902*436bf2bcSAndroid Build Coastguard Worker  * tep_data_comm_from_pid - return the command line from PID
6903*436bf2bcSAndroid Build Coastguard Worker  * @tep: a handle to the trace event parser context
6904*436bf2bcSAndroid Build Coastguard Worker  * @pid: the PID of the task to search for
6905*436bf2bcSAndroid Build Coastguard Worker  *
6906*436bf2bcSAndroid Build Coastguard Worker  * This returns a pointer to the command line that has the given
6907*436bf2bcSAndroid Build Coastguard Worker  * @pid.
6908*436bf2bcSAndroid Build Coastguard Worker  */
tep_data_comm_from_pid(struct tep_handle * tep,int pid)6909*436bf2bcSAndroid Build Coastguard Worker const char *tep_data_comm_from_pid(struct tep_handle *tep, int pid)
6910*436bf2bcSAndroid Build Coastguard Worker {
6911*436bf2bcSAndroid Build Coastguard Worker 	const char *comm;
6912*436bf2bcSAndroid Build Coastguard Worker 
6913*436bf2bcSAndroid Build Coastguard Worker 	comm = find_cmdline(tep, pid);
6914*436bf2bcSAndroid Build Coastguard Worker 	return comm;
6915*436bf2bcSAndroid Build Coastguard Worker }
6916*436bf2bcSAndroid Build Coastguard Worker 
6917*436bf2bcSAndroid Build Coastguard Worker /**
6918*436bf2bcSAndroid Build Coastguard Worker  * tep_record_is_event - return true if the given record is the given event
6919*436bf2bcSAndroid Build Coastguard Worker  * @record: The record to see is the @event
6920*436bf2bcSAndroid Build Coastguard Worker  * @event: The event to test against @record
6921*436bf2bcSAndroid Build Coastguard Worker  *
6922*436bf2bcSAndroid Build Coastguard Worker  * Returns true if the record is of the given event, false otherwise
6923*436bf2bcSAndroid Build Coastguard Worker  */
tep_record_is_event(struct tep_record * record,struct tep_event * event)6924*436bf2bcSAndroid Build Coastguard Worker bool tep_record_is_event(struct tep_record *record, struct tep_event *event)
6925*436bf2bcSAndroid Build Coastguard Worker {
6926*436bf2bcSAndroid Build Coastguard Worker 	int type;
6927*436bf2bcSAndroid Build Coastguard Worker 
6928*436bf2bcSAndroid Build Coastguard Worker 	type = tep_data_type(event->tep, record);
6929*436bf2bcSAndroid Build Coastguard Worker 	return event->id == type;
6930*436bf2bcSAndroid Build Coastguard Worker }
6931*436bf2bcSAndroid Build Coastguard Worker 
6932*436bf2bcSAndroid Build Coastguard Worker static struct tep_cmdline *
pid_from_cmdlist(struct tep_handle * tep,const char * comm,struct tep_cmdline * next)6933*436bf2bcSAndroid Build Coastguard Worker pid_from_cmdlist(struct tep_handle *tep, const char *comm, struct tep_cmdline *next)
6934*436bf2bcSAndroid Build Coastguard Worker {
6935*436bf2bcSAndroid Build Coastguard Worker 	struct cmdline_list *cmdlist = (struct cmdline_list *)next;
6936*436bf2bcSAndroid Build Coastguard Worker 
6937*436bf2bcSAndroid Build Coastguard Worker 	if (cmdlist)
6938*436bf2bcSAndroid Build Coastguard Worker 		cmdlist = cmdlist->next;
6939*436bf2bcSAndroid Build Coastguard Worker 	else
6940*436bf2bcSAndroid Build Coastguard Worker 		cmdlist = tep->cmdlist;
6941*436bf2bcSAndroid Build Coastguard Worker 
6942*436bf2bcSAndroid Build Coastguard Worker 	while (cmdlist && strcmp(cmdlist->comm, comm) != 0)
6943*436bf2bcSAndroid Build Coastguard Worker 		cmdlist = cmdlist->next;
6944*436bf2bcSAndroid Build Coastguard Worker 
6945*436bf2bcSAndroid Build Coastguard Worker 	return (struct tep_cmdline *)cmdlist;
6946*436bf2bcSAndroid Build Coastguard Worker }
6947*436bf2bcSAndroid Build Coastguard Worker 
6948*436bf2bcSAndroid Build Coastguard Worker /**
6949*436bf2bcSAndroid Build Coastguard Worker  * tep_data_pid_from_comm - return the pid from a given comm
6950*436bf2bcSAndroid Build Coastguard Worker  * @tep: a handle to the trace event parser context
6951*436bf2bcSAndroid Build Coastguard Worker  * @comm: the cmdline to find the pid from
6952*436bf2bcSAndroid Build Coastguard Worker  * @next: the cmdline structure to find the next comm
6953*436bf2bcSAndroid Build Coastguard Worker  *
6954*436bf2bcSAndroid Build Coastguard Worker  * This returns the cmdline structure that holds a pid for a given
6955*436bf2bcSAndroid Build Coastguard Worker  * comm, or NULL if none found. As there may be more than one pid for
6956*436bf2bcSAndroid Build Coastguard Worker  * a given comm, the result of this call can be passed back into
6957*436bf2bcSAndroid Build Coastguard Worker  * a recurring call in the @next parameter, and then it will find the
6958*436bf2bcSAndroid Build Coastguard Worker  * next pid.
6959*436bf2bcSAndroid Build Coastguard Worker  * Also, it does a linear search, so it may be slow.
6960*436bf2bcSAndroid Build Coastguard Worker  */
tep_data_pid_from_comm(struct tep_handle * tep,const char * comm,struct tep_cmdline * next)6961*436bf2bcSAndroid Build Coastguard Worker struct tep_cmdline *tep_data_pid_from_comm(struct tep_handle *tep, const char *comm,
6962*436bf2bcSAndroid Build Coastguard Worker 					   struct tep_cmdline *next)
6963*436bf2bcSAndroid Build Coastguard Worker {
6964*436bf2bcSAndroid Build Coastguard Worker 	struct tep_cmdline *cmdline;
6965*436bf2bcSAndroid Build Coastguard Worker 
6966*436bf2bcSAndroid Build Coastguard Worker 	/*
6967*436bf2bcSAndroid Build Coastguard Worker 	 * If the cmdlines have not been converted yet, then use
6968*436bf2bcSAndroid Build Coastguard Worker 	 * the list.
6969*436bf2bcSAndroid Build Coastguard Worker 	 */
6970*436bf2bcSAndroid Build Coastguard Worker 	if (!tep->cmdlines)
6971*436bf2bcSAndroid Build Coastguard Worker 		return pid_from_cmdlist(tep, comm, next);
6972*436bf2bcSAndroid Build Coastguard Worker 
6973*436bf2bcSAndroid Build Coastguard Worker 	if (next) {
6974*436bf2bcSAndroid Build Coastguard Worker 		/*
6975*436bf2bcSAndroid Build Coastguard Worker 		 * The next pointer could have been still from
6976*436bf2bcSAndroid Build Coastguard Worker 		 * a previous call before cmdlines were created
6977*436bf2bcSAndroid Build Coastguard Worker 		 */
6978*436bf2bcSAndroid Build Coastguard Worker 		if (next < tep->cmdlines ||
6979*436bf2bcSAndroid Build Coastguard Worker 		    next >= tep->cmdlines + tep->cmdline_count)
6980*436bf2bcSAndroid Build Coastguard Worker 			next = NULL;
6981*436bf2bcSAndroid Build Coastguard Worker 		else
6982*436bf2bcSAndroid Build Coastguard Worker 			cmdline  = next++;
6983*436bf2bcSAndroid Build Coastguard Worker 	}
6984*436bf2bcSAndroid Build Coastguard Worker 
6985*436bf2bcSAndroid Build Coastguard Worker 	if (!next)
6986*436bf2bcSAndroid Build Coastguard Worker 		cmdline = tep->cmdlines;
6987*436bf2bcSAndroid Build Coastguard Worker 
6988*436bf2bcSAndroid Build Coastguard Worker 	while (cmdline < tep->cmdlines + tep->cmdline_count) {
6989*436bf2bcSAndroid Build Coastguard Worker 		if (strcmp(cmdline->comm, comm) == 0)
6990*436bf2bcSAndroid Build Coastguard Worker 			return cmdline;
6991*436bf2bcSAndroid Build Coastguard Worker 		cmdline++;
6992*436bf2bcSAndroid Build Coastguard Worker 	}
6993*436bf2bcSAndroid Build Coastguard Worker 	return NULL;
6994*436bf2bcSAndroid Build Coastguard Worker }
6995*436bf2bcSAndroid Build Coastguard Worker 
6996*436bf2bcSAndroid Build Coastguard Worker /**
6997*436bf2bcSAndroid Build Coastguard Worker  * tep_cmdline_pid - return the pid associated to a given cmdline
6998*436bf2bcSAndroid Build Coastguard Worker  * @tep: a handle to the trace event parser context
6999*436bf2bcSAndroid Build Coastguard Worker  * @cmdline: The cmdline structure to get the pid from
7000*436bf2bcSAndroid Build Coastguard Worker  *
7001*436bf2bcSAndroid Build Coastguard Worker  * Returns the pid for a give cmdline. If @cmdline is NULL, then
7002*436bf2bcSAndroid Build Coastguard Worker  * -1 is returned.
7003*436bf2bcSAndroid Build Coastguard Worker  */
tep_cmdline_pid(struct tep_handle * tep,struct tep_cmdline * cmdline)7004*436bf2bcSAndroid Build Coastguard Worker int tep_cmdline_pid(struct tep_handle *tep, struct tep_cmdline *cmdline)
7005*436bf2bcSAndroid Build Coastguard Worker {
7006*436bf2bcSAndroid Build Coastguard Worker 	struct cmdline_list *cmdlist = (struct cmdline_list *)cmdline;
7007*436bf2bcSAndroid Build Coastguard Worker 
7008*436bf2bcSAndroid Build Coastguard Worker 	if (!cmdline)
7009*436bf2bcSAndroid Build Coastguard Worker 		return -1;
7010*436bf2bcSAndroid Build Coastguard Worker 
7011*436bf2bcSAndroid Build Coastguard Worker 	/*
7012*436bf2bcSAndroid Build Coastguard Worker 	 * If cmdlines have not been created yet, or cmdline is
7013*436bf2bcSAndroid Build Coastguard Worker 	 * not part of the array, then treat it as a cmdlist instead.
7014*436bf2bcSAndroid Build Coastguard Worker 	 */
7015*436bf2bcSAndroid Build Coastguard Worker 	if (!tep->cmdlines ||
7016*436bf2bcSAndroid Build Coastguard Worker 	    cmdline < tep->cmdlines ||
7017*436bf2bcSAndroid Build Coastguard Worker 	    cmdline >= tep->cmdlines + tep->cmdline_count)
7018*436bf2bcSAndroid Build Coastguard Worker 		return cmdlist->pid;
7019*436bf2bcSAndroid Build Coastguard Worker 
7020*436bf2bcSAndroid Build Coastguard Worker 	return cmdline->pid;
7021*436bf2bcSAndroid Build Coastguard Worker }
7022*436bf2bcSAndroid Build Coastguard Worker 
7023*436bf2bcSAndroid Build Coastguard Worker /*
7024*436bf2bcSAndroid Build Coastguard Worker  * This parses the raw @data using the given @event information and
7025*436bf2bcSAndroid Build Coastguard Worker  * writes the print format into the trace_seq.
7026*436bf2bcSAndroid Build Coastguard Worker  */
print_event_info(struct trace_seq * s,char * format,bool raw,struct tep_event * event,struct tep_record * record)7027*436bf2bcSAndroid Build Coastguard Worker static void print_event_info(struct trace_seq *s, char *format, bool raw,
7028*436bf2bcSAndroid Build Coastguard Worker 			     struct tep_event *event, struct tep_record *record)
7029*436bf2bcSAndroid Build Coastguard Worker {
7030*436bf2bcSAndroid Build Coastguard Worker 	int print_pretty = 1;
7031*436bf2bcSAndroid Build Coastguard Worker 
7032*436bf2bcSAndroid Build Coastguard Worker 	if (raw || (event->flags & TEP_EVENT_FL_PRINTRAW))
7033*436bf2bcSAndroid Build Coastguard Worker 		print_selected_fields(s, record->data, record->size, event, 0, true);
7034*436bf2bcSAndroid Build Coastguard Worker 	else {
7035*436bf2bcSAndroid Build Coastguard Worker 
7036*436bf2bcSAndroid Build Coastguard Worker 		if (event->handler && !(event->flags & TEP_EVENT_FL_NOHANDLE))
7037*436bf2bcSAndroid Build Coastguard Worker 			print_pretty = event->handler(s, record, event,
7038*436bf2bcSAndroid Build Coastguard Worker 						      event->context);
7039*436bf2bcSAndroid Build Coastguard Worker 
7040*436bf2bcSAndroid Build Coastguard Worker 		if (print_pretty)
7041*436bf2bcSAndroid Build Coastguard Worker 			pretty_print(s, record->data, record->size, event);
7042*436bf2bcSAndroid Build Coastguard Worker 	}
7043*436bf2bcSAndroid Build Coastguard Worker 
7044*436bf2bcSAndroid Build Coastguard Worker 	trace_seq_terminate(s);
7045*436bf2bcSAndroid Build Coastguard Worker }
7046*436bf2bcSAndroid Build Coastguard Worker 
7047*436bf2bcSAndroid Build Coastguard Worker /**
7048*436bf2bcSAndroid Build Coastguard Worker  * tep_find_event_by_record - return the event from a given record
7049*436bf2bcSAndroid Build Coastguard Worker  * @tep: a handle to the trace event parser context
7050*436bf2bcSAndroid Build Coastguard Worker  * @record: The record to get the event from
7051*436bf2bcSAndroid Build Coastguard Worker  *
7052*436bf2bcSAndroid Build Coastguard Worker  * Returns the associated event for a given record, or NULL if non is
7053*436bf2bcSAndroid Build Coastguard Worker  * is found.
7054*436bf2bcSAndroid Build Coastguard Worker  */
7055*436bf2bcSAndroid Build Coastguard Worker struct tep_event *
tep_find_event_by_record(struct tep_handle * tep,struct tep_record * record)7056*436bf2bcSAndroid Build Coastguard Worker tep_find_event_by_record(struct tep_handle *tep, struct tep_record *record)
7057*436bf2bcSAndroid Build Coastguard Worker {
7058*436bf2bcSAndroid Build Coastguard Worker 	int type;
7059*436bf2bcSAndroid Build Coastguard Worker 
7060*436bf2bcSAndroid Build Coastguard Worker 	if (record->size < 0) {
7061*436bf2bcSAndroid Build Coastguard Worker 		do_warning("ug! negative record size %d", record->size);
7062*436bf2bcSAndroid Build Coastguard Worker 		return NULL;
7063*436bf2bcSAndroid Build Coastguard Worker 	}
7064*436bf2bcSAndroid Build Coastguard Worker 
7065*436bf2bcSAndroid Build Coastguard Worker 	type = trace_parse_common_type(tep, record->data);
7066*436bf2bcSAndroid Build Coastguard Worker 
7067*436bf2bcSAndroid Build Coastguard Worker 	return tep_find_event(tep, type);
7068*436bf2bcSAndroid Build Coastguard Worker }
7069*436bf2bcSAndroid Build Coastguard Worker 
7070*436bf2bcSAndroid Build Coastguard Worker /*
7071*436bf2bcSAndroid Build Coastguard Worker  * Writes the timestamp of the record into @s. Time divisor and precision can be
7072*436bf2bcSAndroid Build Coastguard Worker  * specified as part of printf @format string. Example:
7073*436bf2bcSAndroid Build Coastguard Worker  *	"%3.1000d" - divide the time by 1000 and print the first 3 digits
7074*436bf2bcSAndroid Build Coastguard Worker  *	before the dot. Thus, the timestamp "123456000" will be printed as
7075*436bf2bcSAndroid Build Coastguard Worker  *	"123.456"
7076*436bf2bcSAndroid Build Coastguard Worker  */
print_event_time(struct tep_handle * tep,struct trace_seq * s,char * format,struct tep_event * event,struct tep_record * record)7077*436bf2bcSAndroid Build Coastguard Worker static void print_event_time(struct tep_handle *tep, struct trace_seq *s,
7078*436bf2bcSAndroid Build Coastguard Worker 				 char *format, struct tep_event *event,
7079*436bf2bcSAndroid Build Coastguard Worker 				 struct tep_record *record)
7080*436bf2bcSAndroid Build Coastguard Worker {
7081*436bf2bcSAndroid Build Coastguard Worker 	unsigned long long time;
7082*436bf2bcSAndroid Build Coastguard Worker 	char *divstr;
7083*436bf2bcSAndroid Build Coastguard Worker 	int prec = 0, pr;
7084*436bf2bcSAndroid Build Coastguard Worker 	int div = 0;
7085*436bf2bcSAndroid Build Coastguard Worker 	int p10 = 1;
7086*436bf2bcSAndroid Build Coastguard Worker 
7087*436bf2bcSAndroid Build Coastguard Worker 	if (isdigit(*(format + 1)))
7088*436bf2bcSAndroid Build Coastguard Worker 		prec = atoi(format + 1);
7089*436bf2bcSAndroid Build Coastguard Worker 	divstr = strchr(format, '.');
7090*436bf2bcSAndroid Build Coastguard Worker 	if (divstr && isdigit(*(divstr + 1)))
7091*436bf2bcSAndroid Build Coastguard Worker 		div = atoi(divstr + 1);
7092*436bf2bcSAndroid Build Coastguard Worker 	time = record->ts;
7093*436bf2bcSAndroid Build Coastguard Worker 	if (div) {
7094*436bf2bcSAndroid Build Coastguard Worker 		time += div / 2;
7095*436bf2bcSAndroid Build Coastguard Worker 		time /= div;
7096*436bf2bcSAndroid Build Coastguard Worker 	}
7097*436bf2bcSAndroid Build Coastguard Worker 	pr = prec;
7098*436bf2bcSAndroid Build Coastguard Worker 	while (pr--)
7099*436bf2bcSAndroid Build Coastguard Worker 		p10 *= 10;
7100*436bf2bcSAndroid Build Coastguard Worker 
7101*436bf2bcSAndroid Build Coastguard Worker 	if (p10 > 1)
7102*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_printf(s, "%5llu.%0*llu", time / p10, prec, time % p10);
7103*436bf2bcSAndroid Build Coastguard Worker 	else
7104*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_printf(s, "%12llu", time);
7105*436bf2bcSAndroid Build Coastguard Worker }
7106*436bf2bcSAndroid Build Coastguard Worker 
7107*436bf2bcSAndroid Build Coastguard Worker struct print_event_type {
7108*436bf2bcSAndroid Build Coastguard Worker 	enum {
7109*436bf2bcSAndroid Build Coastguard Worker 		EVENT_TYPE_INT = 1,
7110*436bf2bcSAndroid Build Coastguard Worker 		EVENT_TYPE_STRING,
7111*436bf2bcSAndroid Build Coastguard Worker 		EVENT_TYPE_UNKNOWN,
7112*436bf2bcSAndroid Build Coastguard Worker 	} type;
7113*436bf2bcSAndroid Build Coastguard Worker 	char format[32];
7114*436bf2bcSAndroid Build Coastguard Worker };
7115*436bf2bcSAndroid Build Coastguard Worker 
print_string(struct tep_handle * tep,struct trace_seq * s,struct tep_record * record,struct tep_event * event,const char * arg,struct print_event_type * type)7116*436bf2bcSAndroid Build Coastguard Worker static void print_string(struct tep_handle *tep, struct trace_seq *s,
7117*436bf2bcSAndroid Build Coastguard Worker 			 struct tep_record *record, struct tep_event *event,
7118*436bf2bcSAndroid Build Coastguard Worker 			 const char *arg, struct print_event_type *type)
7119*436bf2bcSAndroid Build Coastguard Worker {
7120*436bf2bcSAndroid Build Coastguard Worker 	const char *comm;
7121*436bf2bcSAndroid Build Coastguard Worker 	int pid;
7122*436bf2bcSAndroid Build Coastguard Worker 
7123*436bf2bcSAndroid Build Coastguard Worker 	if (strncmp(arg, TEP_PRINT_LATENCY, strlen(TEP_PRINT_LATENCY)) == 0) {
7124*436bf2bcSAndroid Build Coastguard Worker 		data_latency_format(tep, s, type->format, record);
7125*436bf2bcSAndroid Build Coastguard Worker 	} else if (strncmp(arg, TEP_PRINT_COMM, strlen(TEP_PRINT_COMM)) == 0) {
7126*436bf2bcSAndroid Build Coastguard Worker 		pid = parse_common_pid(tep, record->data);
7127*436bf2bcSAndroid Build Coastguard Worker 		comm = find_cmdline(tep, pid);
7128*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_printf(s, type->format, comm);
7129*436bf2bcSAndroid Build Coastguard Worker 	} else if (strncmp(arg, TEP_PRINT_INFO_RAW, strlen(TEP_PRINT_INFO_RAW)) == 0) {
7130*436bf2bcSAndroid Build Coastguard Worker 		print_event_info(s, type->format, true, event, record);
7131*436bf2bcSAndroid Build Coastguard Worker 	} else if (strncmp(arg, TEP_PRINT_INFO, strlen(TEP_PRINT_INFO)) == 0) {
7132*436bf2bcSAndroid Build Coastguard Worker 		print_event_info(s, type->format, false, event, record);
7133*436bf2bcSAndroid Build Coastguard Worker 	} else if  (strncmp(arg, TEP_PRINT_NAME, strlen(TEP_PRINT_NAME)) == 0) {
7134*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_printf(s, type->format, event->name);
7135*436bf2bcSAndroid Build Coastguard Worker 	} else {
7136*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_printf(s, "[UNKNOWN TEP TYPE %s]", arg);
7137*436bf2bcSAndroid Build Coastguard Worker 	}
7138*436bf2bcSAndroid Build Coastguard Worker 
7139*436bf2bcSAndroid Build Coastguard Worker }
7140*436bf2bcSAndroid Build Coastguard Worker 
print_int(struct tep_handle * tep,struct trace_seq * s,struct tep_record * record,struct tep_event * event,int arg,struct print_event_type * type)7141*436bf2bcSAndroid Build Coastguard Worker static void print_int(struct tep_handle *tep, struct trace_seq *s,
7142*436bf2bcSAndroid Build Coastguard Worker 		      struct tep_record *record, struct tep_event *event,
7143*436bf2bcSAndroid Build Coastguard Worker 		      int arg, struct print_event_type *type)
7144*436bf2bcSAndroid Build Coastguard Worker {
7145*436bf2bcSAndroid Build Coastguard Worker 	int param;
7146*436bf2bcSAndroid Build Coastguard Worker 
7147*436bf2bcSAndroid Build Coastguard Worker 	switch (arg) {
7148*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_CPU:
7149*436bf2bcSAndroid Build Coastguard Worker 		param = record->cpu;
7150*436bf2bcSAndroid Build Coastguard Worker 		break;
7151*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_PID:
7152*436bf2bcSAndroid Build Coastguard Worker 		param = parse_common_pid(tep, record->data);
7153*436bf2bcSAndroid Build Coastguard Worker 		break;
7154*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_TIME:
7155*436bf2bcSAndroid Build Coastguard Worker 		return print_event_time(tep, s, type->format, event, record);
7156*436bf2bcSAndroid Build Coastguard Worker 	default:
7157*436bf2bcSAndroid Build Coastguard Worker 		return;
7158*436bf2bcSAndroid Build Coastguard Worker 	}
7159*436bf2bcSAndroid Build Coastguard Worker 	trace_seq_printf(s, type->format, param);
7160*436bf2bcSAndroid Build Coastguard Worker }
7161*436bf2bcSAndroid Build Coastguard Worker 
tep_print_event_param_type(char * format,struct print_event_type * type)7162*436bf2bcSAndroid Build Coastguard Worker static int tep_print_event_param_type(char *format,
7163*436bf2bcSAndroid Build Coastguard Worker 				      struct print_event_type *type)
7164*436bf2bcSAndroid Build Coastguard Worker {
7165*436bf2bcSAndroid Build Coastguard Worker 	char *str = format + 1;
7166*436bf2bcSAndroid Build Coastguard Worker 	int i = 1;
7167*436bf2bcSAndroid Build Coastguard Worker 
7168*436bf2bcSAndroid Build Coastguard Worker 	type->type = EVENT_TYPE_UNKNOWN;
7169*436bf2bcSAndroid Build Coastguard Worker 	while (*str) {
7170*436bf2bcSAndroid Build Coastguard Worker 		switch (*str) {
7171*436bf2bcSAndroid Build Coastguard Worker 		case 'd':
7172*436bf2bcSAndroid Build Coastguard Worker 		case 'u':
7173*436bf2bcSAndroid Build Coastguard Worker 		case 'i':
7174*436bf2bcSAndroid Build Coastguard Worker 		case 'x':
7175*436bf2bcSAndroid Build Coastguard Worker 		case 'X':
7176*436bf2bcSAndroid Build Coastguard Worker 		case 'o':
7177*436bf2bcSAndroid Build Coastguard Worker 			type->type = EVENT_TYPE_INT;
7178*436bf2bcSAndroid Build Coastguard Worker 			break;
7179*436bf2bcSAndroid Build Coastguard Worker 		case 's':
7180*436bf2bcSAndroid Build Coastguard Worker 			type->type = EVENT_TYPE_STRING;
7181*436bf2bcSAndroid Build Coastguard Worker 			break;
7182*436bf2bcSAndroid Build Coastguard Worker 		}
7183*436bf2bcSAndroid Build Coastguard Worker 		str++;
7184*436bf2bcSAndroid Build Coastguard Worker 		i++;
7185*436bf2bcSAndroid Build Coastguard Worker 		if (type->type != EVENT_TYPE_UNKNOWN)
7186*436bf2bcSAndroid Build Coastguard Worker 			break;
7187*436bf2bcSAndroid Build Coastguard Worker 	}
7188*436bf2bcSAndroid Build Coastguard Worker 	memset(type->format, 0, 32);
7189*436bf2bcSAndroid Build Coastguard Worker 	memcpy(type->format, format, i < 32 ? i : 31);
7190*436bf2bcSAndroid Build Coastguard Worker 	return i;
7191*436bf2bcSAndroid Build Coastguard Worker }
7192*436bf2bcSAndroid Build Coastguard Worker 
7193*436bf2bcSAndroid Build Coastguard Worker /**
7194*436bf2bcSAndroid Build Coastguard Worker  * tep_print_event - Write various event information
7195*436bf2bcSAndroid Build Coastguard Worker  * @tep: a handle to the trace event parser context
7196*436bf2bcSAndroid Build Coastguard Worker  * @s: the trace_seq to write to
7197*436bf2bcSAndroid Build Coastguard Worker  * @record: The record to get the event from
7198*436bf2bcSAndroid Build Coastguard Worker  * @format: a printf format string. Supported event fileds:
7199*436bf2bcSAndroid Build Coastguard Worker  *	TEP_PRINT_PID, "%d" - event PID
7200*436bf2bcSAndroid Build Coastguard Worker  *	TEP_PRINT_CPU, "%d" - event CPU
7201*436bf2bcSAndroid Build Coastguard Worker  *	TEP_PRINT_COMM, "%s" - event command string
7202*436bf2bcSAndroid Build Coastguard Worker  *	TEP_PRINT_NAME, "%s" - event name
7203*436bf2bcSAndroid Build Coastguard Worker  *	TEP_PRINT_LATENCY, "%s" - event latency
7204*436bf2bcSAndroid Build Coastguard Worker  *	TEP_PRINT_TIME, %d - event time stamp. A divisor and precision
7205*436bf2bcSAndroid Build Coastguard Worker  *			can be specified as part of this format string:
7206*436bf2bcSAndroid Build Coastguard Worker  *			"%precision.divisord". Example:
7207*436bf2bcSAndroid Build Coastguard Worker  *			"%3.1000d" - divide the time by 1000 and print the first
7208*436bf2bcSAndroid Build Coastguard Worker  *			3 digits before the dot. Thus, the time stamp
7209*436bf2bcSAndroid Build Coastguard Worker  *			"123456000" will be printed as "123.456"
7210*436bf2bcSAndroid Build Coastguard Worker  *	TEP_PRINT_INFO, "%s" - event information. If any width is specified in
7211*436bf2bcSAndroid Build Coastguard Worker  *			the format string, the event information will be printed
7212*436bf2bcSAndroid Build Coastguard Worker  *			in raw format.
7213*436bf2bcSAndroid Build Coastguard Worker  * Writes the specified event information into @s.
7214*436bf2bcSAndroid Build Coastguard Worker  */
tep_print_event(struct tep_handle * tep,struct trace_seq * s,struct tep_record * record,const char * fmt,...)7215*436bf2bcSAndroid Build Coastguard Worker void tep_print_event(struct tep_handle *tep, struct trace_seq *s,
7216*436bf2bcSAndroid Build Coastguard Worker 		     struct tep_record *record, const char *fmt, ...)
7217*436bf2bcSAndroid Build Coastguard Worker {
7218*436bf2bcSAndroid Build Coastguard Worker 	struct print_event_type type;
7219*436bf2bcSAndroid Build Coastguard Worker 	struct tep_event *event;
7220*436bf2bcSAndroid Build Coastguard Worker 	char *current;
7221*436bf2bcSAndroid Build Coastguard Worker 	char *format;
7222*436bf2bcSAndroid Build Coastguard Worker 	char *str;
7223*436bf2bcSAndroid Build Coastguard Worker 	int offset;
7224*436bf2bcSAndroid Build Coastguard Worker 	va_list args;
7225*436bf2bcSAndroid Build Coastguard Worker 
7226*436bf2bcSAndroid Build Coastguard Worker 	event = tep_find_event_by_record(tep, record);
7227*436bf2bcSAndroid Build Coastguard Worker 	if (!event) {
7228*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_printf(s, "[UNKNOWN EVENT]");
7229*436bf2bcSAndroid Build Coastguard Worker 		return;
7230*436bf2bcSAndroid Build Coastguard Worker 	}
7231*436bf2bcSAndroid Build Coastguard Worker 
7232*436bf2bcSAndroid Build Coastguard Worker 	str = current = format = strdup(fmt);
7233*436bf2bcSAndroid Build Coastguard Worker 	if (!format)
7234*436bf2bcSAndroid Build Coastguard Worker 		return;
7235*436bf2bcSAndroid Build Coastguard Worker 
7236*436bf2bcSAndroid Build Coastguard Worker 	va_start(args, fmt);
7237*436bf2bcSAndroid Build Coastguard Worker 	while (*current) {
7238*436bf2bcSAndroid Build Coastguard Worker 		current = strchr(str, '%');
7239*436bf2bcSAndroid Build Coastguard Worker 		if (!current) {
7240*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_puts(s, str);
7241*436bf2bcSAndroid Build Coastguard Worker 			break;
7242*436bf2bcSAndroid Build Coastguard Worker 		}
7243*436bf2bcSAndroid Build Coastguard Worker 		memset(&type, 0, sizeof(type));
7244*436bf2bcSAndroid Build Coastguard Worker 		offset = tep_print_event_param_type(current, &type);
7245*436bf2bcSAndroid Build Coastguard Worker 		*current = '\0';
7246*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_puts(s, str);
7247*436bf2bcSAndroid Build Coastguard Worker 		current += offset;
7248*436bf2bcSAndroid Build Coastguard Worker 		switch (type.type) {
7249*436bf2bcSAndroid Build Coastguard Worker 		case EVENT_TYPE_STRING:
7250*436bf2bcSAndroid Build Coastguard Worker 			print_string(tep, s, record, event,
7251*436bf2bcSAndroid Build Coastguard Worker 				     va_arg(args, char*), &type);
7252*436bf2bcSAndroid Build Coastguard Worker 			break;
7253*436bf2bcSAndroid Build Coastguard Worker 		case EVENT_TYPE_INT:
7254*436bf2bcSAndroid Build Coastguard Worker 			print_int(tep, s, record, event,
7255*436bf2bcSAndroid Build Coastguard Worker 				  va_arg(args, int), &type);
7256*436bf2bcSAndroid Build Coastguard Worker 			break;
7257*436bf2bcSAndroid Build Coastguard Worker 		case EVENT_TYPE_UNKNOWN:
7258*436bf2bcSAndroid Build Coastguard Worker 		default:
7259*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_printf(s, "[UNKNOWN TYPE]");
7260*436bf2bcSAndroid Build Coastguard Worker 			break;
7261*436bf2bcSAndroid Build Coastguard Worker 		}
7262*436bf2bcSAndroid Build Coastguard Worker 		str = current;
7263*436bf2bcSAndroid Build Coastguard Worker 
7264*436bf2bcSAndroid Build Coastguard Worker 	}
7265*436bf2bcSAndroid Build Coastguard Worker 	va_end(args);
7266*436bf2bcSAndroid Build Coastguard Worker 	free(format);
7267*436bf2bcSAndroid Build Coastguard Worker }
7268*436bf2bcSAndroid Build Coastguard Worker 
events_id_cmp(const void * a,const void * b)7269*436bf2bcSAndroid Build Coastguard Worker static int events_id_cmp(const void *a, const void *b)
7270*436bf2bcSAndroid Build Coastguard Worker {
7271*436bf2bcSAndroid Build Coastguard Worker 	struct tep_event * const * ea = a;
7272*436bf2bcSAndroid Build Coastguard Worker 	struct tep_event * const * eb = b;
7273*436bf2bcSAndroid Build Coastguard Worker 
7274*436bf2bcSAndroid Build Coastguard Worker 	if ((*ea)->id < (*eb)->id)
7275*436bf2bcSAndroid Build Coastguard Worker 		return -1;
7276*436bf2bcSAndroid Build Coastguard Worker 
7277*436bf2bcSAndroid Build Coastguard Worker 	if ((*ea)->id > (*eb)->id)
7278*436bf2bcSAndroid Build Coastguard Worker 		return 1;
7279*436bf2bcSAndroid Build Coastguard Worker 
7280*436bf2bcSAndroid Build Coastguard Worker 	return 0;
7281*436bf2bcSAndroid Build Coastguard Worker }
7282*436bf2bcSAndroid Build Coastguard Worker 
events_name_cmp(const void * a,const void * b)7283*436bf2bcSAndroid Build Coastguard Worker static int events_name_cmp(const void *a, const void *b)
7284*436bf2bcSAndroid Build Coastguard Worker {
7285*436bf2bcSAndroid Build Coastguard Worker 	struct tep_event * const * ea = a;
7286*436bf2bcSAndroid Build Coastguard Worker 	struct tep_event * const * eb = b;
7287*436bf2bcSAndroid Build Coastguard Worker 	int res;
7288*436bf2bcSAndroid Build Coastguard Worker 
7289*436bf2bcSAndroid Build Coastguard Worker 	res = strcmp((*ea)->name, (*eb)->name);
7290*436bf2bcSAndroid Build Coastguard Worker 	if (res)
7291*436bf2bcSAndroid Build Coastguard Worker 		return res;
7292*436bf2bcSAndroid Build Coastguard Worker 
7293*436bf2bcSAndroid Build Coastguard Worker 	res = strcmp((*ea)->system, (*eb)->system);
7294*436bf2bcSAndroid Build Coastguard Worker 	if (res)
7295*436bf2bcSAndroid Build Coastguard Worker 		return res;
7296*436bf2bcSAndroid Build Coastguard Worker 
7297*436bf2bcSAndroid Build Coastguard Worker 	return events_id_cmp(a, b);
7298*436bf2bcSAndroid Build Coastguard Worker }
7299*436bf2bcSAndroid Build Coastguard Worker 
events_system_cmp(const void * a,const void * b)7300*436bf2bcSAndroid Build Coastguard Worker static int events_system_cmp(const void *a, const void *b)
7301*436bf2bcSAndroid Build Coastguard Worker {
7302*436bf2bcSAndroid Build Coastguard Worker 	struct tep_event * const * ea = a;
7303*436bf2bcSAndroid Build Coastguard Worker 	struct tep_event * const * eb = b;
7304*436bf2bcSAndroid Build Coastguard Worker 	int res;
7305*436bf2bcSAndroid Build Coastguard Worker 
7306*436bf2bcSAndroid Build Coastguard Worker 	res = strcmp((*ea)->system, (*eb)->system);
7307*436bf2bcSAndroid Build Coastguard Worker 	if (res)
7308*436bf2bcSAndroid Build Coastguard Worker 		return res;
7309*436bf2bcSAndroid Build Coastguard Worker 
7310*436bf2bcSAndroid Build Coastguard Worker 	res = strcmp((*ea)->name, (*eb)->name);
7311*436bf2bcSAndroid Build Coastguard Worker 	if (res)
7312*436bf2bcSAndroid Build Coastguard Worker 		return res;
7313*436bf2bcSAndroid Build Coastguard Worker 
7314*436bf2bcSAndroid Build Coastguard Worker 	return events_id_cmp(a, b);
7315*436bf2bcSAndroid Build Coastguard Worker }
7316*436bf2bcSAndroid Build Coastguard Worker 
list_events_copy(struct tep_handle * tep)7317*436bf2bcSAndroid Build Coastguard Worker static struct tep_event **list_events_copy(struct tep_handle *tep)
7318*436bf2bcSAndroid Build Coastguard Worker {
7319*436bf2bcSAndroid Build Coastguard Worker 	struct tep_event **events;
7320*436bf2bcSAndroid Build Coastguard Worker 
7321*436bf2bcSAndroid Build Coastguard Worker 	if (!tep)
7322*436bf2bcSAndroid Build Coastguard Worker 		return NULL;
7323*436bf2bcSAndroid Build Coastguard Worker 
7324*436bf2bcSAndroid Build Coastguard Worker 	events = malloc(sizeof(*events) * (tep->nr_events + 1));
7325*436bf2bcSAndroid Build Coastguard Worker 	if (!events)
7326*436bf2bcSAndroid Build Coastguard Worker 		return NULL;
7327*436bf2bcSAndroid Build Coastguard Worker 
7328*436bf2bcSAndroid Build Coastguard Worker 	memcpy(events, tep->events, sizeof(*events) * tep->nr_events);
7329*436bf2bcSAndroid Build Coastguard Worker 	events[tep->nr_events] = NULL;
7330*436bf2bcSAndroid Build Coastguard Worker 	return events;
7331*436bf2bcSAndroid Build Coastguard Worker }
7332*436bf2bcSAndroid Build Coastguard Worker 
list_events_sort(struct tep_event ** events,int nr_events,enum tep_event_sort_type sort_type)7333*436bf2bcSAndroid Build Coastguard Worker static void list_events_sort(struct tep_event **events, int nr_events,
7334*436bf2bcSAndroid Build Coastguard Worker 			     enum tep_event_sort_type sort_type)
7335*436bf2bcSAndroid Build Coastguard Worker {
7336*436bf2bcSAndroid Build Coastguard Worker 	int (*sort)(const void *a, const void *b);
7337*436bf2bcSAndroid Build Coastguard Worker 
7338*436bf2bcSAndroid Build Coastguard Worker 	switch (sort_type) {
7339*436bf2bcSAndroid Build Coastguard Worker 	case TEP_EVENT_SORT_ID:
7340*436bf2bcSAndroid Build Coastguard Worker 		sort = events_id_cmp;
7341*436bf2bcSAndroid Build Coastguard Worker 		break;
7342*436bf2bcSAndroid Build Coastguard Worker 	case TEP_EVENT_SORT_NAME:
7343*436bf2bcSAndroid Build Coastguard Worker 		sort = events_name_cmp;
7344*436bf2bcSAndroid Build Coastguard Worker 		break;
7345*436bf2bcSAndroid Build Coastguard Worker 	case TEP_EVENT_SORT_SYSTEM:
7346*436bf2bcSAndroid Build Coastguard Worker 		sort = events_system_cmp;
7347*436bf2bcSAndroid Build Coastguard Worker 		break;
7348*436bf2bcSAndroid Build Coastguard Worker 	default:
7349*436bf2bcSAndroid Build Coastguard Worker 		sort = NULL;
7350*436bf2bcSAndroid Build Coastguard Worker 	}
7351*436bf2bcSAndroid Build Coastguard Worker 
7352*436bf2bcSAndroid Build Coastguard Worker 	if (sort)
7353*436bf2bcSAndroid Build Coastguard Worker 		qsort(events, nr_events, sizeof(*events), sort);
7354*436bf2bcSAndroid Build Coastguard Worker }
7355*436bf2bcSAndroid Build Coastguard Worker 
7356*436bf2bcSAndroid Build Coastguard Worker /**
7357*436bf2bcSAndroid Build Coastguard Worker  * tep_list_events - Get events, sorted by given criteria.
7358*436bf2bcSAndroid Build Coastguard Worker  * @tep: a handle to the tep context
7359*436bf2bcSAndroid Build Coastguard Worker  * @sort_type: desired sort order of the events in the array
7360*436bf2bcSAndroid Build Coastguard Worker  *
7361*436bf2bcSAndroid Build Coastguard Worker  * Returns an array of pointers to all events, sorted by the given
7362*436bf2bcSAndroid Build Coastguard Worker  * @sort_type criteria. The last element of the array is NULL. The returned
7363*436bf2bcSAndroid Build Coastguard Worker  * memory must not be freed, it is managed by the library.
7364*436bf2bcSAndroid Build Coastguard Worker  * The function is not thread safe.
7365*436bf2bcSAndroid Build Coastguard Worker  */
tep_list_events(struct tep_handle * tep,enum tep_event_sort_type sort_type)7366*436bf2bcSAndroid Build Coastguard Worker struct tep_event **tep_list_events(struct tep_handle *tep,
7367*436bf2bcSAndroid Build Coastguard Worker 				   enum tep_event_sort_type sort_type)
7368*436bf2bcSAndroid Build Coastguard Worker {
7369*436bf2bcSAndroid Build Coastguard Worker 	struct tep_event **events;
7370*436bf2bcSAndroid Build Coastguard Worker 
7371*436bf2bcSAndroid Build Coastguard Worker 	if (!tep)
7372*436bf2bcSAndroid Build Coastguard Worker 		return NULL;
7373*436bf2bcSAndroid Build Coastguard Worker 
7374*436bf2bcSAndroid Build Coastguard Worker 	events = tep->sort_events;
7375*436bf2bcSAndroid Build Coastguard Worker 	if (events && tep->last_type == sort_type)
7376*436bf2bcSAndroid Build Coastguard Worker 		return events;
7377*436bf2bcSAndroid Build Coastguard Worker 
7378*436bf2bcSAndroid Build Coastguard Worker 	if (!events) {
7379*436bf2bcSAndroid Build Coastguard Worker 		events = list_events_copy(tep);
7380*436bf2bcSAndroid Build Coastguard Worker 		if (!events)
7381*436bf2bcSAndroid Build Coastguard Worker 			return NULL;
7382*436bf2bcSAndroid Build Coastguard Worker 
7383*436bf2bcSAndroid Build Coastguard Worker 		tep->sort_events = events;
7384*436bf2bcSAndroid Build Coastguard Worker 
7385*436bf2bcSAndroid Build Coastguard Worker 		/* the internal events are sorted by id */
7386*436bf2bcSAndroid Build Coastguard Worker 		if (sort_type == TEP_EVENT_SORT_ID) {
7387*436bf2bcSAndroid Build Coastguard Worker 			tep->last_type = sort_type;
7388*436bf2bcSAndroid Build Coastguard Worker 			return events;
7389*436bf2bcSAndroid Build Coastguard Worker 		}
7390*436bf2bcSAndroid Build Coastguard Worker 	}
7391*436bf2bcSAndroid Build Coastguard Worker 
7392*436bf2bcSAndroid Build Coastguard Worker 	list_events_sort(events, tep->nr_events, sort_type);
7393*436bf2bcSAndroid Build Coastguard Worker 	tep->last_type = sort_type;
7394*436bf2bcSAndroid Build Coastguard Worker 
7395*436bf2bcSAndroid Build Coastguard Worker 	return events;
7396*436bf2bcSAndroid Build Coastguard Worker }
7397*436bf2bcSAndroid Build Coastguard Worker 
7398*436bf2bcSAndroid Build Coastguard Worker 
7399*436bf2bcSAndroid Build Coastguard Worker /**
7400*436bf2bcSAndroid Build Coastguard Worker  * tep_list_events_copy - Thread safe version of tep_list_events()
7401*436bf2bcSAndroid Build Coastguard Worker  * @tep: a handle to the tep context
7402*436bf2bcSAndroid Build Coastguard Worker  * @sort_type: desired sort order of the events in the array
7403*436bf2bcSAndroid Build Coastguard Worker  *
7404*436bf2bcSAndroid Build Coastguard Worker  * Returns an array of pointers to all events, sorted by the given
7405*436bf2bcSAndroid Build Coastguard Worker  * @sort_type criteria. The last element of the array is NULL. The returned
7406*436bf2bcSAndroid Build Coastguard Worker  * array is newly allocated inside the function and must be freed by the caller
7407*436bf2bcSAndroid Build Coastguard Worker  */
tep_list_events_copy(struct tep_handle * tep,enum tep_event_sort_type sort_type)7408*436bf2bcSAndroid Build Coastguard Worker struct tep_event **tep_list_events_copy(struct tep_handle *tep,
7409*436bf2bcSAndroid Build Coastguard Worker 					enum tep_event_sort_type sort_type)
7410*436bf2bcSAndroid Build Coastguard Worker {
7411*436bf2bcSAndroid Build Coastguard Worker 	struct tep_event **events;
7412*436bf2bcSAndroid Build Coastguard Worker 
7413*436bf2bcSAndroid Build Coastguard Worker 	if (!tep)
7414*436bf2bcSAndroid Build Coastguard Worker 		return NULL;
7415*436bf2bcSAndroid Build Coastguard Worker 
7416*436bf2bcSAndroid Build Coastguard Worker 	events = list_events_copy(tep);
7417*436bf2bcSAndroid Build Coastguard Worker 	if (!events)
7418*436bf2bcSAndroid Build Coastguard Worker 		return NULL;
7419*436bf2bcSAndroid Build Coastguard Worker 
7420*436bf2bcSAndroid Build Coastguard Worker 	/* the internal events are sorted by id */
7421*436bf2bcSAndroid Build Coastguard Worker 	if (sort_type == TEP_EVENT_SORT_ID)
7422*436bf2bcSAndroid Build Coastguard Worker 		return events;
7423*436bf2bcSAndroid Build Coastguard Worker 
7424*436bf2bcSAndroid Build Coastguard Worker 	list_events_sort(events, tep->nr_events, sort_type);
7425*436bf2bcSAndroid Build Coastguard Worker 
7426*436bf2bcSAndroid Build Coastguard Worker 	return events;
7427*436bf2bcSAndroid Build Coastguard Worker }
7428*436bf2bcSAndroid Build Coastguard Worker 
7429*436bf2bcSAndroid Build Coastguard Worker static struct tep_format_field **
get_event_fields(const char * type,const char * name,int count,struct tep_format_field * list)7430*436bf2bcSAndroid Build Coastguard Worker get_event_fields(const char *type, const char *name,
7431*436bf2bcSAndroid Build Coastguard Worker 		 int count, struct tep_format_field *list)
7432*436bf2bcSAndroid Build Coastguard Worker {
7433*436bf2bcSAndroid Build Coastguard Worker 	struct tep_format_field **fields;
7434*436bf2bcSAndroid Build Coastguard Worker 	struct tep_format_field *field;
7435*436bf2bcSAndroid Build Coastguard Worker 	int i = 0;
7436*436bf2bcSAndroid Build Coastguard Worker 
7437*436bf2bcSAndroid Build Coastguard Worker 	fields = malloc(sizeof(*fields) * (count + 1));
7438*436bf2bcSAndroid Build Coastguard Worker 	if (!fields)
7439*436bf2bcSAndroid Build Coastguard Worker 		return NULL;
7440*436bf2bcSAndroid Build Coastguard Worker 
7441*436bf2bcSAndroid Build Coastguard Worker 	for (field = list; field; field = field->next) {
7442*436bf2bcSAndroid Build Coastguard Worker 		fields[i++] = field;
7443*436bf2bcSAndroid Build Coastguard Worker 		if (i == count + 1) {
7444*436bf2bcSAndroid Build Coastguard Worker 			do_warning("event %s has more %s fields than specified",
7445*436bf2bcSAndroid Build Coastguard Worker 				name, type);
7446*436bf2bcSAndroid Build Coastguard Worker 			i--;
7447*436bf2bcSAndroid Build Coastguard Worker 			break;
7448*436bf2bcSAndroid Build Coastguard Worker 		}
7449*436bf2bcSAndroid Build Coastguard Worker 	}
7450*436bf2bcSAndroid Build Coastguard Worker 
7451*436bf2bcSAndroid Build Coastguard Worker 	if (i != count)
7452*436bf2bcSAndroid Build Coastguard Worker 		do_warning("event %s has less %s fields than specified",
7453*436bf2bcSAndroid Build Coastguard Worker 			name, type);
7454*436bf2bcSAndroid Build Coastguard Worker 
7455*436bf2bcSAndroid Build Coastguard Worker 	fields[i] = NULL;
7456*436bf2bcSAndroid Build Coastguard Worker 
7457*436bf2bcSAndroid Build Coastguard Worker 	return fields;
7458*436bf2bcSAndroid Build Coastguard Worker }
7459*436bf2bcSAndroid Build Coastguard Worker 
7460*436bf2bcSAndroid Build Coastguard Worker /**
7461*436bf2bcSAndroid Build Coastguard Worker  * tep_event_common_fields - return a list of common fields for an event
7462*436bf2bcSAndroid Build Coastguard Worker  * @event: the event to return the common fields of.
7463*436bf2bcSAndroid Build Coastguard Worker  *
7464*436bf2bcSAndroid Build Coastguard Worker  * Returns an allocated array of fields. The last item in the array is NULL.
7465*436bf2bcSAndroid Build Coastguard Worker  * The array must be freed with free().
7466*436bf2bcSAndroid Build Coastguard Worker  */
tep_event_common_fields(struct tep_event * event)7467*436bf2bcSAndroid Build Coastguard Worker struct tep_format_field **tep_event_common_fields(struct tep_event *event)
7468*436bf2bcSAndroid Build Coastguard Worker {
7469*436bf2bcSAndroid Build Coastguard Worker 	return get_event_fields("common", event->name,
7470*436bf2bcSAndroid Build Coastguard Worker 				event->format.nr_common,
7471*436bf2bcSAndroid Build Coastguard Worker 				event->format.common_fields);
7472*436bf2bcSAndroid Build Coastguard Worker }
7473*436bf2bcSAndroid Build Coastguard Worker 
7474*436bf2bcSAndroid Build Coastguard Worker /**
7475*436bf2bcSAndroid Build Coastguard Worker  * tep_event_fields - return a list of event specific fields for an event
7476*436bf2bcSAndroid Build Coastguard Worker  * @event: the event to return the fields of.
7477*436bf2bcSAndroid Build Coastguard Worker  *
7478*436bf2bcSAndroid Build Coastguard Worker  * Returns an allocated array of fields. The last item in the array is NULL.
7479*436bf2bcSAndroid Build Coastguard Worker  * The array must be freed with free().
7480*436bf2bcSAndroid Build Coastguard Worker  */
tep_event_fields(struct tep_event * event)7481*436bf2bcSAndroid Build Coastguard Worker struct tep_format_field **tep_event_fields(struct tep_event *event)
7482*436bf2bcSAndroid Build Coastguard Worker {
7483*436bf2bcSAndroid Build Coastguard Worker 	return get_event_fields("event", event->name,
7484*436bf2bcSAndroid Build Coastguard Worker 				event->format.nr_fields,
7485*436bf2bcSAndroid Build Coastguard Worker 				event->format.fields);
7486*436bf2bcSAndroid Build Coastguard Worker }
7487*436bf2bcSAndroid Build Coastguard Worker 
print_fields(struct trace_seq * s,struct tep_print_flag_sym * field)7488*436bf2bcSAndroid Build Coastguard Worker static void print_fields(struct trace_seq *s, struct tep_print_flag_sym *field)
7489*436bf2bcSAndroid Build Coastguard Worker {
7490*436bf2bcSAndroid Build Coastguard Worker 	trace_seq_printf(s, "{ %s, %s }", field->value, field->str);
7491*436bf2bcSAndroid Build Coastguard Worker 	if (field->next) {
7492*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_puts(s, ", ");
7493*436bf2bcSAndroid Build Coastguard Worker 		print_fields(s, field->next);
7494*436bf2bcSAndroid Build Coastguard Worker 	}
7495*436bf2bcSAndroid Build Coastguard Worker }
7496*436bf2bcSAndroid Build Coastguard Worker 
7497*436bf2bcSAndroid Build Coastguard Worker /* for debugging */
print_args(struct tep_print_arg * args)7498*436bf2bcSAndroid Build Coastguard Worker static void print_args(struct tep_print_arg *args)
7499*436bf2bcSAndroid Build Coastguard Worker {
7500*436bf2bcSAndroid Build Coastguard Worker 	int print_paren = 1;
7501*436bf2bcSAndroid Build Coastguard Worker 	struct trace_seq s;
7502*436bf2bcSAndroid Build Coastguard Worker 
7503*436bf2bcSAndroid Build Coastguard Worker 	switch (args->type) {
7504*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_NULL:
7505*436bf2bcSAndroid Build Coastguard Worker 		printf("null");
7506*436bf2bcSAndroid Build Coastguard Worker 		break;
7507*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_ATOM:
7508*436bf2bcSAndroid Build Coastguard Worker 		printf("%s", args->atom.atom);
7509*436bf2bcSAndroid Build Coastguard Worker 		break;
7510*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_FIELD:
7511*436bf2bcSAndroid Build Coastguard Worker 		printf("REC->%s", args->field.name);
7512*436bf2bcSAndroid Build Coastguard Worker 		break;
7513*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_FLAGS:
7514*436bf2bcSAndroid Build Coastguard Worker 		printf("__print_flags(");
7515*436bf2bcSAndroid Build Coastguard Worker 		print_args(args->flags.field);
7516*436bf2bcSAndroid Build Coastguard Worker 		printf(", %s, ", args->flags.delim);
7517*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_init(&s);
7518*436bf2bcSAndroid Build Coastguard Worker 		print_fields(&s, args->flags.flags);
7519*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_do_printf(&s);
7520*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_destroy(&s);
7521*436bf2bcSAndroid Build Coastguard Worker 		printf(")");
7522*436bf2bcSAndroid Build Coastguard Worker 		break;
7523*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_SYMBOL:
7524*436bf2bcSAndroid Build Coastguard Worker 		printf("__print_symbolic(");
7525*436bf2bcSAndroid Build Coastguard Worker 		print_args(args->symbol.field);
7526*436bf2bcSAndroid Build Coastguard Worker 		printf(", ");
7527*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_init(&s);
7528*436bf2bcSAndroid Build Coastguard Worker 		print_fields(&s, args->symbol.symbols);
7529*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_do_printf(&s);
7530*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_destroy(&s);
7531*436bf2bcSAndroid Build Coastguard Worker 		printf(")");
7532*436bf2bcSAndroid Build Coastguard Worker 		break;
7533*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_HEX:
7534*436bf2bcSAndroid Build Coastguard Worker 		printf("__print_hex(");
7535*436bf2bcSAndroid Build Coastguard Worker 		print_args(args->hex.field);
7536*436bf2bcSAndroid Build Coastguard Worker 		printf(", ");
7537*436bf2bcSAndroid Build Coastguard Worker 		print_args(args->hex.size);
7538*436bf2bcSAndroid Build Coastguard Worker 		printf(")");
7539*436bf2bcSAndroid Build Coastguard Worker 		break;
7540*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_HEX_STR:
7541*436bf2bcSAndroid Build Coastguard Worker 		printf("__print_hex_str(");
7542*436bf2bcSAndroid Build Coastguard Worker 		print_args(args->hex.field);
7543*436bf2bcSAndroid Build Coastguard Worker 		printf(", ");
7544*436bf2bcSAndroid Build Coastguard Worker 		print_args(args->hex.size);
7545*436bf2bcSAndroid Build Coastguard Worker 		printf(")");
7546*436bf2bcSAndroid Build Coastguard Worker 		break;
7547*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_INT_ARRAY:
7548*436bf2bcSAndroid Build Coastguard Worker 		printf("__print_array(");
7549*436bf2bcSAndroid Build Coastguard Worker 		print_args(args->int_array.field);
7550*436bf2bcSAndroid Build Coastguard Worker 		printf(", ");
7551*436bf2bcSAndroid Build Coastguard Worker 		print_args(args->int_array.count);
7552*436bf2bcSAndroid Build Coastguard Worker 		printf(", ");
7553*436bf2bcSAndroid Build Coastguard Worker 		print_args(args->int_array.el_size);
7554*436bf2bcSAndroid Build Coastguard Worker 		printf(")");
7555*436bf2bcSAndroid Build Coastguard Worker 		break;
7556*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_STRING:
7557*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_BSTRING:
7558*436bf2bcSAndroid Build Coastguard Worker 		printf("__get_str(%s)", args->string.string);
7559*436bf2bcSAndroid Build Coastguard Worker 		break;
7560*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_BITMASK:
7561*436bf2bcSAndroid Build Coastguard Worker 		printf("__get_bitmask(%s)", args->bitmask.bitmask);
7562*436bf2bcSAndroid Build Coastguard Worker 		break;
7563*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_CPUMASK:
7564*436bf2bcSAndroid Build Coastguard Worker 		printf("__get_cpumask(%s)", args->bitmask.bitmask);
7565*436bf2bcSAndroid Build Coastguard Worker 		break;
7566*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_TYPE:
7567*436bf2bcSAndroid Build Coastguard Worker 		printf("(%s)", args->typecast.type);
7568*436bf2bcSAndroid Build Coastguard Worker 		print_args(args->typecast.item);
7569*436bf2bcSAndroid Build Coastguard Worker 		break;
7570*436bf2bcSAndroid Build Coastguard Worker 	case TEP_PRINT_OP:
7571*436bf2bcSAndroid Build Coastguard Worker 		if (strcmp(args->op.op, ":") == 0)
7572*436bf2bcSAndroid Build Coastguard Worker 			print_paren = 0;
7573*436bf2bcSAndroid Build Coastguard Worker 		if (print_paren)
7574*436bf2bcSAndroid Build Coastguard Worker 			printf("(");
7575*436bf2bcSAndroid Build Coastguard Worker 		print_args(args->op.left);
7576*436bf2bcSAndroid Build Coastguard Worker 		printf(" %s ", args->op.op);
7577*436bf2bcSAndroid Build Coastguard Worker 		print_args(args->op.right);
7578*436bf2bcSAndroid Build Coastguard Worker 		if (print_paren)
7579*436bf2bcSAndroid Build Coastguard Worker 			printf(")");
7580*436bf2bcSAndroid Build Coastguard Worker 		break;
7581*436bf2bcSAndroid Build Coastguard Worker 	default:
7582*436bf2bcSAndroid Build Coastguard Worker 		/* we should warn... */
7583*436bf2bcSAndroid Build Coastguard Worker 		return;
7584*436bf2bcSAndroid Build Coastguard Worker 	}
7585*436bf2bcSAndroid Build Coastguard Worker 	if (args->next) {
7586*436bf2bcSAndroid Build Coastguard Worker 		printf("\n");
7587*436bf2bcSAndroid Build Coastguard Worker 		print_args(args->next);
7588*436bf2bcSAndroid Build Coastguard Worker 	}
7589*436bf2bcSAndroid Build Coastguard Worker }
7590*436bf2bcSAndroid Build Coastguard Worker 
parse_header_field(struct tep_handle * tep,const char * field,int * offset,int * size,int mandatory)7591*436bf2bcSAndroid Build Coastguard Worker static void parse_header_field(struct tep_handle *tep, const char *field,
7592*436bf2bcSAndroid Build Coastguard Worker 			       int *offset, int *size, int mandatory)
7593*436bf2bcSAndroid Build Coastguard Worker {
7594*436bf2bcSAndroid Build Coastguard Worker 	unsigned long long save_input_buf_ptr;
7595*436bf2bcSAndroid Build Coastguard Worker 	unsigned long long save_input_buf_siz;
7596*436bf2bcSAndroid Build Coastguard Worker 	char *token;
7597*436bf2bcSAndroid Build Coastguard Worker 	int type;
7598*436bf2bcSAndroid Build Coastguard Worker 
7599*436bf2bcSAndroid Build Coastguard Worker 	save_input_buf_ptr = tep->input_buf_ptr;
7600*436bf2bcSAndroid Build Coastguard Worker 	save_input_buf_siz = tep->input_buf_siz;
7601*436bf2bcSAndroid Build Coastguard Worker 
7602*436bf2bcSAndroid Build Coastguard Worker 	if (read_expected(tep, TEP_EVENT_ITEM, "field") < 0)
7603*436bf2bcSAndroid Build Coastguard Worker 		return;
7604*436bf2bcSAndroid Build Coastguard Worker 	if (read_expected(tep, TEP_EVENT_OP, ":") < 0)
7605*436bf2bcSAndroid Build Coastguard Worker 		return;
7606*436bf2bcSAndroid Build Coastguard Worker 
7607*436bf2bcSAndroid Build Coastguard Worker 	/* type */
7608*436bf2bcSAndroid Build Coastguard Worker 	if (read_expect_type(tep, TEP_EVENT_ITEM, &token) < 0)
7609*436bf2bcSAndroid Build Coastguard Worker 		goto fail;
7610*436bf2bcSAndroid Build Coastguard Worker 	free_token(token);
7611*436bf2bcSAndroid Build Coastguard Worker 
7612*436bf2bcSAndroid Build Coastguard Worker 	/*
7613*436bf2bcSAndroid Build Coastguard Worker 	 * If this is not a mandatory field, then test it first.
7614*436bf2bcSAndroid Build Coastguard Worker 	 */
7615*436bf2bcSAndroid Build Coastguard Worker 	if (mandatory) {
7616*436bf2bcSAndroid Build Coastguard Worker 		if (read_expected(tep, TEP_EVENT_ITEM, field) < 0)
7617*436bf2bcSAndroid Build Coastguard Worker 			return;
7618*436bf2bcSAndroid Build Coastguard Worker 	} else {
7619*436bf2bcSAndroid Build Coastguard Worker 		if (read_expect_type(tep, TEP_EVENT_ITEM, &token) < 0)
7620*436bf2bcSAndroid Build Coastguard Worker 			goto fail;
7621*436bf2bcSAndroid Build Coastguard Worker 		if (strcmp(token, field) != 0)
7622*436bf2bcSAndroid Build Coastguard Worker 			goto discard;
7623*436bf2bcSAndroid Build Coastguard Worker 		free_token(token);
7624*436bf2bcSAndroid Build Coastguard Worker 	}
7625*436bf2bcSAndroid Build Coastguard Worker 
7626*436bf2bcSAndroid Build Coastguard Worker 	if (read_expected(tep, TEP_EVENT_OP, ";") < 0)
7627*436bf2bcSAndroid Build Coastguard Worker 		return;
7628*436bf2bcSAndroid Build Coastguard Worker 	if (read_expected(tep, TEP_EVENT_ITEM, "offset") < 0)
7629*436bf2bcSAndroid Build Coastguard Worker 		return;
7630*436bf2bcSAndroid Build Coastguard Worker 	if (read_expected(tep, TEP_EVENT_OP, ":") < 0)
7631*436bf2bcSAndroid Build Coastguard Worker 		return;
7632*436bf2bcSAndroid Build Coastguard Worker 	if (read_expect_type(tep, TEP_EVENT_ITEM, &token) < 0)
7633*436bf2bcSAndroid Build Coastguard Worker 		goto fail;
7634*436bf2bcSAndroid Build Coastguard Worker 	*offset = atoi(token);
7635*436bf2bcSAndroid Build Coastguard Worker 	free_token(token);
7636*436bf2bcSAndroid Build Coastguard Worker 	if (read_expected(tep, TEP_EVENT_OP, ";") < 0)
7637*436bf2bcSAndroid Build Coastguard Worker 		return;
7638*436bf2bcSAndroid Build Coastguard Worker 	if (read_expected(tep, TEP_EVENT_ITEM, "size") < 0)
7639*436bf2bcSAndroid Build Coastguard Worker 		return;
7640*436bf2bcSAndroid Build Coastguard Worker 	if (read_expected(tep, TEP_EVENT_OP, ":") < 0)
7641*436bf2bcSAndroid Build Coastguard Worker 		return;
7642*436bf2bcSAndroid Build Coastguard Worker 	if (read_expect_type(tep, TEP_EVENT_ITEM, &token) < 0)
7643*436bf2bcSAndroid Build Coastguard Worker 		goto fail;
7644*436bf2bcSAndroid Build Coastguard Worker 	*size = atoi(token);
7645*436bf2bcSAndroid Build Coastguard Worker 	free_token(token);
7646*436bf2bcSAndroid Build Coastguard Worker 	if (read_expected(tep, TEP_EVENT_OP, ";") < 0)
7647*436bf2bcSAndroid Build Coastguard Worker 		return;
7648*436bf2bcSAndroid Build Coastguard Worker 	type = read_token(tep, &token);
7649*436bf2bcSAndroid Build Coastguard Worker 	if (type != TEP_EVENT_NEWLINE) {
7650*436bf2bcSAndroid Build Coastguard Worker 		/* newer versions of the kernel have a "signed" type */
7651*436bf2bcSAndroid Build Coastguard Worker 		if (type != TEP_EVENT_ITEM)
7652*436bf2bcSAndroid Build Coastguard Worker 			goto fail;
7653*436bf2bcSAndroid Build Coastguard Worker 
7654*436bf2bcSAndroid Build Coastguard Worker 		if (strcmp(token, "signed") != 0)
7655*436bf2bcSAndroid Build Coastguard Worker 			goto fail;
7656*436bf2bcSAndroid Build Coastguard Worker 
7657*436bf2bcSAndroid Build Coastguard Worker 		free_token(token);
7658*436bf2bcSAndroid Build Coastguard Worker 
7659*436bf2bcSAndroid Build Coastguard Worker 		if (read_expected(tep, TEP_EVENT_OP, ":") < 0)
7660*436bf2bcSAndroid Build Coastguard Worker 			return;
7661*436bf2bcSAndroid Build Coastguard Worker 
7662*436bf2bcSAndroid Build Coastguard Worker 		if (read_expect_type(tep, TEP_EVENT_ITEM, &token))
7663*436bf2bcSAndroid Build Coastguard Worker 			goto fail;
7664*436bf2bcSAndroid Build Coastguard Worker 
7665*436bf2bcSAndroid Build Coastguard Worker 		free_token(token);
7666*436bf2bcSAndroid Build Coastguard Worker 		if (read_expected(tep, TEP_EVENT_OP, ";") < 0)
7667*436bf2bcSAndroid Build Coastguard Worker 			return;
7668*436bf2bcSAndroid Build Coastguard Worker 
7669*436bf2bcSAndroid Build Coastguard Worker 		if (read_expect_type(tep, TEP_EVENT_NEWLINE, &token))
7670*436bf2bcSAndroid Build Coastguard Worker 			goto fail;
7671*436bf2bcSAndroid Build Coastguard Worker 	}
7672*436bf2bcSAndroid Build Coastguard Worker  fail:
7673*436bf2bcSAndroid Build Coastguard Worker 	free_token(token);
7674*436bf2bcSAndroid Build Coastguard Worker 	return;
7675*436bf2bcSAndroid Build Coastguard Worker 
7676*436bf2bcSAndroid Build Coastguard Worker  discard:
7677*436bf2bcSAndroid Build Coastguard Worker 	tep->input_buf_ptr = save_input_buf_ptr;
7678*436bf2bcSAndroid Build Coastguard Worker 	tep->input_buf_siz = save_input_buf_siz;
7679*436bf2bcSAndroid Build Coastguard Worker 	*offset = 0;
7680*436bf2bcSAndroid Build Coastguard Worker 	*size = 0;
7681*436bf2bcSAndroid Build Coastguard Worker 	free_token(token);
7682*436bf2bcSAndroid Build Coastguard Worker }
7683*436bf2bcSAndroid Build Coastguard Worker 
7684*436bf2bcSAndroid Build Coastguard Worker /**
7685*436bf2bcSAndroid Build Coastguard Worker  * tep_parse_header_page - parse the data stored in the header page
7686*436bf2bcSAndroid Build Coastguard Worker  * @tep: a handle to the trace event parser context
7687*436bf2bcSAndroid Build Coastguard Worker  * @buf: the buffer storing the header page format string
7688*436bf2bcSAndroid Build Coastguard Worker  * @size: the size of @buf
7689*436bf2bcSAndroid Build Coastguard Worker  * @long_size: the long size to use if there is no header
7690*436bf2bcSAndroid Build Coastguard Worker  *
7691*436bf2bcSAndroid Build Coastguard Worker  * This parses the header page format for information on the
7692*436bf2bcSAndroid Build Coastguard Worker  * ring buffer used. The @buf should be copied from
7693*436bf2bcSAndroid Build Coastguard Worker  *
7694*436bf2bcSAndroid Build Coastguard Worker  * /sys/kernel/debug/tracing/events/header_page
7695*436bf2bcSAndroid Build Coastguard Worker  */
tep_parse_header_page(struct tep_handle * tep,char * buf,unsigned long size,int long_size)7696*436bf2bcSAndroid Build Coastguard Worker int tep_parse_header_page(struct tep_handle *tep, char *buf, unsigned long size,
7697*436bf2bcSAndroid Build Coastguard Worker 			  int long_size)
7698*436bf2bcSAndroid Build Coastguard Worker {
7699*436bf2bcSAndroid Build Coastguard Worker 	int ignore;
7700*436bf2bcSAndroid Build Coastguard Worker 
7701*436bf2bcSAndroid Build Coastguard Worker 	if (!size) {
7702*436bf2bcSAndroid Build Coastguard Worker 		/*
7703*436bf2bcSAndroid Build Coastguard Worker 		 * Old kernels did not have header page info.
7704*436bf2bcSAndroid Build Coastguard Worker 		 * Sorry but we just use what we find here in user space.
7705*436bf2bcSAndroid Build Coastguard Worker 		 */
7706*436bf2bcSAndroid Build Coastguard Worker 		tep->header_page_ts_size = sizeof(long long);
7707*436bf2bcSAndroid Build Coastguard Worker 		tep->header_page_size_size = long_size;
7708*436bf2bcSAndroid Build Coastguard Worker 		tep->header_page_data_offset = sizeof(long long) + long_size;
7709*436bf2bcSAndroid Build Coastguard Worker 		tep->header_page_data_size = getpagesize() - tep->header_page_data_offset;
7710*436bf2bcSAndroid Build Coastguard Worker 		tep->old_format = 1;
7711*436bf2bcSAndroid Build Coastguard Worker 		return -1;
7712*436bf2bcSAndroid Build Coastguard Worker 	}
7713*436bf2bcSAndroid Build Coastguard Worker 	init_input_buf(tep, buf, size);
7714*436bf2bcSAndroid Build Coastguard Worker 
7715*436bf2bcSAndroid Build Coastguard Worker 	parse_header_field(tep, "timestamp", &tep->header_page_ts_offset,
7716*436bf2bcSAndroid Build Coastguard Worker 			   &tep->header_page_ts_size, 1);
7717*436bf2bcSAndroid Build Coastguard Worker 	parse_header_field(tep, "commit", &tep->header_page_size_offset,
7718*436bf2bcSAndroid Build Coastguard Worker 			   &tep->header_page_size_size, 1);
7719*436bf2bcSAndroid Build Coastguard Worker 	parse_header_field(tep, "overwrite", &tep->header_page_overwrite,
7720*436bf2bcSAndroid Build Coastguard Worker 			   &ignore, 0);
7721*436bf2bcSAndroid Build Coastguard Worker 	parse_header_field(tep, "data", &tep->header_page_data_offset,
7722*436bf2bcSAndroid Build Coastguard Worker 			   &tep->header_page_data_size, 1);
7723*436bf2bcSAndroid Build Coastguard Worker 
7724*436bf2bcSAndroid Build Coastguard Worker 	return 0;
7725*436bf2bcSAndroid Build Coastguard Worker }
7726*436bf2bcSAndroid Build Coastguard Worker 
event_matches(struct tep_event * event,int id,const char * sys_name,const char * event_name)7727*436bf2bcSAndroid Build Coastguard Worker static int event_matches(struct tep_event *event,
7728*436bf2bcSAndroid Build Coastguard Worker 			 int id, const char *sys_name,
7729*436bf2bcSAndroid Build Coastguard Worker 			 const char *event_name)
7730*436bf2bcSAndroid Build Coastguard Worker {
7731*436bf2bcSAndroid Build Coastguard Worker 	if (id >= 0 && id != event->id)
7732*436bf2bcSAndroid Build Coastguard Worker 		return 0;
7733*436bf2bcSAndroid Build Coastguard Worker 
7734*436bf2bcSAndroid Build Coastguard Worker 	if (event_name && (strcmp(event_name, event->name) != 0))
7735*436bf2bcSAndroid Build Coastguard Worker 		return 0;
7736*436bf2bcSAndroid Build Coastguard Worker 
7737*436bf2bcSAndroid Build Coastguard Worker 	if (sys_name && (strcmp(sys_name, event->system) != 0))
7738*436bf2bcSAndroid Build Coastguard Worker 		return 0;
7739*436bf2bcSAndroid Build Coastguard Worker 
7740*436bf2bcSAndroid Build Coastguard Worker 	return 1;
7741*436bf2bcSAndroid Build Coastguard Worker }
7742*436bf2bcSAndroid Build Coastguard Worker 
free_handler(struct event_handler * handle)7743*436bf2bcSAndroid Build Coastguard Worker static void free_handler(struct event_handler *handle)
7744*436bf2bcSAndroid Build Coastguard Worker {
7745*436bf2bcSAndroid Build Coastguard Worker 	free((void *)handle->sys_name);
7746*436bf2bcSAndroid Build Coastguard Worker 	free((void *)handle->event_name);
7747*436bf2bcSAndroid Build Coastguard Worker 	free(handle);
7748*436bf2bcSAndroid Build Coastguard Worker }
7749*436bf2bcSAndroid Build Coastguard Worker 
find_event_handle(struct tep_handle * tep,struct tep_event * event)7750*436bf2bcSAndroid Build Coastguard Worker static int find_event_handle(struct tep_handle *tep, struct tep_event *event)
7751*436bf2bcSAndroid Build Coastguard Worker {
7752*436bf2bcSAndroid Build Coastguard Worker 	struct event_handler *handle, **next;
7753*436bf2bcSAndroid Build Coastguard Worker 
7754*436bf2bcSAndroid Build Coastguard Worker 	for (next = &tep->handlers; *next;
7755*436bf2bcSAndroid Build Coastguard Worker 	     next = &(*next)->next) {
7756*436bf2bcSAndroid Build Coastguard Worker 		handle = *next;
7757*436bf2bcSAndroid Build Coastguard Worker 		if (event_matches(event, handle->id,
7758*436bf2bcSAndroid Build Coastguard Worker 				  handle->sys_name,
7759*436bf2bcSAndroid Build Coastguard Worker 				  handle->event_name))
7760*436bf2bcSAndroid Build Coastguard Worker 			break;
7761*436bf2bcSAndroid Build Coastguard Worker 	}
7762*436bf2bcSAndroid Build Coastguard Worker 
7763*436bf2bcSAndroid Build Coastguard Worker 	if (!(*next))
7764*436bf2bcSAndroid Build Coastguard Worker 		return 0;
7765*436bf2bcSAndroid Build Coastguard Worker 
7766*436bf2bcSAndroid Build Coastguard Worker 	tep_info("overriding event (%d) %s:%s with new print handler",
7767*436bf2bcSAndroid Build Coastguard Worker 		 event->id, event->system, event->name);
7768*436bf2bcSAndroid Build Coastguard Worker 
7769*436bf2bcSAndroid Build Coastguard Worker 	event->handler = handle->func;
7770*436bf2bcSAndroid Build Coastguard Worker 	event->context = handle->context;
7771*436bf2bcSAndroid Build Coastguard Worker 
7772*436bf2bcSAndroid Build Coastguard Worker 	*next = handle->next;
7773*436bf2bcSAndroid Build Coastguard Worker 	free_handler(handle);
7774*436bf2bcSAndroid Build Coastguard Worker 
7775*436bf2bcSAndroid Build Coastguard Worker 	return 1;
7776*436bf2bcSAndroid Build Coastguard Worker }
7777*436bf2bcSAndroid Build Coastguard Worker 
7778*436bf2bcSAndroid Build Coastguard Worker /**
7779*436bf2bcSAndroid Build Coastguard Worker  * parse_format - parse the event format
7780*436bf2bcSAndroid Build Coastguard Worker  * @buf: the buffer storing the event format string
7781*436bf2bcSAndroid Build Coastguard Worker  * @size: the size of @buf
7782*436bf2bcSAndroid Build Coastguard Worker  * @sys: the system the event belongs to
7783*436bf2bcSAndroid Build Coastguard Worker  *
7784*436bf2bcSAndroid Build Coastguard Worker  * This parses the event format and creates an event structure
7785*436bf2bcSAndroid Build Coastguard Worker  * to quickly parse raw data for a given event.
7786*436bf2bcSAndroid Build Coastguard Worker  *
7787*436bf2bcSAndroid Build Coastguard Worker  * These files currently come from:
7788*436bf2bcSAndroid Build Coastguard Worker  *
7789*436bf2bcSAndroid Build Coastguard Worker  * /sys/kernel/debug/tracing/events/.../.../format
7790*436bf2bcSAndroid Build Coastguard Worker  */
parse_format(struct tep_event ** eventp,struct tep_handle * tep,const char * buf,unsigned long size,const char * sys)7791*436bf2bcSAndroid Build Coastguard Worker static enum tep_errno parse_format(struct tep_event **eventp,
7792*436bf2bcSAndroid Build Coastguard Worker 				   struct tep_handle *tep, const char *buf,
7793*436bf2bcSAndroid Build Coastguard Worker 				   unsigned long size, const char *sys)
7794*436bf2bcSAndroid Build Coastguard Worker {
7795*436bf2bcSAndroid Build Coastguard Worker 	struct tep_event *event;
7796*436bf2bcSAndroid Build Coastguard Worker 	int ret;
7797*436bf2bcSAndroid Build Coastguard Worker 
7798*436bf2bcSAndroid Build Coastguard Worker 	init_input_buf(tep, buf, size);
7799*436bf2bcSAndroid Build Coastguard Worker 
7800*436bf2bcSAndroid Build Coastguard Worker 	*eventp = event = alloc_event();
7801*436bf2bcSAndroid Build Coastguard Worker 	if (!event)
7802*436bf2bcSAndroid Build Coastguard Worker 		return TEP_ERRNO__MEM_ALLOC_FAILED;
7803*436bf2bcSAndroid Build Coastguard Worker 
7804*436bf2bcSAndroid Build Coastguard Worker 	event->name = event_read_name(tep);
7805*436bf2bcSAndroid Build Coastguard Worker 	if (!event->name) {
7806*436bf2bcSAndroid Build Coastguard Worker 		/* Bad event? */
7807*436bf2bcSAndroid Build Coastguard Worker 		ret = TEP_ERRNO__MEM_ALLOC_FAILED;
7808*436bf2bcSAndroid Build Coastguard Worker 		goto event_alloc_failed;
7809*436bf2bcSAndroid Build Coastguard Worker 	}
7810*436bf2bcSAndroid Build Coastguard Worker 
7811*436bf2bcSAndroid Build Coastguard Worker 	if (strcmp(sys, "ftrace") == 0) {
7812*436bf2bcSAndroid Build Coastguard Worker 		event->flags |= TEP_EVENT_FL_ISFTRACE;
7813*436bf2bcSAndroid Build Coastguard Worker 
7814*436bf2bcSAndroid Build Coastguard Worker 		if (strcmp(event->name, "bprint") == 0)
7815*436bf2bcSAndroid Build Coastguard Worker 			event->flags |= TEP_EVENT_FL_ISBPRINT;
7816*436bf2bcSAndroid Build Coastguard Worker 	}
7817*436bf2bcSAndroid Build Coastguard Worker 
7818*436bf2bcSAndroid Build Coastguard Worker 	event->id = event_read_id(tep);
7819*436bf2bcSAndroid Build Coastguard Worker 	if (event->id < 0) {
7820*436bf2bcSAndroid Build Coastguard Worker 		ret = TEP_ERRNO__READ_ID_FAILED;
7821*436bf2bcSAndroid Build Coastguard Worker 		/*
7822*436bf2bcSAndroid Build Coastguard Worker 		 * This isn't an allocation error actually.
7823*436bf2bcSAndroid Build Coastguard Worker 		 * But as the ID is critical, just bail out.
7824*436bf2bcSAndroid Build Coastguard Worker 		 */
7825*436bf2bcSAndroid Build Coastguard Worker 		goto event_alloc_failed;
7826*436bf2bcSAndroid Build Coastguard Worker 	}
7827*436bf2bcSAndroid Build Coastguard Worker 
7828*436bf2bcSAndroid Build Coastguard Worker 	event->system = strdup(sys);
7829*436bf2bcSAndroid Build Coastguard Worker 	if (!event->system) {
7830*436bf2bcSAndroid Build Coastguard Worker 		ret = TEP_ERRNO__MEM_ALLOC_FAILED;
7831*436bf2bcSAndroid Build Coastguard Worker 		goto event_alloc_failed;
7832*436bf2bcSAndroid Build Coastguard Worker 	}
7833*436bf2bcSAndroid Build Coastguard Worker 
7834*436bf2bcSAndroid Build Coastguard Worker 	/* Add tep to event so that it can be referenced */
7835*436bf2bcSAndroid Build Coastguard Worker 	event->tep = tep;
7836*436bf2bcSAndroid Build Coastguard Worker 
7837*436bf2bcSAndroid Build Coastguard Worker 	ret = event_read_format(event);
7838*436bf2bcSAndroid Build Coastguard Worker 	if (ret < 0) {
7839*436bf2bcSAndroid Build Coastguard Worker 		ret = TEP_ERRNO__READ_FORMAT_FAILED;
7840*436bf2bcSAndroid Build Coastguard Worker 		goto event_parse_failed;
7841*436bf2bcSAndroid Build Coastguard Worker 	}
7842*436bf2bcSAndroid Build Coastguard Worker 
7843*436bf2bcSAndroid Build Coastguard Worker 	/*
7844*436bf2bcSAndroid Build Coastguard Worker 	 * If the event has an override, don't print warnings if the event
7845*436bf2bcSAndroid Build Coastguard Worker 	 * print format fails to parse.
7846*436bf2bcSAndroid Build Coastguard Worker 	 */
7847*436bf2bcSAndroid Build Coastguard Worker 	if (tep && find_event_handle(tep, event))
7848*436bf2bcSAndroid Build Coastguard Worker 		show_warning = 0;
7849*436bf2bcSAndroid Build Coastguard Worker 
7850*436bf2bcSAndroid Build Coastguard Worker 	ret = event_read_print(event);
7851*436bf2bcSAndroid Build Coastguard Worker 	show_warning = 1;
7852*436bf2bcSAndroid Build Coastguard Worker 
7853*436bf2bcSAndroid Build Coastguard Worker 	if (ret < 0) {
7854*436bf2bcSAndroid Build Coastguard Worker 		ret = TEP_ERRNO__READ_PRINT_FAILED;
7855*436bf2bcSAndroid Build Coastguard Worker 		goto event_parse_failed;
7856*436bf2bcSAndroid Build Coastguard Worker 	}
7857*436bf2bcSAndroid Build Coastguard Worker 
7858*436bf2bcSAndroid Build Coastguard Worker 	if (!ret && (event->flags & TEP_EVENT_FL_ISFTRACE)) {
7859*436bf2bcSAndroid Build Coastguard Worker 		struct tep_format_field *field;
7860*436bf2bcSAndroid Build Coastguard Worker 		struct tep_print_arg *arg, **list;
7861*436bf2bcSAndroid Build Coastguard Worker 
7862*436bf2bcSAndroid Build Coastguard Worker 		/* old ftrace had no args */
7863*436bf2bcSAndroid Build Coastguard Worker 		list = &event->print_fmt.args;
7864*436bf2bcSAndroid Build Coastguard Worker 		for (field = event->format.fields; field; field = field->next) {
7865*436bf2bcSAndroid Build Coastguard Worker 			arg = alloc_arg();
7866*436bf2bcSAndroid Build Coastguard Worker 			if (!arg) {
7867*436bf2bcSAndroid Build Coastguard Worker 				event->flags |= TEP_EVENT_FL_FAILED;
7868*436bf2bcSAndroid Build Coastguard Worker 				return TEP_ERRNO__OLD_FTRACE_ARG_FAILED;
7869*436bf2bcSAndroid Build Coastguard Worker 			}
7870*436bf2bcSAndroid Build Coastguard Worker 			arg->type = TEP_PRINT_FIELD;
7871*436bf2bcSAndroid Build Coastguard Worker 			arg->field.name = strdup(field->name);
7872*436bf2bcSAndroid Build Coastguard Worker 			if (!arg->field.name) {
7873*436bf2bcSAndroid Build Coastguard Worker 				event->flags |= TEP_EVENT_FL_FAILED;
7874*436bf2bcSAndroid Build Coastguard Worker 				free_arg(arg);
7875*436bf2bcSAndroid Build Coastguard Worker 				return TEP_ERRNO__OLD_FTRACE_ARG_FAILED;
7876*436bf2bcSAndroid Build Coastguard Worker 			}
7877*436bf2bcSAndroid Build Coastguard Worker 			arg->field.field = field;
7878*436bf2bcSAndroid Build Coastguard Worker 			*list = arg;
7879*436bf2bcSAndroid Build Coastguard Worker 			list = &arg->next;
7880*436bf2bcSAndroid Build Coastguard Worker 		}
7881*436bf2bcSAndroid Build Coastguard Worker 	}
7882*436bf2bcSAndroid Build Coastguard Worker 
7883*436bf2bcSAndroid Build Coastguard Worker 	if (!(event->flags & TEP_EVENT_FL_ISBPRINT))
7884*436bf2bcSAndroid Build Coastguard Worker 		event->print_fmt.print_cache = parse_args(event,
7885*436bf2bcSAndroid Build Coastguard Worker 							  event->print_fmt.format,
7886*436bf2bcSAndroid Build Coastguard Worker 							  event->print_fmt.args);
7887*436bf2bcSAndroid Build Coastguard Worker 
7888*436bf2bcSAndroid Build Coastguard Worker 	return 0;
7889*436bf2bcSAndroid Build Coastguard Worker 
7890*436bf2bcSAndroid Build Coastguard Worker  event_parse_failed:
7891*436bf2bcSAndroid Build Coastguard Worker 	event->flags |= TEP_EVENT_FL_FAILED;
7892*436bf2bcSAndroid Build Coastguard Worker 	return ret;
7893*436bf2bcSAndroid Build Coastguard Worker 
7894*436bf2bcSAndroid Build Coastguard Worker  event_alloc_failed:
7895*436bf2bcSAndroid Build Coastguard Worker 	free(event->system);
7896*436bf2bcSAndroid Build Coastguard Worker 	free(event->name);
7897*436bf2bcSAndroid Build Coastguard Worker 	free(event);
7898*436bf2bcSAndroid Build Coastguard Worker 	*eventp = NULL;
7899*436bf2bcSAndroid Build Coastguard Worker 	return ret;
7900*436bf2bcSAndroid Build Coastguard Worker }
7901*436bf2bcSAndroid Build Coastguard Worker 
7902*436bf2bcSAndroid Build Coastguard Worker static enum tep_errno
__parse_event(struct tep_handle * tep,struct tep_event ** eventp,const char * buf,unsigned long size,const char * sys)7903*436bf2bcSAndroid Build Coastguard Worker __parse_event(struct tep_handle *tep,
7904*436bf2bcSAndroid Build Coastguard Worker 	      struct tep_event **eventp,
7905*436bf2bcSAndroid Build Coastguard Worker 	      const char *buf, unsigned long size,
7906*436bf2bcSAndroid Build Coastguard Worker 	      const char *sys)
7907*436bf2bcSAndroid Build Coastguard Worker {
7908*436bf2bcSAndroid Build Coastguard Worker 	int ret = parse_format(eventp, tep, buf, size, sys);
7909*436bf2bcSAndroid Build Coastguard Worker 	struct tep_event *event = *eventp;
7910*436bf2bcSAndroid Build Coastguard Worker 
7911*436bf2bcSAndroid Build Coastguard Worker 	if (event == NULL)
7912*436bf2bcSAndroid Build Coastguard Worker 		return ret;
7913*436bf2bcSAndroid Build Coastguard Worker 
7914*436bf2bcSAndroid Build Coastguard Worker 	if (tep && add_event(tep, event)) {
7915*436bf2bcSAndroid Build Coastguard Worker 		ret = TEP_ERRNO__MEM_ALLOC_FAILED;
7916*436bf2bcSAndroid Build Coastguard Worker 		goto event_add_failed;
7917*436bf2bcSAndroid Build Coastguard Worker 	}
7918*436bf2bcSAndroid Build Coastguard Worker 
7919*436bf2bcSAndroid Build Coastguard Worker #define PRINT_ARGS 0
7920*436bf2bcSAndroid Build Coastguard Worker 	if (PRINT_ARGS && event->print_fmt.args)
7921*436bf2bcSAndroid Build Coastguard Worker 		print_args(event->print_fmt.args);
7922*436bf2bcSAndroid Build Coastguard Worker 
7923*436bf2bcSAndroid Build Coastguard Worker 	return 0;
7924*436bf2bcSAndroid Build Coastguard Worker 
7925*436bf2bcSAndroid Build Coastguard Worker event_add_failed:
7926*436bf2bcSAndroid Build Coastguard Worker 	free_tep_event(event);
7927*436bf2bcSAndroid Build Coastguard Worker 	return ret;
7928*436bf2bcSAndroid Build Coastguard Worker }
7929*436bf2bcSAndroid Build Coastguard Worker 
7930*436bf2bcSAndroid Build Coastguard Worker /**
7931*436bf2bcSAndroid Build Coastguard Worker  * tep_parse_format - parse the event format
7932*436bf2bcSAndroid Build Coastguard Worker  * @tep: a handle to the trace event parser context
7933*436bf2bcSAndroid Build Coastguard Worker  * @eventp: returned format
7934*436bf2bcSAndroid Build Coastguard Worker  * @buf: the buffer storing the event format string
7935*436bf2bcSAndroid Build Coastguard Worker  * @size: the size of @buf
7936*436bf2bcSAndroid Build Coastguard Worker  * @sys: the system the event belongs to
7937*436bf2bcSAndroid Build Coastguard Worker  *
7938*436bf2bcSAndroid Build Coastguard Worker  * This parses the event format and creates an event structure
7939*436bf2bcSAndroid Build Coastguard Worker  * to quickly parse raw data for a given event.
7940*436bf2bcSAndroid Build Coastguard Worker  *
7941*436bf2bcSAndroid Build Coastguard Worker  * These files currently come from:
7942*436bf2bcSAndroid Build Coastguard Worker  *
7943*436bf2bcSAndroid Build Coastguard Worker  * /sys/kernel/debug/tracing/events/.../.../format
7944*436bf2bcSAndroid Build Coastguard Worker  */
tep_parse_format(struct tep_handle * tep,struct tep_event ** eventp,const char * buf,unsigned long size,const char * sys)7945*436bf2bcSAndroid Build Coastguard Worker enum tep_errno tep_parse_format(struct tep_handle *tep,
7946*436bf2bcSAndroid Build Coastguard Worker 				struct tep_event **eventp,
7947*436bf2bcSAndroid Build Coastguard Worker 				const char *buf,
7948*436bf2bcSAndroid Build Coastguard Worker 				unsigned long size, const char *sys)
7949*436bf2bcSAndroid Build Coastguard Worker {
7950*436bf2bcSAndroid Build Coastguard Worker 	return __parse_event(tep, eventp, buf, size, sys);
7951*436bf2bcSAndroid Build Coastguard Worker }
7952*436bf2bcSAndroid Build Coastguard Worker 
7953*436bf2bcSAndroid Build Coastguard Worker /**
7954*436bf2bcSAndroid Build Coastguard Worker  * tep_parse_event - parse the event format
7955*436bf2bcSAndroid Build Coastguard Worker  * @tep: a handle to the trace event parser context
7956*436bf2bcSAndroid Build Coastguard Worker  * @buf: the buffer storing the event format string
7957*436bf2bcSAndroid Build Coastguard Worker  * @size: the size of @buf
7958*436bf2bcSAndroid Build Coastguard Worker  * @sys: the system the event belongs to
7959*436bf2bcSAndroid Build Coastguard Worker  *
7960*436bf2bcSAndroid Build Coastguard Worker  * This parses the event format and creates an event structure
7961*436bf2bcSAndroid Build Coastguard Worker  * to quickly parse raw data for a given event.
7962*436bf2bcSAndroid Build Coastguard Worker  *
7963*436bf2bcSAndroid Build Coastguard Worker  * These files currently come from:
7964*436bf2bcSAndroid Build Coastguard Worker  *
7965*436bf2bcSAndroid Build Coastguard Worker  * /sys/kernel/debug/tracing/events/.../.../format
7966*436bf2bcSAndroid Build Coastguard Worker  */
tep_parse_event(struct tep_handle * tep,const char * buf,unsigned long size,const char * sys)7967*436bf2bcSAndroid Build Coastguard Worker enum tep_errno tep_parse_event(struct tep_handle *tep, const char *buf,
7968*436bf2bcSAndroid Build Coastguard Worker 			       unsigned long size, const char *sys)
7969*436bf2bcSAndroid Build Coastguard Worker {
7970*436bf2bcSAndroid Build Coastguard Worker 	struct tep_event *event = NULL;
7971*436bf2bcSAndroid Build Coastguard Worker 	return __parse_event(tep, &event, buf, size, sys);
7972*436bf2bcSAndroid Build Coastguard Worker }
7973*436bf2bcSAndroid Build Coastguard Worker 
get_field_val(struct trace_seq * s,struct tep_format_field * field,const char * name,struct tep_record * record,unsigned long long * val,int err)7974*436bf2bcSAndroid Build Coastguard Worker int get_field_val(struct trace_seq *s, struct tep_format_field *field,
7975*436bf2bcSAndroid Build Coastguard Worker 		  const char *name, struct tep_record *record,
7976*436bf2bcSAndroid Build Coastguard Worker 		  unsigned long long *val, int err)
7977*436bf2bcSAndroid Build Coastguard Worker {
7978*436bf2bcSAndroid Build Coastguard Worker 	if (!field) {
7979*436bf2bcSAndroid Build Coastguard Worker 		if (err)
7980*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_printf(s, "<CANT FIND FIELD %s>", name);
7981*436bf2bcSAndroid Build Coastguard Worker 		return -1;
7982*436bf2bcSAndroid Build Coastguard Worker 	}
7983*436bf2bcSAndroid Build Coastguard Worker 
7984*436bf2bcSAndroid Build Coastguard Worker 	if (tep_read_number_field(field, record->data, val)) {
7985*436bf2bcSAndroid Build Coastguard Worker 		if (err)
7986*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_printf(s, " %s=INVALID", name);
7987*436bf2bcSAndroid Build Coastguard Worker 		return -1;
7988*436bf2bcSAndroid Build Coastguard Worker 	}
7989*436bf2bcSAndroid Build Coastguard Worker 
7990*436bf2bcSAndroid Build Coastguard Worker 	return 0;
7991*436bf2bcSAndroid Build Coastguard Worker }
7992*436bf2bcSAndroid Build Coastguard Worker 
7993*436bf2bcSAndroid Build Coastguard Worker /**
7994*436bf2bcSAndroid Build Coastguard Worker  * tep_get_field_raw - return the raw pointer into the data field
7995*436bf2bcSAndroid Build Coastguard Worker  * @s: The seq to print to on error
7996*436bf2bcSAndroid Build Coastguard Worker  * @event: the event that the field is for
7997*436bf2bcSAndroid Build Coastguard Worker  * @name: The name of the field
7998*436bf2bcSAndroid Build Coastguard Worker  * @record: The record with the field name.
7999*436bf2bcSAndroid Build Coastguard Worker  * @len: place to store the field length.
8000*436bf2bcSAndroid Build Coastguard Worker  * @err: print default error if failed.
8001*436bf2bcSAndroid Build Coastguard Worker  *
8002*436bf2bcSAndroid Build Coastguard Worker  * Returns a pointer into record->data of the field and places
8003*436bf2bcSAndroid Build Coastguard Worker  * the length of the field in @len.
8004*436bf2bcSAndroid Build Coastguard Worker  *
8005*436bf2bcSAndroid Build Coastguard Worker  * On failure, it returns NULL.
8006*436bf2bcSAndroid Build Coastguard Worker  */
tep_get_field_raw(struct trace_seq * s,struct tep_event * event,const char * name,struct tep_record * record,int * len,int err)8007*436bf2bcSAndroid Build Coastguard Worker void *tep_get_field_raw(struct trace_seq *s, struct tep_event *event,
8008*436bf2bcSAndroid Build Coastguard Worker 			const char *name, struct tep_record *record,
8009*436bf2bcSAndroid Build Coastguard Worker 			int *len, int err)
8010*436bf2bcSAndroid Build Coastguard Worker {
8011*436bf2bcSAndroid Build Coastguard Worker 	struct tep_format_field *field;
8012*436bf2bcSAndroid Build Coastguard Worker 	void *data = record->data;
8013*436bf2bcSAndroid Build Coastguard Worker 	unsigned offset;
8014*436bf2bcSAndroid Build Coastguard Worker 	int dummy;
8015*436bf2bcSAndroid Build Coastguard Worker 
8016*436bf2bcSAndroid Build Coastguard Worker 	if (!event)
8017*436bf2bcSAndroid Build Coastguard Worker 		return NULL;
8018*436bf2bcSAndroid Build Coastguard Worker 
8019*436bf2bcSAndroid Build Coastguard Worker 	field = tep_find_field(event, name);
8020*436bf2bcSAndroid Build Coastguard Worker 
8021*436bf2bcSAndroid Build Coastguard Worker 	if (!field) {
8022*436bf2bcSAndroid Build Coastguard Worker 		if (err)
8023*436bf2bcSAndroid Build Coastguard Worker 			trace_seq_printf(s, "<CANT FIND FIELD %s>", name);
8024*436bf2bcSAndroid Build Coastguard Worker 		return NULL;
8025*436bf2bcSAndroid Build Coastguard Worker 	}
8026*436bf2bcSAndroid Build Coastguard Worker 
8027*436bf2bcSAndroid Build Coastguard Worker 	/* Allow @len to be NULL */
8028*436bf2bcSAndroid Build Coastguard Worker 	if (!len)
8029*436bf2bcSAndroid Build Coastguard Worker 		len = &dummy;
8030*436bf2bcSAndroid Build Coastguard Worker 
8031*436bf2bcSAndroid Build Coastguard Worker 	offset = field->offset;
8032*436bf2bcSAndroid Build Coastguard Worker 	if (field->flags & TEP_FIELD_IS_DYNAMIC) {
8033*436bf2bcSAndroid Build Coastguard Worker 		offset = tep_read_number(event->tep,
8034*436bf2bcSAndroid Build Coastguard Worker 					 data + offset, field->size);
8035*436bf2bcSAndroid Build Coastguard Worker 		*len = offset >> 16;
8036*436bf2bcSAndroid Build Coastguard Worker 		offset &= 0xffff;
8037*436bf2bcSAndroid Build Coastguard Worker 		if (field->flags & TEP_FIELD_IS_RELATIVE)
8038*436bf2bcSAndroid Build Coastguard Worker 			offset += field->offset + field->size;
8039*436bf2bcSAndroid Build Coastguard Worker 	} else
8040*436bf2bcSAndroid Build Coastguard Worker 		*len = field->size;
8041*436bf2bcSAndroid Build Coastguard Worker 
8042*436bf2bcSAndroid Build Coastguard Worker 	return data + offset;
8043*436bf2bcSAndroid Build Coastguard Worker }
8044*436bf2bcSAndroid Build Coastguard Worker 
8045*436bf2bcSAndroid Build Coastguard Worker /**
8046*436bf2bcSAndroid Build Coastguard Worker  * tep_get_field_val - find a field and return its value
8047*436bf2bcSAndroid Build Coastguard Worker  * @s: The seq to print to on error
8048*436bf2bcSAndroid Build Coastguard Worker  * @event: the event that the field is for
8049*436bf2bcSAndroid Build Coastguard Worker  * @name: The name of the field
8050*436bf2bcSAndroid Build Coastguard Worker  * @record: The record with the field name.
8051*436bf2bcSAndroid Build Coastguard Worker  * @val: place to store the value of the field.
8052*436bf2bcSAndroid Build Coastguard Worker  * @err: print default error if failed.
8053*436bf2bcSAndroid Build Coastguard Worker  *
8054*436bf2bcSAndroid Build Coastguard Worker  * Returns 0 on success -1 on field not found.
8055*436bf2bcSAndroid Build Coastguard Worker  */
tep_get_field_val(struct trace_seq * s,struct tep_event * event,const char * name,struct tep_record * record,unsigned long long * val,int err)8056*436bf2bcSAndroid Build Coastguard Worker int tep_get_field_val(struct trace_seq *s, struct tep_event *event,
8057*436bf2bcSAndroid Build Coastguard Worker 		      const char *name, struct tep_record *record,
8058*436bf2bcSAndroid Build Coastguard Worker 		      unsigned long long *val, int err)
8059*436bf2bcSAndroid Build Coastguard Worker {
8060*436bf2bcSAndroid Build Coastguard Worker 	struct tep_format_field *field;
8061*436bf2bcSAndroid Build Coastguard Worker 
8062*436bf2bcSAndroid Build Coastguard Worker 	if (!event)
8063*436bf2bcSAndroid Build Coastguard Worker 		return -1;
8064*436bf2bcSAndroid Build Coastguard Worker 
8065*436bf2bcSAndroid Build Coastguard Worker 	field = tep_find_field(event, name);
8066*436bf2bcSAndroid Build Coastguard Worker 
8067*436bf2bcSAndroid Build Coastguard Worker 	return get_field_val(s, field, name, record, val, err);
8068*436bf2bcSAndroid Build Coastguard Worker }
8069*436bf2bcSAndroid Build Coastguard Worker 
8070*436bf2bcSAndroid Build Coastguard Worker /**
8071*436bf2bcSAndroid Build Coastguard Worker  * tep_get_common_field_val - find a common field and return its value
8072*436bf2bcSAndroid Build Coastguard Worker  * @s: The seq to print to on error
8073*436bf2bcSAndroid Build Coastguard Worker  * @event: the event that the field is for
8074*436bf2bcSAndroid Build Coastguard Worker  * @name: The name of the field
8075*436bf2bcSAndroid Build Coastguard Worker  * @record: The record with the field name.
8076*436bf2bcSAndroid Build Coastguard Worker  * @val: place to store the value of the field.
8077*436bf2bcSAndroid Build Coastguard Worker  * @err: print default error if failed.
8078*436bf2bcSAndroid Build Coastguard Worker  *
8079*436bf2bcSAndroid Build Coastguard Worker  * Returns 0 on success -1 on field not found.
8080*436bf2bcSAndroid Build Coastguard Worker  */
tep_get_common_field_val(struct trace_seq * s,struct tep_event * event,const char * name,struct tep_record * record,unsigned long long * val,int err)8081*436bf2bcSAndroid Build Coastguard Worker int tep_get_common_field_val(struct trace_seq *s, struct tep_event *event,
8082*436bf2bcSAndroid Build Coastguard Worker 			     const char *name, struct tep_record *record,
8083*436bf2bcSAndroid Build Coastguard Worker 			     unsigned long long *val, int err)
8084*436bf2bcSAndroid Build Coastguard Worker {
8085*436bf2bcSAndroid Build Coastguard Worker 	struct tep_format_field *field;
8086*436bf2bcSAndroid Build Coastguard Worker 
8087*436bf2bcSAndroid Build Coastguard Worker 	if (!event)
8088*436bf2bcSAndroid Build Coastguard Worker 		return -1;
8089*436bf2bcSAndroid Build Coastguard Worker 
8090*436bf2bcSAndroid Build Coastguard Worker 	field = tep_find_common_field(event, name);
8091*436bf2bcSAndroid Build Coastguard Worker 
8092*436bf2bcSAndroid Build Coastguard Worker 	return get_field_val(s, field, name, record, val, err);
8093*436bf2bcSAndroid Build Coastguard Worker }
8094*436bf2bcSAndroid Build Coastguard Worker 
8095*436bf2bcSAndroid Build Coastguard Worker /**
8096*436bf2bcSAndroid Build Coastguard Worker  * tep_get_any_field_val - find a any field and return its value
8097*436bf2bcSAndroid Build Coastguard Worker  * @s: The seq to print to on error
8098*436bf2bcSAndroid Build Coastguard Worker  * @event: the event that the field is for
8099*436bf2bcSAndroid Build Coastguard Worker  * @name: The name of the field
8100*436bf2bcSAndroid Build Coastguard Worker  * @record: The record with the field name.
8101*436bf2bcSAndroid Build Coastguard Worker  * @val: place to store the value of the field.
8102*436bf2bcSAndroid Build Coastguard Worker  * @err: print default error if failed.
8103*436bf2bcSAndroid Build Coastguard Worker  *
8104*436bf2bcSAndroid Build Coastguard Worker  * Returns 0 on success -1 on field not found.
8105*436bf2bcSAndroid Build Coastguard Worker  */
tep_get_any_field_val(struct trace_seq * s,struct tep_event * event,const char * name,struct tep_record * record,unsigned long long * val,int err)8106*436bf2bcSAndroid Build Coastguard Worker int tep_get_any_field_val(struct trace_seq *s, struct tep_event *event,
8107*436bf2bcSAndroid Build Coastguard Worker 			  const char *name, struct tep_record *record,
8108*436bf2bcSAndroid Build Coastguard Worker 			  unsigned long long *val, int err)
8109*436bf2bcSAndroid Build Coastguard Worker {
8110*436bf2bcSAndroid Build Coastguard Worker 	struct tep_format_field *field;
8111*436bf2bcSAndroid Build Coastguard Worker 
8112*436bf2bcSAndroid Build Coastguard Worker 	if (!event)
8113*436bf2bcSAndroid Build Coastguard Worker 		return -1;
8114*436bf2bcSAndroid Build Coastguard Worker 
8115*436bf2bcSAndroid Build Coastguard Worker 	field = tep_find_any_field(event, name);
8116*436bf2bcSAndroid Build Coastguard Worker 
8117*436bf2bcSAndroid Build Coastguard Worker 	return get_field_val(s, field, name, record, val, err);
8118*436bf2bcSAndroid Build Coastguard Worker }
8119*436bf2bcSAndroid Build Coastguard Worker 
8120*436bf2bcSAndroid Build Coastguard Worker /**
8121*436bf2bcSAndroid Build Coastguard Worker  * tep_print_num_field - print a field and a format
8122*436bf2bcSAndroid Build Coastguard Worker  * @s: The seq to print to
8123*436bf2bcSAndroid Build Coastguard Worker  * @fmt: The printf format to print the field with.
8124*436bf2bcSAndroid Build Coastguard Worker  * @event: the event that the field is for
8125*436bf2bcSAndroid Build Coastguard Worker  * @name: The name of the field
8126*436bf2bcSAndroid Build Coastguard Worker  * @record: The record with the field name.
8127*436bf2bcSAndroid Build Coastguard Worker  * @err: print default error if failed.
8128*436bf2bcSAndroid Build Coastguard Worker  *
8129*436bf2bcSAndroid Build Coastguard Worker  * Returns positive value on success, negative in case of an error,
8130*436bf2bcSAndroid Build Coastguard Worker  * or 0 if buffer is full.
8131*436bf2bcSAndroid Build Coastguard Worker  */
tep_print_num_field(struct trace_seq * s,const char * fmt,struct tep_event * event,const char * name,struct tep_record * record,int err)8132*436bf2bcSAndroid Build Coastguard Worker int tep_print_num_field(struct trace_seq *s, const char *fmt,
8133*436bf2bcSAndroid Build Coastguard Worker 			struct tep_event *event, const char *name,
8134*436bf2bcSAndroid Build Coastguard Worker 			struct tep_record *record, int err)
8135*436bf2bcSAndroid Build Coastguard Worker {
8136*436bf2bcSAndroid Build Coastguard Worker 	struct tep_format_field *field = tep_find_field(event, name);
8137*436bf2bcSAndroid Build Coastguard Worker 	unsigned long long val;
8138*436bf2bcSAndroid Build Coastguard Worker 
8139*436bf2bcSAndroid Build Coastguard Worker 	if (!field)
8140*436bf2bcSAndroid Build Coastguard Worker 		goto failed;
8141*436bf2bcSAndroid Build Coastguard Worker 
8142*436bf2bcSAndroid Build Coastguard Worker 	if (tep_read_number_field(field, record->data, &val))
8143*436bf2bcSAndroid Build Coastguard Worker 		goto failed;
8144*436bf2bcSAndroid Build Coastguard Worker 
8145*436bf2bcSAndroid Build Coastguard Worker 	return trace_seq_printf(s, fmt, val);
8146*436bf2bcSAndroid Build Coastguard Worker 
8147*436bf2bcSAndroid Build Coastguard Worker  failed:
8148*436bf2bcSAndroid Build Coastguard Worker 	if (err)
8149*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_printf(s, "CAN'T FIND FIELD \"%s\"", name);
8150*436bf2bcSAndroid Build Coastguard Worker 	return -1;
8151*436bf2bcSAndroid Build Coastguard Worker }
8152*436bf2bcSAndroid Build Coastguard Worker 
8153*436bf2bcSAndroid Build Coastguard Worker /**
8154*436bf2bcSAndroid Build Coastguard Worker  * tep_print_func_field - print a field and a format for function pointers
8155*436bf2bcSAndroid Build Coastguard Worker  * @s: The seq to print to
8156*436bf2bcSAndroid Build Coastguard Worker  * @fmt: The printf format to print the field with.
8157*436bf2bcSAndroid Build Coastguard Worker  * @event: the event that the field is for
8158*436bf2bcSAndroid Build Coastguard Worker  * @name: The name of the field
8159*436bf2bcSAndroid Build Coastguard Worker  * @record: The record with the field name.
8160*436bf2bcSAndroid Build Coastguard Worker  * @err: print default error if failed.
8161*436bf2bcSAndroid Build Coastguard Worker  *
8162*436bf2bcSAndroid Build Coastguard Worker  * Returns positive value on success, negative in case of an error,
8163*436bf2bcSAndroid Build Coastguard Worker  * or 0 if buffer is full.
8164*436bf2bcSAndroid Build Coastguard Worker  */
tep_print_func_field(struct trace_seq * s,const char * fmt,struct tep_event * event,const char * name,struct tep_record * record,int err)8165*436bf2bcSAndroid Build Coastguard Worker int tep_print_func_field(struct trace_seq *s, const char *fmt,
8166*436bf2bcSAndroid Build Coastguard Worker 			 struct tep_event *event, const char *name,
8167*436bf2bcSAndroid Build Coastguard Worker 			 struct tep_record *record, int err)
8168*436bf2bcSAndroid Build Coastguard Worker {
8169*436bf2bcSAndroid Build Coastguard Worker 	struct tep_format_field *field = tep_find_field(event, name);
8170*436bf2bcSAndroid Build Coastguard Worker 	struct tep_handle *tep = event->tep;
8171*436bf2bcSAndroid Build Coastguard Worker 	unsigned long long val;
8172*436bf2bcSAndroid Build Coastguard Worker 	struct func_map *func;
8173*436bf2bcSAndroid Build Coastguard Worker 	char tmp[128];
8174*436bf2bcSAndroid Build Coastguard Worker 
8175*436bf2bcSAndroid Build Coastguard Worker 	if (!field)
8176*436bf2bcSAndroid Build Coastguard Worker 		goto failed;
8177*436bf2bcSAndroid Build Coastguard Worker 
8178*436bf2bcSAndroid Build Coastguard Worker 	if (tep_read_number_field(field, record->data, &val))
8179*436bf2bcSAndroid Build Coastguard Worker 		goto failed;
8180*436bf2bcSAndroid Build Coastguard Worker 
8181*436bf2bcSAndroid Build Coastguard Worker 	func = find_func(tep, val);
8182*436bf2bcSAndroid Build Coastguard Worker 
8183*436bf2bcSAndroid Build Coastguard Worker 	if (func)
8184*436bf2bcSAndroid Build Coastguard Worker 		snprintf(tmp, 128, "%s/0x%llx", func->func, func->addr - val);
8185*436bf2bcSAndroid Build Coastguard Worker 	else
8186*436bf2bcSAndroid Build Coastguard Worker 		sprintf(tmp, "0x%08llx", val);
8187*436bf2bcSAndroid Build Coastguard Worker 
8188*436bf2bcSAndroid Build Coastguard Worker 	return trace_seq_printf(s, fmt, tmp);
8189*436bf2bcSAndroid Build Coastguard Worker 
8190*436bf2bcSAndroid Build Coastguard Worker  failed:
8191*436bf2bcSAndroid Build Coastguard Worker 	if (err)
8192*436bf2bcSAndroid Build Coastguard Worker 		trace_seq_printf(s, "CAN'T FIND FIELD \"%s\"", name);
8193*436bf2bcSAndroid Build Coastguard Worker 	return -1;
8194*436bf2bcSAndroid Build Coastguard Worker }
8195*436bf2bcSAndroid Build Coastguard Worker 
free_func_handle(struct tep_function_handler * func)8196*436bf2bcSAndroid Build Coastguard Worker static void free_func_handle(struct tep_function_handler *func)
8197*436bf2bcSAndroid Build Coastguard Worker {
8198*436bf2bcSAndroid Build Coastguard Worker 	struct func_params *params;
8199*436bf2bcSAndroid Build Coastguard Worker 
8200*436bf2bcSAndroid Build Coastguard Worker 	free(func->name);
8201*436bf2bcSAndroid Build Coastguard Worker 
8202*436bf2bcSAndroid Build Coastguard Worker 	while (func->params) {
8203*436bf2bcSAndroid Build Coastguard Worker 		params = func->params;
8204*436bf2bcSAndroid Build Coastguard Worker 		func->params = params->next;
8205*436bf2bcSAndroid Build Coastguard Worker 		free(params);
8206*436bf2bcSAndroid Build Coastguard Worker 	}
8207*436bf2bcSAndroid Build Coastguard Worker 
8208*436bf2bcSAndroid Build Coastguard Worker 	free(func);
8209*436bf2bcSAndroid Build Coastguard Worker }
8210*436bf2bcSAndroid Build Coastguard Worker 
8211*436bf2bcSAndroid Build Coastguard Worker /**
8212*436bf2bcSAndroid Build Coastguard Worker  * tep_register_print_function - register a helper function
8213*436bf2bcSAndroid Build Coastguard Worker  * @tep: a handle to the trace event parser context
8214*436bf2bcSAndroid Build Coastguard Worker  * @func: the function to process the helper function
8215*436bf2bcSAndroid Build Coastguard Worker  * @ret_type: the return type of the helper function
8216*436bf2bcSAndroid Build Coastguard Worker  * @name: the name of the helper function
8217*436bf2bcSAndroid Build Coastguard Worker  * @parameters: A list of enum tep_func_arg_type
8218*436bf2bcSAndroid Build Coastguard Worker  *
8219*436bf2bcSAndroid Build Coastguard Worker  * Some events may have helper functions in the print format arguments.
8220*436bf2bcSAndroid Build Coastguard Worker  * This allows a plugin to dynamically create a way to process one
8221*436bf2bcSAndroid Build Coastguard Worker  * of these functions.
8222*436bf2bcSAndroid Build Coastguard Worker  *
8223*436bf2bcSAndroid Build Coastguard Worker  * The @parameters is a variable list of tep_func_arg_type enums that
8224*436bf2bcSAndroid Build Coastguard Worker  * must end with TEP_FUNC_ARG_VOID.
8225*436bf2bcSAndroid Build Coastguard Worker  */
tep_register_print_function(struct tep_handle * tep,tep_func_handler func,enum tep_func_arg_type ret_type,char * name,...)8226*436bf2bcSAndroid Build Coastguard Worker int tep_register_print_function(struct tep_handle *tep,
8227*436bf2bcSAndroid Build Coastguard Worker 				tep_func_handler func,
8228*436bf2bcSAndroid Build Coastguard Worker 				enum tep_func_arg_type ret_type,
8229*436bf2bcSAndroid Build Coastguard Worker 				char *name, ...)
8230*436bf2bcSAndroid Build Coastguard Worker {
8231*436bf2bcSAndroid Build Coastguard Worker 	struct tep_function_handler *func_handle;
8232*436bf2bcSAndroid Build Coastguard Worker 	struct func_params **next_param;
8233*436bf2bcSAndroid Build Coastguard Worker 	struct func_params *param;
8234*436bf2bcSAndroid Build Coastguard Worker 	enum tep_func_arg_type type;
8235*436bf2bcSAndroid Build Coastguard Worker 	va_list ap;
8236*436bf2bcSAndroid Build Coastguard Worker 	int ret;
8237*436bf2bcSAndroid Build Coastguard Worker 
8238*436bf2bcSAndroid Build Coastguard Worker 	func_handle = find_func_handler(tep, name);
8239*436bf2bcSAndroid Build Coastguard Worker 	if (func_handle) {
8240*436bf2bcSAndroid Build Coastguard Worker 		/*
8241*436bf2bcSAndroid Build Coastguard Worker 		 * This is most like caused by the users own
8242*436bf2bcSAndroid Build Coastguard Worker 		 * plugins updating the function. This overrides the
8243*436bf2bcSAndroid Build Coastguard Worker 		 * system defaults.
8244*436bf2bcSAndroid Build Coastguard Worker 		 */
8245*436bf2bcSAndroid Build Coastguard Worker 		tep_info("override of function helper '%s'", name);
8246*436bf2bcSAndroid Build Coastguard Worker 		remove_func_handler(tep, name);
8247*436bf2bcSAndroid Build Coastguard Worker 	}
8248*436bf2bcSAndroid Build Coastguard Worker 
8249*436bf2bcSAndroid Build Coastguard Worker 	func_handle = calloc(1, sizeof(*func_handle));
8250*436bf2bcSAndroid Build Coastguard Worker 	if (!func_handle) {
8251*436bf2bcSAndroid Build Coastguard Worker 		do_warning("Failed to allocate function handler");
8252*436bf2bcSAndroid Build Coastguard Worker 		return TEP_ERRNO__MEM_ALLOC_FAILED;
8253*436bf2bcSAndroid Build Coastguard Worker 	}
8254*436bf2bcSAndroid Build Coastguard Worker 
8255*436bf2bcSAndroid Build Coastguard Worker 	func_handle->ret_type = ret_type;
8256*436bf2bcSAndroid Build Coastguard Worker 	func_handle->name = strdup(name);
8257*436bf2bcSAndroid Build Coastguard Worker 	func_handle->func = func;
8258*436bf2bcSAndroid Build Coastguard Worker 	if (!func_handle->name) {
8259*436bf2bcSAndroid Build Coastguard Worker 		do_warning("Failed to allocate function name");
8260*436bf2bcSAndroid Build Coastguard Worker 		free(func_handle);
8261*436bf2bcSAndroid Build Coastguard Worker 		return TEP_ERRNO__MEM_ALLOC_FAILED;
8262*436bf2bcSAndroid Build Coastguard Worker 	}
8263*436bf2bcSAndroid Build Coastguard Worker 
8264*436bf2bcSAndroid Build Coastguard Worker 	next_param = &(func_handle->params);
8265*436bf2bcSAndroid Build Coastguard Worker 	va_start(ap, name);
8266*436bf2bcSAndroid Build Coastguard Worker 	for (;;) {
8267*436bf2bcSAndroid Build Coastguard Worker 		type = va_arg(ap, enum tep_func_arg_type);
8268*436bf2bcSAndroid Build Coastguard Worker 		if (type == TEP_FUNC_ARG_VOID)
8269*436bf2bcSAndroid Build Coastguard Worker 			break;
8270*436bf2bcSAndroid Build Coastguard Worker 
8271*436bf2bcSAndroid Build Coastguard Worker 		if (type >= TEP_FUNC_ARG_MAX_TYPES) {
8272*436bf2bcSAndroid Build Coastguard Worker 			do_warning("Invalid argument type %d", type);
8273*436bf2bcSAndroid Build Coastguard Worker 			ret = TEP_ERRNO__INVALID_ARG_TYPE;
8274*436bf2bcSAndroid Build Coastguard Worker 			goto out_free;
8275*436bf2bcSAndroid Build Coastguard Worker 		}
8276*436bf2bcSAndroid Build Coastguard Worker 
8277*436bf2bcSAndroid Build Coastguard Worker 		param = malloc(sizeof(*param));
8278*436bf2bcSAndroid Build Coastguard Worker 		if (!param) {
8279*436bf2bcSAndroid Build Coastguard Worker 			do_warning("Failed to allocate function param");
8280*436bf2bcSAndroid Build Coastguard Worker 			ret = TEP_ERRNO__MEM_ALLOC_FAILED;
8281*436bf2bcSAndroid Build Coastguard Worker 			goto out_free;
8282*436bf2bcSAndroid Build Coastguard Worker 		}
8283*436bf2bcSAndroid Build Coastguard Worker 		param->type = type;
8284*436bf2bcSAndroid Build Coastguard Worker 		param->next = NULL;
8285*436bf2bcSAndroid Build Coastguard Worker 
8286*436bf2bcSAndroid Build Coastguard Worker 		*next_param = param;
8287*436bf2bcSAndroid Build Coastguard Worker 		next_param = &(param->next);
8288*436bf2bcSAndroid Build Coastguard Worker 
8289*436bf2bcSAndroid Build Coastguard Worker 		func_handle->nr_args++;
8290*436bf2bcSAndroid Build Coastguard Worker 	}
8291*436bf2bcSAndroid Build Coastguard Worker 	va_end(ap);
8292*436bf2bcSAndroid Build Coastguard Worker 
8293*436bf2bcSAndroid Build Coastguard Worker 	func_handle->next = tep->func_handlers;
8294*436bf2bcSAndroid Build Coastguard Worker 	tep->func_handlers = func_handle;
8295*436bf2bcSAndroid Build Coastguard Worker 
8296*436bf2bcSAndroid Build Coastguard Worker 	return 0;
8297*436bf2bcSAndroid Build Coastguard Worker  out_free:
8298*436bf2bcSAndroid Build Coastguard Worker 	va_end(ap);
8299*436bf2bcSAndroid Build Coastguard Worker 	free_func_handle(func_handle);
8300*436bf2bcSAndroid Build Coastguard Worker 	return ret;
8301*436bf2bcSAndroid Build Coastguard Worker }
8302*436bf2bcSAndroid Build Coastguard Worker 
8303*436bf2bcSAndroid Build Coastguard Worker /**
8304*436bf2bcSAndroid Build Coastguard Worker  * tep_unregister_print_function - unregister a helper function
8305*436bf2bcSAndroid Build Coastguard Worker  * @tep: a handle to the trace event parser context
8306*436bf2bcSAndroid Build Coastguard Worker  * @func: the function to process the helper function
8307*436bf2bcSAndroid Build Coastguard Worker  * @name: the name of the helper function
8308*436bf2bcSAndroid Build Coastguard Worker  *
8309*436bf2bcSAndroid Build Coastguard Worker  * This function removes existing print handler for function @name.
8310*436bf2bcSAndroid Build Coastguard Worker  *
8311*436bf2bcSAndroid Build Coastguard Worker  * Returns 0 if the handler was removed successully, -1 otherwise.
8312*436bf2bcSAndroid Build Coastguard Worker  */
tep_unregister_print_function(struct tep_handle * tep,tep_func_handler func,char * name)8313*436bf2bcSAndroid Build Coastguard Worker int tep_unregister_print_function(struct tep_handle *tep,
8314*436bf2bcSAndroid Build Coastguard Worker 				  tep_func_handler func, char *name)
8315*436bf2bcSAndroid Build Coastguard Worker {
8316*436bf2bcSAndroid Build Coastguard Worker 	struct tep_function_handler *func_handle;
8317*436bf2bcSAndroid Build Coastguard Worker 
8318*436bf2bcSAndroid Build Coastguard Worker 	func_handle = find_func_handler(tep, name);
8319*436bf2bcSAndroid Build Coastguard Worker 	if (func_handle && func_handle->func == func) {
8320*436bf2bcSAndroid Build Coastguard Worker 		remove_func_handler(tep, name);
8321*436bf2bcSAndroid Build Coastguard Worker 		return 0;
8322*436bf2bcSAndroid Build Coastguard Worker 	}
8323*436bf2bcSAndroid Build Coastguard Worker 	return -1;
8324*436bf2bcSAndroid Build Coastguard Worker }
8325*436bf2bcSAndroid Build Coastguard Worker 
search_event(struct tep_handle * tep,int id,const char * sys_name,const char * event_name)8326*436bf2bcSAndroid Build Coastguard Worker static struct tep_event *search_event(struct tep_handle *tep, int id,
8327*436bf2bcSAndroid Build Coastguard Worker 				      const char *sys_name,
8328*436bf2bcSAndroid Build Coastguard Worker 				      const char *event_name)
8329*436bf2bcSAndroid Build Coastguard Worker {
8330*436bf2bcSAndroid Build Coastguard Worker 	struct tep_event *event;
8331*436bf2bcSAndroid Build Coastguard Worker 
8332*436bf2bcSAndroid Build Coastguard Worker 	if (id >= 0) {
8333*436bf2bcSAndroid Build Coastguard Worker 		/* search by id */
8334*436bf2bcSAndroid Build Coastguard Worker 		event = tep_find_event(tep, id);
8335*436bf2bcSAndroid Build Coastguard Worker 		if (!event)
8336*436bf2bcSAndroid Build Coastguard Worker 			return NULL;
8337*436bf2bcSAndroid Build Coastguard Worker 		if (event_name && (strcmp(event_name, event->name) != 0))
8338*436bf2bcSAndroid Build Coastguard Worker 			return NULL;
8339*436bf2bcSAndroid Build Coastguard Worker 		if (sys_name && (strcmp(sys_name, event->system) != 0))
8340*436bf2bcSAndroid Build Coastguard Worker 			return NULL;
8341*436bf2bcSAndroid Build Coastguard Worker 	} else {
8342*436bf2bcSAndroid Build Coastguard Worker 		event = tep_find_event_by_name(tep, sys_name, event_name);
8343*436bf2bcSAndroid Build Coastguard Worker 		if (!event)
8344*436bf2bcSAndroid Build Coastguard Worker 			return NULL;
8345*436bf2bcSAndroid Build Coastguard Worker 	}
8346*436bf2bcSAndroid Build Coastguard Worker 	return event;
8347*436bf2bcSAndroid Build Coastguard Worker }
8348*436bf2bcSAndroid Build Coastguard Worker 
8349*436bf2bcSAndroid Build Coastguard Worker /**
8350*436bf2bcSAndroid Build Coastguard Worker  * tep_register_event_handler - register a way to parse an event
8351*436bf2bcSAndroid Build Coastguard Worker  * @tep: a handle to the trace event parser context
8352*436bf2bcSAndroid Build Coastguard Worker  * @id: the id of the event to register
8353*436bf2bcSAndroid Build Coastguard Worker  * @sys_name: the system name the event belongs to
8354*436bf2bcSAndroid Build Coastguard Worker  * @event_name: the name of the event
8355*436bf2bcSAndroid Build Coastguard Worker  * @func: the function to call to parse the event information
8356*436bf2bcSAndroid Build Coastguard Worker  * @context: the data to be passed to @func
8357*436bf2bcSAndroid Build Coastguard Worker  *
8358*436bf2bcSAndroid Build Coastguard Worker  * This function allows a developer to override the parsing of
8359*436bf2bcSAndroid Build Coastguard Worker  * a given event. If for some reason the default print format
8360*436bf2bcSAndroid Build Coastguard Worker  * is not sufficient, this function will register a function
8361*436bf2bcSAndroid Build Coastguard Worker  * for an event to be used to parse the data instead.
8362*436bf2bcSAndroid Build Coastguard Worker  *
8363*436bf2bcSAndroid Build Coastguard Worker  * If @id is >= 0, then it is used to find the event.
8364*436bf2bcSAndroid Build Coastguard Worker  * else @sys_name and @event_name are used.
8365*436bf2bcSAndroid Build Coastguard Worker  *
8366*436bf2bcSAndroid Build Coastguard Worker  * Returns:
8367*436bf2bcSAndroid Build Coastguard Worker  *  TEP_REGISTER_SUCCESS_OVERWRITE if an existing handler is overwritten
8368*436bf2bcSAndroid Build Coastguard Worker  *  TEP_REGISTER_SUCCESS if a new handler is registered successfully
8369*436bf2bcSAndroid Build Coastguard Worker  *  negative TEP_ERRNO_... in case of an error
8370*436bf2bcSAndroid Build Coastguard Worker  *
8371*436bf2bcSAndroid Build Coastguard Worker  */
tep_register_event_handler(struct tep_handle * tep,int id,const char * sys_name,const char * event_name,tep_event_handler_func func,void * context)8372*436bf2bcSAndroid Build Coastguard Worker int tep_register_event_handler(struct tep_handle *tep, int id,
8373*436bf2bcSAndroid Build Coastguard Worker 			       const char *sys_name, const char *event_name,
8374*436bf2bcSAndroid Build Coastguard Worker 			       tep_event_handler_func func, void *context)
8375*436bf2bcSAndroid Build Coastguard Worker {
8376*436bf2bcSAndroid Build Coastguard Worker 	struct tep_event *event;
8377*436bf2bcSAndroid Build Coastguard Worker 	struct event_handler *handle;
8378*436bf2bcSAndroid Build Coastguard Worker 
8379*436bf2bcSAndroid Build Coastguard Worker 	event = search_event(tep, id, sys_name, event_name);
8380*436bf2bcSAndroid Build Coastguard Worker 	if (event == NULL)
8381*436bf2bcSAndroid Build Coastguard Worker 		goto not_found;
8382*436bf2bcSAndroid Build Coastguard Worker 
8383*436bf2bcSAndroid Build Coastguard Worker 	tep_info("overriding event (%d) %s:%s with new print handler",
8384*436bf2bcSAndroid Build Coastguard Worker 		 event->id, event->system, event->name);
8385*436bf2bcSAndroid Build Coastguard Worker 
8386*436bf2bcSAndroid Build Coastguard Worker 	event->handler = func;
8387*436bf2bcSAndroid Build Coastguard Worker 	event->context = context;
8388*436bf2bcSAndroid Build Coastguard Worker 	return TEP_REGISTER_SUCCESS_OVERWRITE;
8389*436bf2bcSAndroid Build Coastguard Worker 
8390*436bf2bcSAndroid Build Coastguard Worker  not_found:
8391*436bf2bcSAndroid Build Coastguard Worker 	/* Save for later use. */
8392*436bf2bcSAndroid Build Coastguard Worker 	handle = calloc(1, sizeof(*handle));
8393*436bf2bcSAndroid Build Coastguard Worker 	if (!handle) {
8394*436bf2bcSAndroid Build Coastguard Worker 		do_warning("Failed to allocate event handler");
8395*436bf2bcSAndroid Build Coastguard Worker 		return TEP_ERRNO__MEM_ALLOC_FAILED;
8396*436bf2bcSAndroid Build Coastguard Worker 	}
8397*436bf2bcSAndroid Build Coastguard Worker 
8398*436bf2bcSAndroid Build Coastguard Worker 	handle->id = id;
8399*436bf2bcSAndroid Build Coastguard Worker 	if (event_name)
8400*436bf2bcSAndroid Build Coastguard Worker 		handle->event_name = strdup(event_name);
8401*436bf2bcSAndroid Build Coastguard Worker 	if (sys_name)
8402*436bf2bcSAndroid Build Coastguard Worker 		handle->sys_name = strdup(sys_name);
8403*436bf2bcSAndroid Build Coastguard Worker 
8404*436bf2bcSAndroid Build Coastguard Worker 	if ((event_name && !handle->event_name) ||
8405*436bf2bcSAndroid Build Coastguard Worker 	    (sys_name && !handle->sys_name)) {
8406*436bf2bcSAndroid Build Coastguard Worker 		do_warning("Failed to allocate event/sys name");
8407*436bf2bcSAndroid Build Coastguard Worker 		free((void *)handle->event_name);
8408*436bf2bcSAndroid Build Coastguard Worker 		free((void *)handle->sys_name);
8409*436bf2bcSAndroid Build Coastguard Worker 		free(handle);
8410*436bf2bcSAndroid Build Coastguard Worker 		return TEP_ERRNO__MEM_ALLOC_FAILED;
8411*436bf2bcSAndroid Build Coastguard Worker 	}
8412*436bf2bcSAndroid Build Coastguard Worker 
8413*436bf2bcSAndroid Build Coastguard Worker 	handle->func = func;
8414*436bf2bcSAndroid Build Coastguard Worker 	handle->next = tep->handlers;
8415*436bf2bcSAndroid Build Coastguard Worker 	tep->handlers = handle;
8416*436bf2bcSAndroid Build Coastguard Worker 	handle->context = context;
8417*436bf2bcSAndroid Build Coastguard Worker 
8418*436bf2bcSAndroid Build Coastguard Worker 	return TEP_REGISTER_SUCCESS;
8419*436bf2bcSAndroid Build Coastguard Worker }
8420*436bf2bcSAndroid Build Coastguard Worker 
handle_matches(struct event_handler * handler,int id,const char * sys_name,const char * event_name,tep_event_handler_func func,void * context)8421*436bf2bcSAndroid Build Coastguard Worker static int handle_matches(struct event_handler *handler, int id,
8422*436bf2bcSAndroid Build Coastguard Worker 			  const char *sys_name, const char *event_name,
8423*436bf2bcSAndroid Build Coastguard Worker 			  tep_event_handler_func func, void *context)
8424*436bf2bcSAndroid Build Coastguard Worker {
8425*436bf2bcSAndroid Build Coastguard Worker 	if (id >= 0 && id != handler->id)
8426*436bf2bcSAndroid Build Coastguard Worker 		return 0;
8427*436bf2bcSAndroid Build Coastguard Worker 
8428*436bf2bcSAndroid Build Coastguard Worker 	if (event_name && (strcmp(event_name, handler->event_name) != 0))
8429*436bf2bcSAndroid Build Coastguard Worker 		return 0;
8430*436bf2bcSAndroid Build Coastguard Worker 
8431*436bf2bcSAndroid Build Coastguard Worker 	if (sys_name && (strcmp(sys_name, handler->sys_name) != 0))
8432*436bf2bcSAndroid Build Coastguard Worker 		return 0;
8433*436bf2bcSAndroid Build Coastguard Worker 
8434*436bf2bcSAndroid Build Coastguard Worker 	if (func != handler->func || context != handler->context)
8435*436bf2bcSAndroid Build Coastguard Worker 		return 0;
8436*436bf2bcSAndroid Build Coastguard Worker 
8437*436bf2bcSAndroid Build Coastguard Worker 	return 1;
8438*436bf2bcSAndroid Build Coastguard Worker }
8439*436bf2bcSAndroid Build Coastguard Worker 
8440*436bf2bcSAndroid Build Coastguard Worker /**
8441*436bf2bcSAndroid Build Coastguard Worker  * tep_unregister_event_handler - unregister an existing event handler
8442*436bf2bcSAndroid Build Coastguard Worker  * @tep: a handle to the trace event parser context
8443*436bf2bcSAndroid Build Coastguard Worker  * @id: the id of the event to unregister
8444*436bf2bcSAndroid Build Coastguard Worker  * @sys_name: the system name the handler belongs to
8445*436bf2bcSAndroid Build Coastguard Worker  * @event_name: the name of the event handler
8446*436bf2bcSAndroid Build Coastguard Worker  * @func: the function to call to parse the event information
8447*436bf2bcSAndroid Build Coastguard Worker  * @context: the data to be passed to @func
8448*436bf2bcSAndroid Build Coastguard Worker  *
8449*436bf2bcSAndroid Build Coastguard Worker  * This function removes existing event handler (parser).
8450*436bf2bcSAndroid Build Coastguard Worker  *
8451*436bf2bcSAndroid Build Coastguard Worker  * If @id is >= 0, then it is used to find the event.
8452*436bf2bcSAndroid Build Coastguard Worker  * else @sys_name and @event_name are used.
8453*436bf2bcSAndroid Build Coastguard Worker  *
8454*436bf2bcSAndroid Build Coastguard Worker  * Returns 0 if handler was removed successfully, -1 if event was not found.
8455*436bf2bcSAndroid Build Coastguard Worker  */
tep_unregister_event_handler(struct tep_handle * tep,int id,const char * sys_name,const char * event_name,tep_event_handler_func func,void * context)8456*436bf2bcSAndroid Build Coastguard Worker int tep_unregister_event_handler(struct tep_handle *tep, int id,
8457*436bf2bcSAndroid Build Coastguard Worker 				 const char *sys_name, const char *event_name,
8458*436bf2bcSAndroid Build Coastguard Worker 				 tep_event_handler_func func, void *context)
8459*436bf2bcSAndroid Build Coastguard Worker {
8460*436bf2bcSAndroid Build Coastguard Worker 	struct tep_event *event;
8461*436bf2bcSAndroid Build Coastguard Worker 	struct event_handler *handle;
8462*436bf2bcSAndroid Build Coastguard Worker 	struct event_handler **next;
8463*436bf2bcSAndroid Build Coastguard Worker 
8464*436bf2bcSAndroid Build Coastguard Worker 	event = search_event(tep, id, sys_name, event_name);
8465*436bf2bcSAndroid Build Coastguard Worker 	if (event == NULL)
8466*436bf2bcSAndroid Build Coastguard Worker 		goto not_found;
8467*436bf2bcSAndroid Build Coastguard Worker 
8468*436bf2bcSAndroid Build Coastguard Worker 	if (event->handler == func && event->context == context) {
8469*436bf2bcSAndroid Build Coastguard Worker 		tep_info("removing override handler for event (%d) %s:%s. Going back to default handler.",
8470*436bf2bcSAndroid Build Coastguard Worker 			 event->id, event->system, event->name);
8471*436bf2bcSAndroid Build Coastguard Worker 
8472*436bf2bcSAndroid Build Coastguard Worker 		event->handler = NULL;
8473*436bf2bcSAndroid Build Coastguard Worker 		event->context = NULL;
8474*436bf2bcSAndroid Build Coastguard Worker 		return 0;
8475*436bf2bcSAndroid Build Coastguard Worker 	}
8476*436bf2bcSAndroid Build Coastguard Worker 
8477*436bf2bcSAndroid Build Coastguard Worker not_found:
8478*436bf2bcSAndroid Build Coastguard Worker 	for (next = &tep->handlers; *next; next = &(*next)->next) {
8479*436bf2bcSAndroid Build Coastguard Worker 		handle = *next;
8480*436bf2bcSAndroid Build Coastguard Worker 		if (handle_matches(handle, id, sys_name, event_name,
8481*436bf2bcSAndroid Build Coastguard Worker 				   func, context))
8482*436bf2bcSAndroid Build Coastguard Worker 			break;
8483*436bf2bcSAndroid Build Coastguard Worker 	}
8484*436bf2bcSAndroid Build Coastguard Worker 
8485*436bf2bcSAndroid Build Coastguard Worker 	if (!(*next))
8486*436bf2bcSAndroid Build Coastguard Worker 		return -1;
8487*436bf2bcSAndroid Build Coastguard Worker 
8488*436bf2bcSAndroid Build Coastguard Worker 	*next = handle->next;
8489*436bf2bcSAndroid Build Coastguard Worker 	free_handler(handle);
8490*436bf2bcSAndroid Build Coastguard Worker 
8491*436bf2bcSAndroid Build Coastguard Worker 	return 0;
8492*436bf2bcSAndroid Build Coastguard Worker }
8493*436bf2bcSAndroid Build Coastguard Worker 
8494*436bf2bcSAndroid Build Coastguard Worker /**
8495*436bf2bcSAndroid Build Coastguard Worker  * tep_alloc - create a tep handle
8496*436bf2bcSAndroid Build Coastguard Worker  */
tep_alloc(void)8497*436bf2bcSAndroid Build Coastguard Worker struct tep_handle *tep_alloc(void)
8498*436bf2bcSAndroid Build Coastguard Worker {
8499*436bf2bcSAndroid Build Coastguard Worker 	struct tep_handle *tep = calloc(1, sizeof(*tep));
8500*436bf2bcSAndroid Build Coastguard Worker 
8501*436bf2bcSAndroid Build Coastguard Worker 	if (tep) {
8502*436bf2bcSAndroid Build Coastguard Worker 		tep->ref_count = 1;
8503*436bf2bcSAndroid Build Coastguard Worker 		tep->host_bigendian = tep_is_bigendian();
8504*436bf2bcSAndroid Build Coastguard Worker 	}
8505*436bf2bcSAndroid Build Coastguard Worker 
8506*436bf2bcSAndroid Build Coastguard Worker 	return tep;
8507*436bf2bcSAndroid Build Coastguard Worker }
8508*436bf2bcSAndroid Build Coastguard Worker 
tep_ref(struct tep_handle * tep)8509*436bf2bcSAndroid Build Coastguard Worker void tep_ref(struct tep_handle *tep)
8510*436bf2bcSAndroid Build Coastguard Worker {
8511*436bf2bcSAndroid Build Coastguard Worker 	tep->ref_count++;
8512*436bf2bcSAndroid Build Coastguard Worker }
8513*436bf2bcSAndroid Build Coastguard Worker 
tep_get_ref(struct tep_handle * tep)8514*436bf2bcSAndroid Build Coastguard Worker int tep_get_ref(struct tep_handle *tep)
8515*436bf2bcSAndroid Build Coastguard Worker {
8516*436bf2bcSAndroid Build Coastguard Worker 	if (tep)
8517*436bf2bcSAndroid Build Coastguard Worker 		return tep->ref_count;
8518*436bf2bcSAndroid Build Coastguard Worker 	return 0;
8519*436bf2bcSAndroid Build Coastguard Worker }
8520*436bf2bcSAndroid Build Coastguard Worker 
free_tep_format_field(struct tep_format_field * field)8521*436bf2bcSAndroid Build Coastguard Worker __hidden void free_tep_format_field(struct tep_format_field *field)
8522*436bf2bcSAndroid Build Coastguard Worker {
8523*436bf2bcSAndroid Build Coastguard Worker 	free(field->type);
8524*436bf2bcSAndroid Build Coastguard Worker 	if (field->alias != field->name)
8525*436bf2bcSAndroid Build Coastguard Worker 		free(field->alias);
8526*436bf2bcSAndroid Build Coastguard Worker 	free(field->name);
8527*436bf2bcSAndroid Build Coastguard Worker 	free(field);
8528*436bf2bcSAndroid Build Coastguard Worker }
8529*436bf2bcSAndroid Build Coastguard Worker 
free_format_fields(struct tep_format_field * field)8530*436bf2bcSAndroid Build Coastguard Worker static void free_format_fields(struct tep_format_field *field)
8531*436bf2bcSAndroid Build Coastguard Worker {
8532*436bf2bcSAndroid Build Coastguard Worker 	struct tep_format_field *next;
8533*436bf2bcSAndroid Build Coastguard Worker 
8534*436bf2bcSAndroid Build Coastguard Worker 	while (field) {
8535*436bf2bcSAndroid Build Coastguard Worker 		next = field->next;
8536*436bf2bcSAndroid Build Coastguard Worker 		free_tep_format_field(field);
8537*436bf2bcSAndroid Build Coastguard Worker 		field = next;
8538*436bf2bcSAndroid Build Coastguard Worker 	}
8539*436bf2bcSAndroid Build Coastguard Worker }
8540*436bf2bcSAndroid Build Coastguard Worker 
free_formats(struct tep_format * format)8541*436bf2bcSAndroid Build Coastguard Worker static void free_formats(struct tep_format *format)
8542*436bf2bcSAndroid Build Coastguard Worker {
8543*436bf2bcSAndroid Build Coastguard Worker 	free_format_fields(format->common_fields);
8544*436bf2bcSAndroid Build Coastguard Worker 	free_format_fields(format->fields);
8545*436bf2bcSAndroid Build Coastguard Worker }
8546*436bf2bcSAndroid Build Coastguard Worker 
free_tep_event(struct tep_event * event)8547*436bf2bcSAndroid Build Coastguard Worker __hidden void free_tep_event(struct tep_event *event)
8548*436bf2bcSAndroid Build Coastguard Worker {
8549*436bf2bcSAndroid Build Coastguard Worker 	free(event->name);
8550*436bf2bcSAndroid Build Coastguard Worker 	free(event->system);
8551*436bf2bcSAndroid Build Coastguard Worker 
8552*436bf2bcSAndroid Build Coastguard Worker 	free_formats(&event->format);
8553*436bf2bcSAndroid Build Coastguard Worker 
8554*436bf2bcSAndroid Build Coastguard Worker 	free(event->print_fmt.format);
8555*436bf2bcSAndroid Build Coastguard Worker 	free_args(event->print_fmt.args);
8556*436bf2bcSAndroid Build Coastguard Worker 	free_parse_args(event->print_fmt.print_cache);
8557*436bf2bcSAndroid Build Coastguard Worker 	free(event);
8558*436bf2bcSAndroid Build Coastguard Worker }
8559*436bf2bcSAndroid Build Coastguard Worker 
8560*436bf2bcSAndroid Build Coastguard Worker /**
8561*436bf2bcSAndroid Build Coastguard Worker  * tep_free - free a tep handle
8562*436bf2bcSAndroid Build Coastguard Worker  * @tep: the tep handle to free
8563*436bf2bcSAndroid Build Coastguard Worker  */
tep_free(struct tep_handle * tep)8564*436bf2bcSAndroid Build Coastguard Worker void tep_free(struct tep_handle *tep)
8565*436bf2bcSAndroid Build Coastguard Worker {
8566*436bf2bcSAndroid Build Coastguard Worker 	struct cmdline_list *cmdlist, *cmdnext;
8567*436bf2bcSAndroid Build Coastguard Worker 	struct func_list *funclist, *funcnext;
8568*436bf2bcSAndroid Build Coastguard Worker 	struct printk_list *printklist, *printknext;
8569*436bf2bcSAndroid Build Coastguard Worker 	struct tep_function_handler *func_handler;
8570*436bf2bcSAndroid Build Coastguard Worker 	struct event_handler *handle;
8571*436bf2bcSAndroid Build Coastguard Worker 	int i;
8572*436bf2bcSAndroid Build Coastguard Worker 
8573*436bf2bcSAndroid Build Coastguard Worker 	if (!tep)
8574*436bf2bcSAndroid Build Coastguard Worker 		return;
8575*436bf2bcSAndroid Build Coastguard Worker 
8576*436bf2bcSAndroid Build Coastguard Worker 	cmdlist = tep->cmdlist;
8577*436bf2bcSAndroid Build Coastguard Worker 	funclist = tep->funclist;
8578*436bf2bcSAndroid Build Coastguard Worker 	printklist = tep->printklist;
8579*436bf2bcSAndroid Build Coastguard Worker 
8580*436bf2bcSAndroid Build Coastguard Worker 	tep->ref_count--;
8581*436bf2bcSAndroid Build Coastguard Worker 	if (tep->ref_count)
8582*436bf2bcSAndroid Build Coastguard Worker 		return;
8583*436bf2bcSAndroid Build Coastguard Worker 
8584*436bf2bcSAndroid Build Coastguard Worker 	if (tep->cmdlines) {
8585*436bf2bcSAndroid Build Coastguard Worker 		for (i = 0; i < tep->cmdline_count; i++)
8586*436bf2bcSAndroid Build Coastguard Worker 			free(tep->cmdlines[i].comm);
8587*436bf2bcSAndroid Build Coastguard Worker 		free(tep->cmdlines);
8588*436bf2bcSAndroid Build Coastguard Worker 	}
8589*436bf2bcSAndroid Build Coastguard Worker 
8590*436bf2bcSAndroid Build Coastguard Worker 	while (cmdlist) {
8591*436bf2bcSAndroid Build Coastguard Worker 		cmdnext = cmdlist->next;
8592*436bf2bcSAndroid Build Coastguard Worker 		free(cmdlist->comm);
8593*436bf2bcSAndroid Build Coastguard Worker 		free(cmdlist);
8594*436bf2bcSAndroid Build Coastguard Worker 		cmdlist = cmdnext;
8595*436bf2bcSAndroid Build Coastguard Worker 	}
8596*436bf2bcSAndroid Build Coastguard Worker 
8597*436bf2bcSAndroid Build Coastguard Worker 	if (tep->func_map) {
8598*436bf2bcSAndroid Build Coastguard Worker 		for (i = 0; i < (int)tep->func_count; i++) {
8599*436bf2bcSAndroid Build Coastguard Worker 			free(tep->func_map[i].func);
8600*436bf2bcSAndroid Build Coastguard Worker 			free(tep->func_map[i].mod);
8601*436bf2bcSAndroid Build Coastguard Worker 		}
8602*436bf2bcSAndroid Build Coastguard Worker 		free(tep->func_map);
8603*436bf2bcSAndroid Build Coastguard Worker 	}
8604*436bf2bcSAndroid Build Coastguard Worker 
8605*436bf2bcSAndroid Build Coastguard Worker 	while (funclist) {
8606*436bf2bcSAndroid Build Coastguard Worker 		funcnext = funclist->next;
8607*436bf2bcSAndroid Build Coastguard Worker 		free(funclist->func);
8608*436bf2bcSAndroid Build Coastguard Worker 		free(funclist->mod);
8609*436bf2bcSAndroid Build Coastguard Worker 		free(funclist);
8610*436bf2bcSAndroid Build Coastguard Worker 		funclist = funcnext;
8611*436bf2bcSAndroid Build Coastguard Worker 	}
8612*436bf2bcSAndroid Build Coastguard Worker 
8613*436bf2bcSAndroid Build Coastguard Worker 	while (tep->func_handlers) {
8614*436bf2bcSAndroid Build Coastguard Worker 		func_handler = tep->func_handlers;
8615*436bf2bcSAndroid Build Coastguard Worker 		tep->func_handlers = func_handler->next;
8616*436bf2bcSAndroid Build Coastguard Worker 		free_func_handle(func_handler);
8617*436bf2bcSAndroid Build Coastguard Worker 	}
8618*436bf2bcSAndroid Build Coastguard Worker 
8619*436bf2bcSAndroid Build Coastguard Worker 	if (tep->printk_map) {
8620*436bf2bcSAndroid Build Coastguard Worker 		for (i = 0; i < (int)tep->printk_count; i++)
8621*436bf2bcSAndroid Build Coastguard Worker 			free(tep->printk_map[i].printk);
8622*436bf2bcSAndroid Build Coastguard Worker 		free(tep->printk_map);
8623*436bf2bcSAndroid Build Coastguard Worker 	}
8624*436bf2bcSAndroid Build Coastguard Worker 
8625*436bf2bcSAndroid Build Coastguard Worker 	while (printklist) {
8626*436bf2bcSAndroid Build Coastguard Worker 		printknext = printklist->next;
8627*436bf2bcSAndroid Build Coastguard Worker 		free(printklist->printk);
8628*436bf2bcSAndroid Build Coastguard Worker 		free(printklist);
8629*436bf2bcSAndroid Build Coastguard Worker 		printklist = printknext;
8630*436bf2bcSAndroid Build Coastguard Worker 	}
8631*436bf2bcSAndroid Build Coastguard Worker 
8632*436bf2bcSAndroid Build Coastguard Worker 	for (i = 0; i < tep->nr_events; i++)
8633*436bf2bcSAndroid Build Coastguard Worker 		free_tep_event(tep->events[i]);
8634*436bf2bcSAndroid Build Coastguard Worker 
8635*436bf2bcSAndroid Build Coastguard Worker 	while (tep->handlers) {
8636*436bf2bcSAndroid Build Coastguard Worker 		handle = tep->handlers;
8637*436bf2bcSAndroid Build Coastguard Worker 		tep->handlers = handle->next;
8638*436bf2bcSAndroid Build Coastguard Worker 		free_handler(handle);
8639*436bf2bcSAndroid Build Coastguard Worker 	}
8640*436bf2bcSAndroid Build Coastguard Worker 
8641*436bf2bcSAndroid Build Coastguard Worker 	free(tep->events);
8642*436bf2bcSAndroid Build Coastguard Worker 	free(tep->sort_events);
8643*436bf2bcSAndroid Build Coastguard Worker 	free(tep->func_resolver);
8644*436bf2bcSAndroid Build Coastguard Worker 	free_tep_plugin_paths(tep);
8645*436bf2bcSAndroid Build Coastguard Worker 
8646*436bf2bcSAndroid Build Coastguard Worker 	free(tep);
8647*436bf2bcSAndroid Build Coastguard Worker }
8648*436bf2bcSAndroid Build Coastguard Worker 
tep_unref(struct tep_handle * tep)8649*436bf2bcSAndroid Build Coastguard Worker void tep_unref(struct tep_handle *tep)
8650*436bf2bcSAndroid Build Coastguard Worker {
8651*436bf2bcSAndroid Build Coastguard Worker 	tep_free(tep);
8652*436bf2bcSAndroid Build Coastguard Worker }
8653