From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([208.118.235.92]:43269) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SDg4q-0006xr-Fg for qemu-devel@nongnu.org; Fri, 30 Mar 2012 13:57:36 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1SDg4m-0001E6-Dd for qemu-devel@nongnu.org; Fri, 30 Mar 2012 13:57:32 -0400 Received: from roura.ac.upc.es ([147.83.33.10]:46132) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SDg4l-0001Dy-Lu for qemu-devel@nongnu.org; Fri, 30 Mar 2012 13:57:28 -0400 From: =?utf-8?b?TGx1w61z?= Vilanova Date: Fri, 30 Mar 2012 19:57:29 +0200 Message-Id: <20120330175729.22501.1204.stgit@ginnungagap.bsc.es> In-Reply-To: <20120330175721.22501.39566.stgit@ginnungagap.bsc.es> References: <20120330175721.22501.39566.stgit@ginnungagap.bsc.es> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Subject: [Qemu-devel] [RFC PATCH v4 1/8] tracetool: Rewrite infrastructure as python modules List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: stefanha@gmail.com Signed-off-by: Llu=C3=ADs Vilanova --- Makefile.objs | 6=20 Makefile.target | 13 - configure | 4=20 scripts/tracetool | 648 ---------------------------= ------ scripts/tracetool.py | 108 ++++++ scripts/tracetool/__init__.py | 222 +++++++++++ scripts/tracetool/backend/__init__.py | 105 +++++ scripts/tracetool/format/__init__.py | 96 +++++ 8 files changed, 543 insertions(+), 659 deletions(-) delete mode 100755 scripts/tracetool create mode 100755 scripts/tracetool.py create mode 100644 scripts/tracetool/__init__.py create mode 100644 scripts/tracetool/backend/__init__.py create mode 100644 scripts/tracetool/format/__init__.py diff --git a/Makefile.objs b/Makefile.objs index 226b01d..8e56f48 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -373,12 +373,12 @@ else trace.h: trace.h-timestamp endif trace.h-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak - $(call quiet-command,sh $(SRC_PATH)/scripts/tracetool --$(TRACE_BACKEND= ) -h < $< > $@," GEN trace.h") + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py --forma= t=3Dh --backend=3D$(TRACE_BACKEND) < $< > $@," GEN trace.h") @cmp -s $@ trace.h || cp $@ trace.h =20 trace.c: trace.c-timestamp trace.c-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak - $(call quiet-command,sh $(SRC_PATH)/scripts/tracetool --$(TRACE_BACKEND= ) -c < $< > $@," GEN trace.c") + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py --forma= t=3Dc --backend=3D$(TRACE_BACKEND) < $< > $@," GEN trace.c") @cmp -s $@ trace.c || cp $@ trace.c =20 trace.o: trace.c $(GENERATED_HEADERS) @@ -391,7 +391,7 @@ trace-dtrace.h: trace-dtrace.dtrace # rule file. So we use '.dtrace' instead trace-dtrace.dtrace: trace-dtrace.dtrace-timestamp trace-dtrace.dtrace-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/con= fig-host.mak - $(call quiet-command,sh $(SRC_PATH)/scripts/tracetool --$(TRACE_BACKEND= ) -d < $< > $@," GEN trace-dtrace.dtrace") + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py --forma= t=3Dd --backend=3D$(TRACE_BACKEND) < $< > $@," GEN trace-dtrace.dtrace= ") @cmp -s $@ trace-dtrace.dtrace || cp $@ trace-dtrace.dtrace =20 trace-dtrace.o: trace-dtrace.dtrace $(GENERATED_HEADERS) diff --git a/Makefile.target b/Makefile.target index 63cf769..fe28e8b 100644 --- a/Makefile.target +++ b/Makefile.target @@ -59,12 +59,13 @@ TARGET_TYPE=3Dsystem endif =20 $(QEMU_PROG).stp: - $(call quiet-command,sh $(SRC_PATH)/scripts/tracetool \ - --$(TRACE_BACKEND) \ - --binary $(bindir)/$(QEMU_PROG) \ - --target-arch $(TARGET_ARCH) \ - --target-type $(TARGET_TYPE) \ - --stap < $(SRC_PATH)/trace-events > $(QEMU_PROG).stp," GEN $(QEMU_P= ROG).stp") + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py \ + --format=3Dstap \ + --backend=3D$(TRACE_BACKEND) \ + --binary=3D$(bindir)/$(QEMU_PROG) \ + --target-arch=3D$(TARGET_ARCH) \ + --target-type=3D$(TARGET_TYPE) \ + < $(SRC_PATH)/trace-events > $(QEMU_PROG).stp," GEN $(QEMU_PROG).st= p") else stap: endif diff --git a/configure b/configure index 8b4e3c1..c2d6117 100755 --- a/configure +++ b/configure @@ -1097,7 +1097,7 @@ echo " --disable-docs disable documentat= ion build" echo " --disable-vhost-net disable vhost-net acceleration support" echo " --enable-vhost-net enable vhost-net acceleration support" echo " --enable-trace-backend=3DB Set trace backend" -echo " Available backends:" $("$source_path"/s= cripts/tracetool --list-backends) +echo " Available backends:" $($python "$source= _path"/scripts/tracetool.py --list-backends) echo " --with-trace-file=3DNAME Full PATH,NAME of file to store trace= s" echo " Default:trace-" echo " --disable-spice disable spice" @@ -2654,7 +2654,7 @@ fi ########################################## # check if trace backend exists =20 -sh "$source_path/scripts/tracetool" "--$trace_backend" --check-backend >= /dev/null 2> /dev/null +$python "$source_path/scripts/tracetool.py" "--backend=3D$trace_backend"= --check-backend > /dev/null 2> /dev/null if test "$?" -ne 0 ; then echo echo "Error: invalid trace backend" diff --git a/scripts/tracetool b/scripts/tracetool deleted file mode 100755 index 65bd0a1..0000000 --- a/scripts/tracetool +++ /dev/null @@ -1,648 +0,0 @@ -#!/bin/sh -# -# Code generator for trace events -# -# Copyright IBM, Corp. 2010 -# -# This work is licensed under the terms of the GNU GPL, version 2. See -# the COPYING file in the top-level directory. - -# Disable pathname expansion, makes processing text with '*' characters = simpler -set -f - -usage() -{ - cat >&2 < return 0 if property is present, or 1 otherwise -has_property() -{ - local props prop - props=3D${1%%\(*} - props=3D${props% *} - for prop in $props; do - if [ "$prop" =3D "$2" ]; then - return 0 - fi - done - return 1 -} - -# Get the argument list of a trace event, including types and names -get_args() -{ - local args - args=3D${1#*\(} - args=3D${args%%\)*} - echo "$args" -} - -# Get the argument name list of a trace event -get_argnames() -{ - local nfields field name sep - nfields=3D0 - sep=3D"$2" - for field in $(get_args "$1"); do - nfields=3D$((nfields + 1)) - - # Drop pointer star - field=3D${field#\*} - - # Only argument names have commas at the end - name=3D${field%,} - test "$field" =3D "$name" && continue - - printf "%s%s " $name $sep - done - - # Last argument name - if [ "$nfields" -gt 1 ] - then - printf "%s" "$name" - fi -} - -# Get the number of arguments to a trace event -get_argc() -{ - local name argc - argc=3D0 - for name in $(get_argnames "$1", ","); do - argc=3D$((argc + 1)) - done - echo $argc -} - -# Get the format string including double quotes for a trace event -get_fmt() -{ - puts "${1#*)}" -} - -linetoh_begin_nop() -{ - return -} - -linetoh_nop() -{ - local name args - name=3D$(get_name "$1") - args=3D$(get_args "$1") - - # Define an empty function for the trace event - cat < -#include "trace/stderr.h" - -extern TraceEvent trace_list[]; -EOF - - stderr_event_num=3D0 -} - -linetoh_stderr() -{ - local name args argnames argc fmt - name=3D$(get_name "$1") - args=3D$(get_args "$1") - argnames=3D$(get_argnames "$1" ",") - argc=3D$(get_argc "$1") - fmt=3D$(get_fmt "$1") - - if [ "$argc" -gt 0 ]; then - argnames=3D", $argnames" - fi - - cat <" - ust_clean_namespace -} - -linetoh_ust() -{ - local name args argnames - name=3D$(get_name "$1") - args=3D$(get_args "$1") - argnames=3D$(get_argnames "$1", ",") - - cat < -$(ust_clean_namespace) -#include "trace.h" -EOF -} - -linetoc_ust() -{ - local name args argnames fmt - name=3D$(get_name "$1") - args=3D$(get_args "$1") - argnames=3D$(get_argnames "$1", ",") - [ -z "$argnames" ] || argnames=3D", $argnames" - fmt=3D$(get_fmt "$1") - - cat <" +__copyright__ =3D "Copyright 2012, Llu=C3=ADs Vilanova " +__license__ =3D "GPL version 2 or (at your option) any later version" + +__maintainer__ =3D "Stefan Hajnoczi" +__email__ =3D "stefanha@linux.vnet.ibm.com" + + +import sys +import getopt + +from tracetool import error_write, out +import tracetool.backend +import tracetool.format + + +_SCRIPT =3D "" + +def error_opt(msg =3D None): + if msg is not None: + error_write("Error: " + msg + "\n") + + backend_descr =3D "\n".join([ " %-15s %s" % (n, d) + for n,d in tracetool.backend.get_list() = ]) + format_descr =3D "\n".join([ " %-15s %s" % (n, d) + for n,d in tracetool.format.get_list() ]) + error_write("""\ +Usage: %(script)s --format=3D --backend=3D [] + +Backends: +%(backends)s + +Formats: +%(formats)s + +Options: + --help This help message. + --list-backends Print list of available backends. + --check-backend Check if the given backend is valid. +""" % { + "script" : _SCRIPT, + "backends" : backend_descr, + "formats" : format_descr, + }) + + if msg is None: + sys.exit(0) + else: + sys.exit(1) + + +def main(args): + global _SCRIPT + _SCRIPT =3D args[0] + + long_opts =3D [ "backend=3D", "format=3D", "help", "list-backends",= "check-backend" ] + long_opts +=3D [ "binary=3D", "target-type=3D", "target-arch=3D", "p= robe-prefix=3D" ] + + try: + opts, args =3D getopt.getopt(args[1:], "", long_opts) + except getopt.GetoptError as err: + error_opt(str(err)) + + check_backend =3D False + arg_backend =3D "" + arg_format =3D "" + for opt, arg in opts: + if opt =3D=3D "--help": + error_opt() + + elif opt =3D=3D "--backend": + arg_backend =3D arg + elif opt =3D=3D "--format": + arg_format =3D arg + + elif opt =3D=3D "--list-backends": + backends =3D tracetool.backend.get_list() + out(", ".join([ b for b,_ in backends ])) + sys.exit(0) + elif opt =3D=3D "--check-backend": + check_backend =3D True + + else: + error_opt("unhandled option: %s" % opt) + + if arg_backend is None: + error_opt("backend not set") + + if check_backend: + if tracetool.backend.exists(arg_backend): + sys.exit(0) + else: + sys.exit(1) + + try: + tracetool.generate(sys.stdin, arg_format, arg_backend) + except tracetool.TracetoolError as e: + error_opt(str(e)) + +if __name__ =3D=3D "__main__": + main(sys.argv) diff --git a/scripts/tracetool/__init__.py b/scripts/tracetool/__init__.p= y new file mode 100644 index 0000000..200cb6f --- /dev/null +++ b/scripts/tracetool/__init__.py @@ -0,0 +1,222 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +Machinery for generating tracing-related intermediate files. +""" + +__author__ =3D "Llu=C3=ADs Vilanova " +__copyright__ =3D "Copyright 2012, Llu=C3=ADs Vilanova " +__license__ =3D "GPL version 2 or (at your option) any later version" + +__maintainer__ =3D "Stefan Hajnoczi" +__email__ =3D "stefanha@linux.vnet.ibm.com" + + +import re +import sys + +import tracetool.format +import tracetool.backend + + +def error_write(*lines): + """Write a set of error lines.""" + sys.stderr.writelines("\n".join(lines) + "\n") + +def error(*lines): + """Write a set of error lines and exit.""" + error_write(*lines) + sys.exit(1) + + +def out(*lines): + """Write a set of output lines.""" + sys.stdout.writelines("\n".join(lines) + "\n") + + +class Arguments: + """Event arguments description. + + Parameters + ---------- + arg_str : str + String describing the event arguments. + """ + + def __init__ (self, arg_str): + self._args =3D [] + for arg in arg_str.split(","): + arg =3D arg.strip() + parts =3D arg.split() + head, sep, tail =3D parts[-1].rpartition("*") + parts =3D parts[:-1] + if tail =3D=3D "void": + assert len(parts) =3D=3D 0 and sep =3D=3D "" + continue + arg_type =3D " ".join(parts + [ " ".join([head, sep]).strip(= ) ]).strip() + self._args.append((arg_type, tail)) + + def __iter__(self): + """Iterate over the (type, name) pairs.""" + return iter(self._args) + + def __len__(self): + """Number of arguments.""" + return len(self._args) + + def __str__(self): + """String suitable for declaring function arguments.""" + if len(self._args) =3D=3D 0: + return "void" + else: + return ", ".join([ " ".join([t, n]) for t,n in self._args ]) + + def __repr__(self): + """Evaluable string representation for this object.""" + return "Arguments(\"%s\")" % str(self) + + def names(self): + """List of argument names.""" + return [ name for _, name in self._args ] + + def types(self): + """List of argument types.""" + return [ type_ for type_, _ in self._args ] + + +class Event(object): + """Event description. + + Parameters + ---------- + line : str + Line describing the event. + + Attributes + ---------- + name : str + The event name. + fmt : str + The event format string. + properties : set(str) + Properties of the event. + args : Arguments + The event arguments. + """ + + _CRE =3D re.compile("((?P.*)\s+)?(?P[^(\s]+)\((?P= [^)]*)\)\s*(?P\".*)?") + + _VALID_PROPS =3D set(["disable"]) + + def __init__(self, line): + m =3D self._CRE.match(line) + assert m is not None + groups =3D m.groupdict('') + self.name =3D groups["name"] + self.fmt =3D groups["fmt"] + self.properties =3D groups["props"].split() + self.args =3D Arguments(groups["args"]) + + unknown_props =3D set(self.properties) - self._VALID_PROPS + if len(unknown_props) > 0: + raise ValueError("Unknown properties: %s" % ", ".join(unknow= n_props)) + + def __repr__(self): + """Evaluable string representation for this object.""" + return "Event('%s %s(%s) %s')" % (" ".join(self.properties), + self.name, + self.args, + self.fmt) + +def _read_events(fobj): + res =3D [] + for line in fobj: + if not line.strip(): + continue + if line.lstrip().startswith('#'): + continue + res.append(Event(line)) + return res + + +class TracetoolError (Exception): + """Exception for calls to generate.""" + pass + + +def try_import(mod_name, attr_name =3D None, attr_default =3D None): + """Try to import a module and get an attribute from it. + + Parameters + ---------- + mod_name : str + Module name. + attr_name : str, optional + Name of an attribute in the module. + attr_default : optional + Default value if the attribute does not exist in the module. + + Returns + ------- + A pair indicating whether the module could be imported and the modul= e or + object or attribute value. + """ + mod_name =3D mod_name.replace("-", "_") + try: + module =3D __import__(mod_name, fromlist=3D["__package__"]) + if attr_name is None: + return True, module + return True, getattr(module, str(attr_name), attr_default) + except ImportError: + return False, None + + +def generate(fevents, format, backend): + """Generate the output for the given (format, backend) pair. + + Parameters + ---------- + fevents : file + Event description file. + format : str + Output format name. + backend : str + Output backend name. + """ + # fix strange python error (UnboundLocalError tracetool) + import tracetool + + format =3D str(format) + if len(format) is 0: + raise TracetoolError("format not set") + mformat =3D format.replace("-", "_") + if not tracetool.format.exists(mformat): + raise TracetoolError("unknown format: %s" % format) + + backend =3D str(backend) + if len(backend) is 0: + raise TracetoolError("backend not set") + mbackend =3D backend.replace("-", "_") + if not tracetool.backend.exists(mbackend): + raise TracetoolError("unknown backend: %s" % backend) + + if not tracetool.backend.compatible(mbackend, mformat): + raise TracetoolError("backend '%s' not compatible with format '%= s'" % + (backend, format)) + + events =3D _read_events(fevents) + + if backend =3D=3D "nop": + ( e.properies.add("disable") for e in events ) + + tracetool.format.generate_begin(mformat, events) + tracetool.backend.generate("nop", format, + [ e + for e in events + if "disable" in e.properties ]) + tracetool.backend.generate(backend, format, + [ e + for e in events + if "disable" not in e.properties ]) + tracetool.format.generate_end(mformat, events) diff --git a/scripts/tracetool/backend/__init__.py b/scripts/tracetool/ba= ckend/__init__.py new file mode 100644 index 0000000..891994f --- /dev/null +++ b/scripts/tracetool/backend/__init__.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +Backend management. + + +Creating new backends +--------------------- + +A new backend named 'foo-bar' corresponds to Python module +'tracetool/backend/foo_bar.py'. + +A backend module should provide a docstring, whose first non-empty line = will be +considered its short description. + +All backends must generate their contents through the 'tracetool.out' ro= utine. + + +Backend functions +----------------- + +=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D +Function Description +=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D + Called to generate the format- and backend-specific code for ea= ch of + the specified events. If the function does not exist, the backe= nd is + considered not compatible with the given format. +=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D +""" + +__author__ =3D "Llu=C3=ADs Vilanova " +__copyright__ =3D "Copyright 2012, Llu=C3=ADs Vilanova " +__license__ =3D "GPL version 2 or (at your option) any later version" + +__maintainer__ =3D "Stefan Hajnoczi" +__email__ =3D "stefanha@linux.vnet.ibm.com" + + +import pkgutil + +import tracetool + + +def get_list(): + """Get a list of (name, description) pairs.""" + res =3D [("nop", "Tracing disabled.")] + for _, modname, _ in pkgutil.iter_modules(tracetool.backend.__path__= ): + module =3D tracetool.try_import("tracetool.backend." + modname) + + # just in case; should never fail unless non-module files are pu= t there + if not module[0]: + continue + module =3D module[1] + + doc =3D module.__doc__ + if doc is None: + doc =3D "" + doc =3D doc.strip().split("\n")[0] + + name =3D modname.replace("_", "-") + res.append((name, doc)) + return res + + +def exists(name): + """Return whether the given backend exists.""" + if len(name) =3D=3D 0: + return False + name =3D name.replace("-", "_") + if name =3D=3D "nop": + return True + return tracetool.try_import("tracetool.backend." + name)[1] + + +def compatible(backend, format): + """Whether a backend is compatible with the given format.""" + if not exists(backend): + raise ValueError("unknown backend: %s" % backend) + + if backend =3D=3D "nop": + return True + else: + func =3D tracetool.try_import("tracetool.backend." + backend, + format, None)[1] + return func is not None + + +def _empty(events): + pass + +def generate(backend, format, events): + """Generate the per-event output for the given (backend, format) pai= r.""" + if not compatible(backend, format): + raise ValueError("backend '%s' not compatible with format '%s'" = % + (backend, format)) + + if backend =3D=3D "nop": + func =3D tracetool.try_import("tracetool.format." + format, + "nop", _empty)[1] + else: + func =3D tracetool.try_import("tracetool.backend." + backend, + format, None)[1] + + func(events) diff --git a/scripts/tracetool/format/__init__.py b/scripts/tracetool/for= mat/__init__.py new file mode 100644 index 0000000..174777f --- /dev/null +++ b/scripts/tracetool/format/__init__.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +Format management. + + +Creating new formats +-------------------- + +A new format named 'foo-bar' corresponds to Python module +'tracetool/format/foo_bar.py'. + +A format module should provide a docstring, whose first non-empty line w= ill be +considered its short description. + +All formats must generate their contents through the 'tracetool.out' rou= tine. + + +Format functions +---------------- + +All the following functions are optional, and no output will be generate= d if +they do not exist. + +=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D +Function Description +=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D +begin Called to generate the format-specific file header. +end Called to generate the format-specific file footer. +nop Called to generate the per-event contents when the event is dis= abled or + the selected backend is 'nop'. +=3D=3D=3D=3D=3D=3D=3D=3D =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D +""" + +__author__ =3D "Llu=C3=ADs Vilanova " +__copyright__ =3D "Copyright 2012, Llu=C3=ADs Vilanova " +__license__ =3D "GPL version 2 or (at your option) any later version" + +__maintainer__ =3D "Stefan Hajnoczi" +__email__ =3D "stefanha@linux.vnet.ibm.com" + + +import pkgutil + +import tracetool + + +def get_list(): + """Get a list of (name, description) pairs.""" + res =3D [] + for _, modname, _ in pkgutil.iter_modules(tracetool.format.__path__)= : + module =3D tracetool.try_import("tracetool.format." + modname) + + # just in case; should never fail unless non-module files are pu= t there + if not module[0]: + continue + module =3D module[1] + + doc =3D module.__doc__ + if doc is None: + doc =3D "" + doc =3D doc.strip().split("\n")[0] + + name =3D modname.replace("_", "-") + res.append((name, doc)) + return res + + +def exists(name): + """Return whether the given format exists.""" + if len(name) =3D=3D 0: + return False + return tracetool.try_import("tracetool.format." + name)[1] + + +def _empty(events): + pass + +def generate_begin(name, events): + """Generate the header of the format-specific file.""" + if not exists(name): + raise ValueError("unknown format: %s" % name) + + func =3D tracetool.try_import("tracetool.format." + name, + "begin", _empty)[1] + func(events) + +def generate_end(name, events): + """Generate the footer of the format-specific file.""" + if not exists(name): + raise ValueError("unknown format: %s" % name) + + func =3D tracetool.try_import("tracetool.format." + name, + "end", _empty)[1] + func(events)