Home | History | Annotate | Download | only in scripting-engines
      1 /*
      2  * trace-event-python.  Feed trace events to an embedded Python interpreter.
      3  *
      4  * Copyright (C) 2010 Tom Zanussi <tzanussi (at) gmail.com>
      5  *
      6  *  This program is free software; you can redistribute it and/or modify
      7  *  it under the terms of the GNU General Public License as published by
      8  *  the Free Software Foundation; either version 2 of the License, or
      9  *  (at your option) any later version.
     10  *
     11  *  This program is distributed in the hope that it will be useful,
     12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14  *  GNU General Public License for more details.
     15  *
     16  *  You should have received a copy of the GNU General Public License
     17  *  along with this program; if not, write to the Free Software
     18  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
     19  *
     20  */
     21 
     22 #include <Python.h>
     23 
     24 #include <stdio.h>
     25 #include <stdlib.h>
     26 #include <string.h>
     27 #include <errno.h>
     28 
     29 #include "../../perf.h"
     30 #include "../evsel.h"
     31 #include "../util.h"
     32 #include "../event.h"
     33 #include "../thread.h"
     34 #include "../trace-event.h"
     35 
     36 PyMODINIT_FUNC initperf_trace_context(void);
     37 
     38 #define FTRACE_MAX_EVENT				\
     39 	((1 << (sizeof(unsigned short) * 8)) - 1)
     40 
     41 struct event_format *events[FTRACE_MAX_EVENT];
     42 
     43 #define MAX_FIELDS	64
     44 #define N_COMMON_FIELDS	7
     45 
     46 extern struct scripting_context *scripting_context;
     47 
     48 static char *cur_field_name;
     49 static int zero_flag_atom;
     50 
     51 static PyObject *main_module, *main_dict;
     52 
     53 static void handler_call_die(const char *handler_name)
     54 {
     55 	PyErr_Print();
     56 	Py_FatalError("problem in Python trace event handler");
     57 }
     58 
     59 /*
     60  * Insert val into into the dictionary and decrement the reference counter.
     61  * This is necessary for dictionaries since PyDict_SetItemString() does not
     62  * steal a reference, as opposed to PyTuple_SetItem().
     63  */
     64 static void pydict_set_item_string_decref(PyObject *dict, const char *key, PyObject *val)
     65 {
     66 	PyDict_SetItemString(dict, key, val);
     67 	Py_DECREF(val);
     68 }
     69 
     70 static void define_value(enum print_arg_type field_type,
     71 			 const char *ev_name,
     72 			 const char *field_name,
     73 			 const char *field_value,
     74 			 const char *field_str)
     75 {
     76 	const char *handler_name = "define_flag_value";
     77 	PyObject *handler, *t, *retval;
     78 	unsigned long long value;
     79 	unsigned n = 0;
     80 
     81 	if (field_type == PRINT_SYMBOL)
     82 		handler_name = "define_symbolic_value";
     83 
     84 	t = PyTuple_New(4);
     85 	if (!t)
     86 		Py_FatalError("couldn't create Python tuple");
     87 
     88 	value = eval_flag(field_value);
     89 
     90 	PyTuple_SetItem(t, n++, PyString_FromString(ev_name));
     91 	PyTuple_SetItem(t, n++, PyString_FromString(field_name));
     92 	PyTuple_SetItem(t, n++, PyInt_FromLong(value));
     93 	PyTuple_SetItem(t, n++, PyString_FromString(field_str));
     94 
     95 	handler = PyDict_GetItemString(main_dict, handler_name);
     96 	if (handler && PyCallable_Check(handler)) {
     97 		retval = PyObject_CallObject(handler, t);
     98 		if (retval == NULL)
     99 			handler_call_die(handler_name);
    100 	}
    101 
    102 	Py_DECREF(t);
    103 }
    104 
    105 static void define_values(enum print_arg_type field_type,
    106 			  struct print_flag_sym *field,
    107 			  const char *ev_name,
    108 			  const char *field_name)
    109 {
    110 	define_value(field_type, ev_name, field_name, field->value,
    111 		     field->str);
    112 
    113 	if (field->next)
    114 		define_values(field_type, field->next, ev_name, field_name);
    115 }
    116 
    117 static void define_field(enum print_arg_type field_type,
    118 			 const char *ev_name,
    119 			 const char *field_name,
    120 			 const char *delim)
    121 {
    122 	const char *handler_name = "define_flag_field";
    123 	PyObject *handler, *t, *retval;
    124 	unsigned n = 0;
    125 
    126 	if (field_type == PRINT_SYMBOL)
    127 		handler_name = "define_symbolic_field";
    128 
    129 	if (field_type == PRINT_FLAGS)
    130 		t = PyTuple_New(3);
    131 	else
    132 		t = PyTuple_New(2);
    133 	if (!t)
    134 		Py_FatalError("couldn't create Python tuple");
    135 
    136 	PyTuple_SetItem(t, n++, PyString_FromString(ev_name));
    137 	PyTuple_SetItem(t, n++, PyString_FromString(field_name));
    138 	if (field_type == PRINT_FLAGS)
    139 		PyTuple_SetItem(t, n++, PyString_FromString(delim));
    140 
    141 	handler = PyDict_GetItemString(main_dict, handler_name);
    142 	if (handler && PyCallable_Check(handler)) {
    143 		retval = PyObject_CallObject(handler, t);
    144 		if (retval == NULL)
    145 			handler_call_die(handler_name);
    146 	}
    147 
    148 	Py_DECREF(t);
    149 }
    150 
    151 static void define_event_symbols(struct event_format *event,
    152 				 const char *ev_name,
    153 				 struct print_arg *args)
    154 {
    155 	switch (args->type) {
    156 	case PRINT_NULL:
    157 		break;
    158 	case PRINT_ATOM:
    159 		define_value(PRINT_FLAGS, ev_name, cur_field_name, "0",
    160 			     args->atom.atom);
    161 		zero_flag_atom = 0;
    162 		break;
    163 	case PRINT_FIELD:
    164 		if (cur_field_name)
    165 			free(cur_field_name);
    166 		cur_field_name = strdup(args->field.name);
    167 		break;
    168 	case PRINT_FLAGS:
    169 		define_event_symbols(event, ev_name, args->flags.field);
    170 		define_field(PRINT_FLAGS, ev_name, cur_field_name,
    171 			     args->flags.delim);
    172 		define_values(PRINT_FLAGS, args->flags.flags, ev_name,
    173 			      cur_field_name);
    174 		break;
    175 	case PRINT_SYMBOL:
    176 		define_event_symbols(event, ev_name, args->symbol.field);
    177 		define_field(PRINT_SYMBOL, ev_name, cur_field_name, NULL);
    178 		define_values(PRINT_SYMBOL, args->symbol.symbols, ev_name,
    179 			      cur_field_name);
    180 		break;
    181 	case PRINT_HEX:
    182 		define_event_symbols(event, ev_name, args->hex.field);
    183 		define_event_symbols(event, ev_name, args->hex.size);
    184 		break;
    185 	case PRINT_STRING:
    186 		break;
    187 	case PRINT_TYPE:
    188 		define_event_symbols(event, ev_name, args->typecast.item);
    189 		break;
    190 	case PRINT_OP:
    191 		if (strcmp(args->op.op, ":") == 0)
    192 			zero_flag_atom = 1;
    193 		define_event_symbols(event, ev_name, args->op.left);
    194 		define_event_symbols(event, ev_name, args->op.right);
    195 		break;
    196 	default:
    197 		/* gcc warns for these? */
    198 	case PRINT_BSTRING:
    199 	case PRINT_DYNAMIC_ARRAY:
    200 	case PRINT_FUNC:
    201 		/* we should warn... */
    202 		return;
    203 	}
    204 
    205 	if (args->next)
    206 		define_event_symbols(event, ev_name, args->next);
    207 }
    208 
    209 static inline struct event_format *find_cache_event(struct perf_evsel *evsel)
    210 {
    211 	static char ev_name[256];
    212 	struct event_format *event;
    213 	int type = evsel->attr.config;
    214 
    215 	/*
    216  	 * XXX: Do we really need to cache this since now we have evsel->tp_format
    217  	 * cached already? Need to re-read this "cache" routine that as well calls
    218  	 * define_event_symbols() :-\
    219  	 */
    220 	if (events[type])
    221 		return events[type];
    222 
    223 	events[type] = event = evsel->tp_format;
    224 	if (!event)
    225 		return NULL;
    226 
    227 	sprintf(ev_name, "%s__%s", event->system, event->name);
    228 
    229 	define_event_symbols(event, ev_name, event->print_fmt.args);
    230 
    231 	return event;
    232 }
    233 
    234 static void python_process_tracepoint(union perf_event *perf_event
    235 				      __maybe_unused,
    236 				 struct perf_sample *sample,
    237 				 struct perf_evsel *evsel,
    238 				 struct machine *machine __maybe_unused,
    239 				 struct thread *thread,
    240 				 struct addr_location *al)
    241 {
    242 	PyObject *handler, *retval, *context, *t, *obj, *dict = NULL;
    243 	static char handler_name[256];
    244 	struct format_field *field;
    245 	unsigned long long val;
    246 	unsigned long s, ns;
    247 	struct event_format *event;
    248 	unsigned n = 0;
    249 	int pid;
    250 	int cpu = sample->cpu;
    251 	void *data = sample->raw_data;
    252 	unsigned long long nsecs = sample->time;
    253 	char *comm = thread->comm;
    254 
    255 	t = PyTuple_New(MAX_FIELDS);
    256 	if (!t)
    257 		Py_FatalError("couldn't create Python tuple");
    258 
    259 	event = find_cache_event(evsel);
    260 	if (!event)
    261 		die("ug! no event found for type %d", (int)evsel->attr.config);
    262 
    263 	pid = raw_field_value(event, "common_pid", data);
    264 
    265 	sprintf(handler_name, "%s__%s", event->system, event->name);
    266 
    267 	handler = PyDict_GetItemString(main_dict, handler_name);
    268 	if (handler && !PyCallable_Check(handler))
    269 		handler = NULL;
    270 	if (!handler) {
    271 		dict = PyDict_New();
    272 		if (!dict)
    273 			Py_FatalError("couldn't create Python dict");
    274 	}
    275 	s = nsecs / NSECS_PER_SEC;
    276 	ns = nsecs - s * NSECS_PER_SEC;
    277 
    278 	scripting_context->event_data = data;
    279 	scripting_context->pevent = evsel->tp_format->pevent;
    280 
    281 	context = PyCObject_FromVoidPtr(scripting_context, NULL);
    282 
    283 	PyTuple_SetItem(t, n++, PyString_FromString(handler_name));
    284 	PyTuple_SetItem(t, n++, context);
    285 
    286 	if (handler) {
    287 		PyTuple_SetItem(t, n++, PyInt_FromLong(cpu));
    288 		PyTuple_SetItem(t, n++, PyInt_FromLong(s));
    289 		PyTuple_SetItem(t, n++, PyInt_FromLong(ns));
    290 		PyTuple_SetItem(t, n++, PyInt_FromLong(pid));
    291 		PyTuple_SetItem(t, n++, PyString_FromString(comm));
    292 	} else {
    293 		pydict_set_item_string_decref(dict, "common_cpu", PyInt_FromLong(cpu));
    294 		pydict_set_item_string_decref(dict, "common_s", PyInt_FromLong(s));
    295 		pydict_set_item_string_decref(dict, "common_ns", PyInt_FromLong(ns));
    296 		pydict_set_item_string_decref(dict, "common_pid", PyInt_FromLong(pid));
    297 		pydict_set_item_string_decref(dict, "common_comm", PyString_FromString(comm));
    298 	}
    299 	for (field = event->format.fields; field; field = field->next) {
    300 		if (field->flags & FIELD_IS_STRING) {
    301 			int offset;
    302 			if (field->flags & FIELD_IS_DYNAMIC) {
    303 				offset = *(int *)(data + field->offset);
    304 				offset &= 0xffff;
    305 			} else
    306 				offset = field->offset;
    307 			obj = PyString_FromString((char *)data + offset);
    308 		} else { /* FIELD_IS_NUMERIC */
    309 			val = read_size(event, data + field->offset,
    310 					field->size);
    311 			if (field->flags & FIELD_IS_SIGNED) {
    312 				if ((long long)val >= LONG_MIN &&
    313 				    (long long)val <= LONG_MAX)
    314 					obj = PyInt_FromLong(val);
    315 				else
    316 					obj = PyLong_FromLongLong(val);
    317 			} else {
    318 				if (val <= LONG_MAX)
    319 					obj = PyInt_FromLong(val);
    320 				else
    321 					obj = PyLong_FromUnsignedLongLong(val);
    322 			}
    323 		}
    324 		if (handler)
    325 			PyTuple_SetItem(t, n++, obj);
    326 		else
    327 			pydict_set_item_string_decref(dict, field->name, obj);
    328 
    329 	}
    330 	if (!handler)
    331 		PyTuple_SetItem(t, n++, dict);
    332 
    333 	if (_PyTuple_Resize(&t, n) == -1)
    334 		Py_FatalError("error resizing Python tuple");
    335 
    336 	if (handler) {
    337 		retval = PyObject_CallObject(handler, t);
    338 		if (retval == NULL)
    339 			handler_call_die(handler_name);
    340 	} else {
    341 		handler = PyDict_GetItemString(main_dict, "trace_unhandled");
    342 		if (handler && PyCallable_Check(handler)) {
    343 
    344 			retval = PyObject_CallObject(handler, t);
    345 			if (retval == NULL)
    346 				handler_call_die("trace_unhandled");
    347 		}
    348 		Py_DECREF(dict);
    349 	}
    350 
    351 	Py_DECREF(t);
    352 }
    353 
    354 static void python_process_general_event(union perf_event *perf_event
    355 					 __maybe_unused,
    356 					 struct perf_sample *sample,
    357 					 struct perf_evsel *evsel,
    358 					 struct machine *machine __maybe_unused,
    359 					 struct thread *thread,
    360 					 struct addr_location *al)
    361 {
    362 	PyObject *handler, *retval, *t, *dict;
    363 	static char handler_name[64];
    364 	unsigned n = 0;
    365 
    366 	/*
    367 	 * Use the MAX_FIELDS to make the function expandable, though
    368 	 * currently there is only one item for the tuple.
    369 	 */
    370 	t = PyTuple_New(MAX_FIELDS);
    371 	if (!t)
    372 		Py_FatalError("couldn't create Python tuple");
    373 
    374 	dict = PyDict_New();
    375 	if (!dict)
    376 		Py_FatalError("couldn't create Python dictionary");
    377 
    378 	snprintf(handler_name, sizeof(handler_name), "%s", "process_event");
    379 
    380 	handler = PyDict_GetItemString(main_dict, handler_name);
    381 	if (!handler || !PyCallable_Check(handler))
    382 		goto exit;
    383 
    384 	pydict_set_item_string_decref(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel)));
    385 	pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize(
    386 			(const char *)&evsel->attr, sizeof(evsel->attr)));
    387 	pydict_set_item_string_decref(dict, "sample", PyString_FromStringAndSize(
    388 			(const char *)sample, sizeof(*sample)));
    389 	pydict_set_item_string_decref(dict, "raw_buf", PyString_FromStringAndSize(
    390 			(const char *)sample->raw_data, sample->raw_size));
    391 	pydict_set_item_string_decref(dict, "comm",
    392 			PyString_FromString(thread->comm));
    393 	if (al->map) {
    394 		pydict_set_item_string_decref(dict, "dso",
    395 			PyString_FromString(al->map->dso->name));
    396 	}
    397 	if (al->sym) {
    398 		pydict_set_item_string_decref(dict, "symbol",
    399 			PyString_FromString(al->sym->name));
    400 	}
    401 
    402 	PyTuple_SetItem(t, n++, dict);
    403 	if (_PyTuple_Resize(&t, n) == -1)
    404 		Py_FatalError("error resizing Python tuple");
    405 
    406 	retval = PyObject_CallObject(handler, t);
    407 	if (retval == NULL)
    408 		handler_call_die(handler_name);
    409 exit:
    410 	Py_DECREF(dict);
    411 	Py_DECREF(t);
    412 }
    413 
    414 static void python_process_event(union perf_event *perf_event,
    415 				 struct perf_sample *sample,
    416 				 struct perf_evsel *evsel,
    417 				 struct machine *machine,
    418 				 struct thread *thread,
    419 				 struct addr_location *al)
    420 {
    421 	switch (evsel->attr.type) {
    422 	case PERF_TYPE_TRACEPOINT:
    423 		python_process_tracepoint(perf_event, sample, evsel,
    424 					  machine, thread, al);
    425 		break;
    426 	/* Reserve for future process_hw/sw/raw APIs */
    427 	default:
    428 		python_process_general_event(perf_event, sample, evsel,
    429 					     machine, thread, al);
    430 	}
    431 }
    432 
    433 static int run_start_sub(void)
    434 {
    435 	PyObject *handler, *retval;
    436 	int err = 0;
    437 
    438 	main_module = PyImport_AddModule("__main__");
    439 	if (main_module == NULL)
    440 		return -1;
    441 	Py_INCREF(main_module);
    442 
    443 	main_dict = PyModule_GetDict(main_module);
    444 	if (main_dict == NULL) {
    445 		err = -1;
    446 		goto error;
    447 	}
    448 	Py_INCREF(main_dict);
    449 
    450 	handler = PyDict_GetItemString(main_dict, "trace_begin");
    451 	if (handler == NULL || !PyCallable_Check(handler))
    452 		goto out;
    453 
    454 	retval = PyObject_CallObject(handler, NULL);
    455 	if (retval == NULL)
    456 		handler_call_die("trace_begin");
    457 
    458 	Py_DECREF(retval);
    459 	return err;
    460 error:
    461 	Py_XDECREF(main_dict);
    462 	Py_XDECREF(main_module);
    463 out:
    464 	return err;
    465 }
    466 
    467 /*
    468  * Start trace script
    469  */
    470 static int python_start_script(const char *script, int argc, const char **argv)
    471 {
    472 	const char **command_line;
    473 	char buf[PATH_MAX];
    474 	int i, err = 0;
    475 	FILE *fp;
    476 
    477 	command_line = malloc((argc + 1) * sizeof(const char *));
    478 	command_line[0] = script;
    479 	for (i = 1; i < argc + 1; i++)
    480 		command_line[i] = argv[i - 1];
    481 
    482 	Py_Initialize();
    483 
    484 	initperf_trace_context();
    485 
    486 	PySys_SetArgv(argc + 1, (char **)command_line);
    487 
    488 	fp = fopen(script, "r");
    489 	if (!fp) {
    490 		sprintf(buf, "Can't open python script \"%s\"", script);
    491 		perror(buf);
    492 		err = -1;
    493 		goto error;
    494 	}
    495 
    496 	err = PyRun_SimpleFile(fp, script);
    497 	if (err) {
    498 		fprintf(stderr, "Error running python script %s\n", script);
    499 		goto error;
    500 	}
    501 
    502 	err = run_start_sub();
    503 	if (err) {
    504 		fprintf(stderr, "Error starting python script %s\n", script);
    505 		goto error;
    506 	}
    507 
    508 	free(command_line);
    509 
    510 	return err;
    511 error:
    512 	Py_Finalize();
    513 	free(command_line);
    514 
    515 	return err;
    516 }
    517 
    518 /*
    519  * Stop trace script
    520  */
    521 static int python_stop_script(void)
    522 {
    523 	PyObject *handler, *retval;
    524 	int err = 0;
    525 
    526 	handler = PyDict_GetItemString(main_dict, "trace_end");
    527 	if (handler == NULL || !PyCallable_Check(handler))
    528 		goto out;
    529 
    530 	retval = PyObject_CallObject(handler, NULL);
    531 	if (retval == NULL)
    532 		handler_call_die("trace_end");
    533 	else
    534 		Py_DECREF(retval);
    535 out:
    536 	Py_XDECREF(main_dict);
    537 	Py_XDECREF(main_module);
    538 	Py_Finalize();
    539 
    540 	return err;
    541 }
    542 
    543 static int python_generate_script(struct pevent *pevent, const char *outfile)
    544 {
    545 	struct event_format *event = NULL;
    546 	struct format_field *f;
    547 	char fname[PATH_MAX];
    548 	int not_first, count;
    549 	FILE *ofp;
    550 
    551 	sprintf(fname, "%s.py", outfile);
    552 	ofp = fopen(fname, "w");
    553 	if (ofp == NULL) {
    554 		fprintf(stderr, "couldn't open %s\n", fname);
    555 		return -1;
    556 	}
    557 	fprintf(ofp, "# perf script event handlers, "
    558 		"generated by perf script -g python\n");
    559 
    560 	fprintf(ofp, "# Licensed under the terms of the GNU GPL"
    561 		" License version 2\n\n");
    562 
    563 	fprintf(ofp, "# The common_* event handler fields are the most useful "
    564 		"fields common to\n");
    565 
    566 	fprintf(ofp, "# all events.  They don't necessarily correspond to "
    567 		"the 'common_*' fields\n");
    568 
    569 	fprintf(ofp, "# in the format files.  Those fields not available as "
    570 		"handler params can\n");
    571 
    572 	fprintf(ofp, "# be retrieved using Python functions of the form "
    573 		"common_*(context).\n");
    574 
    575 	fprintf(ofp, "# See the perf-trace-python Documentation for the list "
    576 		"of available functions.\n\n");
    577 
    578 	fprintf(ofp, "import os\n");
    579 	fprintf(ofp, "import sys\n\n");
    580 
    581 	fprintf(ofp, "sys.path.append(os.environ['PERF_EXEC_PATH'] + \\\n");
    582 	fprintf(ofp, "\t'/scripts/python/Perf-Trace-Util/lib/Perf/Trace')\n");
    583 	fprintf(ofp, "\nfrom perf_trace_context import *\n");
    584 	fprintf(ofp, "from Core import *\n\n\n");
    585 
    586 	fprintf(ofp, "def trace_begin():\n");
    587 	fprintf(ofp, "\tprint \"in trace_begin\"\n\n");
    588 
    589 	fprintf(ofp, "def trace_end():\n");
    590 	fprintf(ofp, "\tprint \"in trace_end\"\n\n");
    591 
    592 	while ((event = trace_find_next_event(pevent, event))) {
    593 		fprintf(ofp, "def %s__%s(", event->system, event->name);
    594 		fprintf(ofp, "event_name, ");
    595 		fprintf(ofp, "context, ");
    596 		fprintf(ofp, "common_cpu,\n");
    597 		fprintf(ofp, "\tcommon_secs, ");
    598 		fprintf(ofp, "common_nsecs, ");
    599 		fprintf(ofp, "common_pid, ");
    600 		fprintf(ofp, "common_comm,\n\t");
    601 
    602 		not_first = 0;
    603 		count = 0;
    604 
    605 		for (f = event->format.fields; f; f = f->next) {
    606 			if (not_first++)
    607 				fprintf(ofp, ", ");
    608 			if (++count % 5 == 0)
    609 				fprintf(ofp, "\n\t");
    610 
    611 			fprintf(ofp, "%s", f->name);
    612 		}
    613 		fprintf(ofp, "):\n");
    614 
    615 		fprintf(ofp, "\t\tprint_header(event_name, common_cpu, "
    616 			"common_secs, common_nsecs,\n\t\t\t"
    617 			"common_pid, common_comm)\n\n");
    618 
    619 		fprintf(ofp, "\t\tprint \"");
    620 
    621 		not_first = 0;
    622 		count = 0;
    623 
    624 		for (f = event->format.fields; f; f = f->next) {
    625 			if (not_first++)
    626 				fprintf(ofp, ", ");
    627 			if (count && count % 3 == 0) {
    628 				fprintf(ofp, "\" \\\n\t\t\"");
    629 			}
    630 			count++;
    631 
    632 			fprintf(ofp, "%s=", f->name);
    633 			if (f->flags & FIELD_IS_STRING ||
    634 			    f->flags & FIELD_IS_FLAG ||
    635 			    f->flags & FIELD_IS_SYMBOLIC)
    636 				fprintf(ofp, "%%s");
    637 			else if (f->flags & FIELD_IS_SIGNED)
    638 				fprintf(ofp, "%%d");
    639 			else
    640 				fprintf(ofp, "%%u");
    641 		}
    642 
    643 		fprintf(ofp, "\\n\" %% \\\n\t\t(");
    644 
    645 		not_first = 0;
    646 		count = 0;
    647 
    648 		for (f = event->format.fields; f; f = f->next) {
    649 			if (not_first++)
    650 				fprintf(ofp, ", ");
    651 
    652 			if (++count % 5 == 0)
    653 				fprintf(ofp, "\n\t\t");
    654 
    655 			if (f->flags & FIELD_IS_FLAG) {
    656 				if ((count - 1) % 5 != 0) {
    657 					fprintf(ofp, "\n\t\t");
    658 					count = 4;
    659 				}
    660 				fprintf(ofp, "flag_str(\"");
    661 				fprintf(ofp, "%s__%s\", ", event->system,
    662 					event->name);
    663 				fprintf(ofp, "\"%s\", %s)", f->name,
    664 					f->name);
    665 			} else if (f->flags & FIELD_IS_SYMBOLIC) {
    666 				if ((count - 1) % 5 != 0) {
    667 					fprintf(ofp, "\n\t\t");
    668 					count = 4;
    669 				}
    670 				fprintf(ofp, "symbol_str(\"");
    671 				fprintf(ofp, "%s__%s\", ", event->system,
    672 					event->name);
    673 				fprintf(ofp, "\"%s\", %s)", f->name,
    674 					f->name);
    675 			} else
    676 				fprintf(ofp, "%s", f->name);
    677 		}
    678 
    679 		fprintf(ofp, "),\n\n");
    680 	}
    681 
    682 	fprintf(ofp, "def trace_unhandled(event_name, context, "
    683 		"event_fields_dict):\n");
    684 
    685 	fprintf(ofp, "\t\tprint ' '.join(['%%s=%%s'%%(k,str(v))"
    686 		"for k,v in sorted(event_fields_dict.items())])\n\n");
    687 
    688 	fprintf(ofp, "def print_header("
    689 		"event_name, cpu, secs, nsecs, pid, comm):\n"
    690 		"\tprint \"%%-20s %%5u %%05u.%%09u %%8u %%-20s \" %% \\\n\t"
    691 		"(event_name, cpu, secs, nsecs, pid, comm),\n");
    692 
    693 	fclose(ofp);
    694 
    695 	fprintf(stderr, "generated Python script: %s\n", fname);
    696 
    697 	return 0;
    698 }
    699 
    700 struct scripting_ops python_scripting_ops = {
    701 	.name = "Python",
    702 	.start_script = python_start_script,
    703 	.stop_script = python_stop_script,
    704 	.process_event = python_process_event,
    705 	.generate_script = python_generate_script,
    706 };
    707