diff --git a/Makefile b/Makefile
index 02698e9..2ba52aa 100644
--- a/Makefile
+++ b/Makefile
@@ -110,12 +110,12 @@ bt-host.o: QEMU_CFLAGS += $(BLUEZ_CFLAGS)
 
 trace.h: trace.h-timestamp
 trace.h-timestamp: $(SRC_PATH)/trace-events config-host.mak
-	$(call quiet-command,sh $(SRC_PATH)/tracetool --$(TRACE_BACKEND) -h < $< > $@,"  GEN   trace.h")
+	$(call quiet-command,sh $(SRC_PATH)/tracetool --regular --$(TRACE_BACKEND) -h < $< > $@,"  GEN   trace.h")
 	@cmp -s $@ trace.h || cp $@ trace.h
 
 trace.c: trace.c-timestamp
 trace.c-timestamp: $(SRC_PATH)/trace-events config-host.mak
-	$(call quiet-command,sh $(SRC_PATH)/tracetool --$(TRACE_BACKEND) -c < $< > $@,"  GEN   trace.c")
+	$(call quiet-command,sh $(SRC_PATH)/tracetool --regular --$(TRACE_BACKEND) -c < $< > $@,"  GEN   trace.c")
 	@cmp -s $@ trace.c || cp $@ trace.c
 
 trace.o: trace.c $(GENERATED_HEADERS)
diff --git a/tracetool b/tracetool
index 7010858..c5ae6a7 100755
--- a/tracetool
+++ b/tracetool
@@ -10,28 +10,32 @@
 # Disable pathname expansion, makes processing text with '*' characters simpler
 set -f
 
-usage()
-{
-    cat >&2 <<EOF
-usage: $0 [--nop | --simple | --ust] [-h | -c]
-Generate tracing code for a file on stdin.
+################################################################################
+### Helper routines
 
-Backends:
-  --nop     Tracing disabled
-  --simple  Simple built-in backend
-  --ust     LTTng User Space Tracing backend
+# Get the name of a trace event
+get_event_name()
+{
+    local str i last
+    str=${1%%\(*}
+    str=${str##* }
+    echo "$str"
+}
 
-Output formats:
-  -h    Generate .h file
-  -c    Generate .c file
-EOF
-    exit 1
+# Get the name of the backend-specific function recording the trace event
+get_func_name()
+{
+    local name
+    name=$(get_event_name "$1")
+    echo "trace_${name}_backend"
 }
 
-# Get the name of a trace event
-get_name()
+# Get the name of the public function recording the trace event
+get_api_name()
 {
-    echo ${1%%\(*}
+    local event
+    event=trace_$(get_event_name "$1")
+    echo "$event"
 }
 
 # Get the argument list of a trace event, including types and names
@@ -79,6 +83,21 @@ get_argc()
     echo $argc
 }
 
+# See if an event property is set (returns "1" or "0")
+get_property()
+{
+    local i str prop
+    str=${1%%\(*}
+    prop="$2"
+    for i in $str; do
+        if [ "$i" = "$prop" ] ; then
+            echo "1"
+            return
+        fi
+    done
+    echo "0"
+}
+
 # Get the format string for a trace event
 get_fmt()
 {
@@ -88,70 +107,60 @@ get_fmt()
     echo "$fmt"
 }
 
-# Get the state of a trace event
-get_state()
-{
-    local str disable state
-    str=$(get_name "$1")
-    disable=${str##disable }
-    if [ "$disable" = "$str" ] ; then
-        state=1
-    else
-        state=0
-    fi
-    echo "$state"
-}
+################################################################################
+### Backend code
 
-linetoh_begin_nop()
+### nop -- H
+begin_h_nop()
 {
     return
 }
 
-linetoh_nop()
+line_h_nop()
 {
-    local name args
-    name=$(get_name "$1")
+    local func args
+    func=$(get_func_name "$1")
     args=$(get_args "$1")
 
     # Define an empty function for the trace event
     cat <<EOF
-static inline void trace_$name($args)
+static inline void $func($args)
 {
 }
 EOF
 }
 
-linetoh_end_nop()
+end_h_nop()
 {
     return
 }
 
-linetoc_begin_nop()
+### nop -- H
+begin_c_nop()
 {
     return
 }
 
-linetoc_nop()
+line_c_nop()
 {
-    # No need for function definitions in nop backend
     return
 }
 
-linetoc_end_nop()
+end_c_nop()
 {
     return
 }
 
-linetoh_begin_simple()
+### simple -- H
+begin_h_simple()
 {
     cat <<EOF
 #include "simpletrace.h"
 EOF
-
     simple_event_num=0
 }
 
-cast_args_to_uint64_t()
+get_trace_args_simple()
 {
     local arg
     for arg in $(get_argnames "$1"); do
@@ -159,25 +168,22 @@ cast_args_to_uint64_t()
     done
 }
 
-linetoh_simple()
+line_h_simple()
 {
-    local name args argc trace_args state
-    name=$(get_name "$1")
+    # XXX: why 'simple' backend does not expand into 'nop' when disabled?
+    local func args argc trace_args
+    func=$(get_func_name "$1")
     args=$(get_args "$1")
     argc=$(get_argc "$1")
-    state=$(get_state "$1")
-    if [ "$state" = "0" ]; then
-        name=${name##disable }
-    fi
-
+    
     trace_args="$simple_event_num"
     if [ "$argc" -gt 0 ]
     then
-        trace_args="$trace_args, $(cast_args_to_uint64_t "$1")"
+        trace_args="$trace_args, $(get_trace_args_simple "$1")"
     fi
 
     cat <<EOF
-static inline void trace_$name($args)
+static inline void $func($args)
 {
     trace$argc($trace_args);
 }
@@ -186,7 +192,7 @@ EOF
     simple_event_num=$((simple_event_num + 1))
 }
 
-linetoh_end_simple()
+end_h_simple()
 {
     cat <<EOF
 #define NR_TRACE_EVENTS $simple_event_num
@@ -194,7 +200,8 @@ extern TraceEvent trace_list[NR_TRACE_EVENTS];
 EOF
 }
 
-linetoc_begin_simple()
+### simple -- C
+begin_c_simple()
 {
     cat <<EOF
 #include "trace.h"
@@ -202,30 +209,36 @@ linetoc_begin_simple()
 TraceEvent trace_list[] = {
 EOF
     simple_event_num=0
-
 }
 
-linetoc_simple()
+line_c_simple()
 {
-    local name state
-    name=$(get_name "$1")
-    state=$(get_state "$1")
-    if [ "$state" = "0" ] ; then
-        name=${name##disable }
-    fi
+    # XXX: why 'simple' backend does not expand into 'nop' when disabled?
+    local name disable state
+    name=$(get_event_name "$1")
+    disable=$(get_property "$1" "disable")
+
+    case "$disable" in
+        "0") state="1" ;;
+        "1") state="0" ;;
+    esac
+
     cat <<EOF
 {.tp_name = "$name", .state=$state},
 EOF
+
     simple_event_num=$((simple_event_num + 1))
 }
 
-linetoc_end_simple()
+end_c_simple()
 {
     cat <<EOF
 };
 EOF
 }
 
+### ust -- H
+
 # Clean up after UST headers which pollute the namespace
 ust_clean_namespace() {
     cat <<EOF
@@ -236,31 +249,40 @@ ust_clean_namespace() {
 EOF
 }
 
-linetoh_begin_ust()
+begin_h_ust()
 {
     echo "#include <ust/tracepoint.h>"
     ust_clean_namespace
 }
 
-linetoh_ust()
+line_h_ust()
 {
-    local name args argnames
-    name=$(get_name "$1")
+    local disable
+    disable=$(get_property "$1" "disable")
+    if [ "$disable" = "1" ]; then
+        line_h_nop "$1"
+        return
+    fi
+
+    local name func args argnames
+    name=$(get_event_name "$1")
+    func=$(get_func_name "$1")
     args=$(get_args "$1")
     argnames=$(get_argnames "$1")
 
     cat <<EOF
 DECLARE_TRACE(ust_$name, TP_PROTO($args), TP_ARGS($argnames));
-#define trace_$name trace_ust_$name
+#define $func trace_ust_$name
 EOF
 }
 
-linetoh_end_ust()
+end_h_ust()
 {
     return
 }
 
-linetoc_begin_ust()
+### ust -- C
+begin_c_ust()
 {
     cat <<EOF
 #include <ust/marker.h>
@@ -269,17 +291,23 @@ $(ust_clean_namespace)
 EOF
 }
 
-linetoc_ust()
+line_c_ust()
 {
+    local disable
+    disable=$(get_property "$1" "disable")
+    if [ "$disable" = "1" ]; then
+        line_c_nop "$1"
+        return
+    fi
+
     local name args argnames fmt
-    name=$(get_name "$1")
+    name=$(get_event_name "$1")
     args=$(get_args "$1")
     argnames=$(get_argnames "$1")
     fmt=$(get_fmt "$1")
 
     cat <<EOF
 DEFINE_TRACE(ust_$name);
-
 static void ust_${name}_probe($args)
 {
     trace_mark(ust, $name, "$fmt", $argnames);
@@ -290,7 +318,7 @@ EOF
     names="$names $name"
 }
 
-linetoc_end_ust()
+end_c_ust()
 {
     cat <<EOF
 static void __attribute__((constructor)) trace_init(void)
@@ -306,72 +334,111 @@ EOF
     echo "}"
 }
 
-# Process stdin by calling begin, line, and end functions for the backend
+################################################################################
+### Frontend code
+
+### Regular -- H
+traceto_h_regular()
+{
+     cat <<EOF
+#ifndef TRACE_H
+#define TRACE_H
+
+/* This file is autogenerated by tracetool, do not edit. */
+
+#include "qemu-common.h"
+EOF
+    convert h $1 $2
+    echo "#endif /* TRACE_H */"
+}
+
+line_h_regular()
+{
+    local api func
+    api=$(get_api_name "$1")
+    func=$(get_func_name "$1")
+    echo "#define $api $func"
+}
+
+### Regular -- C
+traceto_c_regular()
+{
+    echo "/* This file is autogenerated by tracetool, do not edit. */"
+    convert c $1 $2
+}
+
+line_c_regular()
+{
+    return
+}
+
+################################################################################
+### Generic code
+
+# Process stdin by calling the backend/frontend specfic routines
 convert()
 {
-    local begin process_line end str disable
-    begin="lineto$1_begin_$backend"
-    process_line="lineto$1_$backend"
-    end="lineto$1_end_$backend"
+    local str
 
-    "$begin"
+    begin_$1_$3
+    echo
 
     while read -r str; do
         # Skip comments and empty lines
         test -z "${str%%#*}" && continue
 
-        # Process the line.  The nop backend handles disabled lines.
-        disable=${str%%disable *}
-        echo
-        if test -z "$disable"; then
-            # Pass the disabled state as an arg to lineto$1_simple().
-            # For all other cases, call lineto$1_nop()
-            if [ $backend = "simple" ]; then
-                "$process_line" "$str"
-            else
-                "lineto$1_nop" "${str##disable }"
-            fi
-        else
-            "$process_line" "$str"
-        fi
+        "line_$1_$3" "$str"
+        "line_$1_$2" "$str"
     done
 
     echo
-    "$end"
+    end_$1_$3
 }
 
-tracetoh()
+################################################################################
+### Argument parsing
+
+frontend=nil
+backend=nil
+output=nil
+
+usage()
 {
-    cat <<EOF
-#ifndef TRACE_H
-#define TRACE_H
+    cat >&2 <<EOF
+usage: $0 <frontend> <backend> <output>
+Generate tracing code for a file on stdin.
 
-/* This file is autogenerated by tracetool, do not edit. */
+Frontends:
+  --regular     Regular frontend
 
-#include "qemu-common.h"
+Backends:
+  --nop         Tracing disabled
+  --simple      Simple built-in backend
+  --ust         LTTng User Space Tracing backend
+
+Output formats:
+  -h            Generate .h file
+  -c            Generate .c file
 EOF
-    convert h
-    echo "#endif /* TRACE_H */"
+    exit 1
 }
 
-tracetoc()
-{
-    echo "/* This file is autogenerated by tracetool, do not edit. */"
-    convert c
-}
-
-# Choose backend
-case "$1" in
-"--nop" | "--simple" | "--ust") backend="${1#--}" ;;
-*) usage ;;
-esac
-shift
-
-case "$1" in
-"-h") tracetoh ;;
-"-c") tracetoc ;;
-"--check-backend") exit 0 ;; # used by ./configure to test for backend
-*) usage ;;
-esac
+while [ $# -gt 0 ]; do
+    case $1 in
+        "--regular") frontend="${1#--}" ;;
+        "--nop"|"--simple"|"--ust") backend="${1#--}" ;;
+        "-h"|"-c") output="${1#-}" ;;
+        "--check-backend") check=1 ;; # used by ./configure to test for backend
+        *) usage ;;
+    esac
+    shift
+done
+
+if [ "$check" = "1" ]; then
+    [ "$backend" != "nil" ] || exit 1
+    exit 0
+fi
+
+traceto_${output}_$frontend $frontend $backend
 
 exit 0
