qemu-img: Fix qemu-img convert -obacking_file
[qemu.git] / tracetool
blob701085837f6b83f68fbdde9c54751d2aaec3db18
1 #!/bin/sh
3 # Code generator for trace events
5 # Copyright IBM, Corp. 2010
7 # This work is licensed under the terms of the GNU GPL, version 2. See
8 # the COPYING file in the top-level directory.
10 # Disable pathname expansion, makes processing text with '*' characters simpler
11 set -f
13 usage()
15 cat >&2 <<EOF
16 usage: $0 [--nop | --simple | --ust] [-h | -c]
17 Generate tracing code for a file on stdin.
19 Backends:
20 --nop Tracing disabled
21 --simple Simple built-in backend
22 --ust LTTng User Space Tracing backend
24 Output formats:
25 -h Generate .h file
26 -c Generate .c file
27 EOF
28 exit 1
31 # Get the name of a trace event
32 get_name()
34 echo ${1%%\(*}
37 # Get the argument list of a trace event, including types and names
38 get_args()
40 local args
41 args=${1#*\(}
42 args=${args%\)*}
43 echo "$args"
46 # Get the argument name list of a trace event
47 get_argnames()
49 local nfields field name
50 nfields=0
51 for field in $(get_args "$1"); do
52 nfields=$((nfields + 1))
54 # Drop pointer star
55 field=${field#\*}
57 # Only argument names have commas at the end
58 name=${field%,}
59 test "$field" = "$name" && continue
61 printf "%s" "$name, "
62 done
64 # Last argument name
65 if [ "$nfields" -gt 1 ]
66 then
67 printf "%s" "$name"
71 # Get the number of arguments to a trace event
72 get_argc()
74 local name argc
75 argc=0
76 for name in $(get_argnames "$1"); do
77 argc=$((argc + 1))
78 done
79 echo $argc
82 # Get the format string for a trace event
83 get_fmt()
85 local fmt
86 fmt=${1#*\"}
87 fmt=${fmt%\"*}
88 echo "$fmt"
91 # Get the state of a trace event
92 get_state()
94 local str disable state
95 str=$(get_name "$1")
96 disable=${str##disable }
97 if [ "$disable" = "$str" ] ; then
98 state=1
99 else
100 state=0
102 echo "$state"
105 linetoh_begin_nop()
107 return
110 linetoh_nop()
112 local name args
113 name=$(get_name "$1")
114 args=$(get_args "$1")
116 # Define an empty function for the trace event
117 cat <<EOF
118 static inline void trace_$name($args)
124 linetoh_end_nop()
126 return
129 linetoc_begin_nop()
131 return
134 linetoc_nop()
136 # No need for function definitions in nop backend
137 return
140 linetoc_end_nop()
142 return
145 linetoh_begin_simple()
147 cat <<EOF
148 #include "simpletrace.h"
151 simple_event_num=0
154 cast_args_to_uint64_t()
156 local arg
157 for arg in $(get_argnames "$1"); do
158 printf "%s" "(uint64_t)(uintptr_t)$arg"
159 done
162 linetoh_simple()
164 local name args argc trace_args state
165 name=$(get_name "$1")
166 args=$(get_args "$1")
167 argc=$(get_argc "$1")
168 state=$(get_state "$1")
169 if [ "$state" = "0" ]; then
170 name=${name##disable }
173 trace_args="$simple_event_num"
174 if [ "$argc" -gt 0 ]
175 then
176 trace_args="$trace_args, $(cast_args_to_uint64_t "$1")"
179 cat <<EOF
180 static inline void trace_$name($args)
182 trace$argc($trace_args);
186 simple_event_num=$((simple_event_num + 1))
189 linetoh_end_simple()
191 cat <<EOF
192 #define NR_TRACE_EVENTS $simple_event_num
193 extern TraceEvent trace_list[NR_TRACE_EVENTS];
197 linetoc_begin_simple()
199 cat <<EOF
200 #include "trace.h"
202 TraceEvent trace_list[] = {
204 simple_event_num=0
208 linetoc_simple()
210 local name state
211 name=$(get_name "$1")
212 state=$(get_state "$1")
213 if [ "$state" = "0" ] ; then
214 name=${name##disable }
216 cat <<EOF
217 {.tp_name = "$name", .state=$state},
219 simple_event_num=$((simple_event_num + 1))
222 linetoc_end_simple()
224 cat <<EOF
229 # Clean up after UST headers which pollute the namespace
230 ust_clean_namespace() {
231 cat <<EOF
232 #undef mutex_lock
233 #undef mutex_unlock
234 #undef inline
235 #undef wmb
239 linetoh_begin_ust()
241 echo "#include <ust/tracepoint.h>"
242 ust_clean_namespace
245 linetoh_ust()
247 local name args argnames
248 name=$(get_name "$1")
249 args=$(get_args "$1")
250 argnames=$(get_argnames "$1")
252 cat <<EOF
253 DECLARE_TRACE(ust_$name, TP_PROTO($args), TP_ARGS($argnames));
254 #define trace_$name trace_ust_$name
258 linetoh_end_ust()
260 return
263 linetoc_begin_ust()
265 cat <<EOF
266 #include <ust/marker.h>
267 $(ust_clean_namespace)
268 #include "trace.h"
272 linetoc_ust()
274 local name args argnames fmt
275 name=$(get_name "$1")
276 args=$(get_args "$1")
277 argnames=$(get_argnames "$1")
278 fmt=$(get_fmt "$1")
280 cat <<EOF
281 DEFINE_TRACE(ust_$name);
283 static void ust_${name}_probe($args)
285 trace_mark(ust, $name, "$fmt", $argnames);
289 # Collect names for later
290 names="$names $name"
293 linetoc_end_ust()
295 cat <<EOF
296 static void __attribute__((constructor)) trace_init(void)
300 for name in $names; do
301 cat <<EOF
302 register_trace_ust_$name(ust_${name}_probe);
304 done
306 echo "}"
309 # Process stdin by calling begin, line, and end functions for the backend
310 convert()
312 local begin process_line end str disable
313 begin="lineto$1_begin_$backend"
314 process_line="lineto$1_$backend"
315 end="lineto$1_end_$backend"
317 "$begin"
319 while read -r str; do
320 # Skip comments and empty lines
321 test -z "${str%%#*}" && continue
323 # Process the line. The nop backend handles disabled lines.
324 disable=${str%%disable *}
325 echo
326 if test -z "$disable"; then
327 # Pass the disabled state as an arg to lineto$1_simple().
328 # For all other cases, call lineto$1_nop()
329 if [ $backend = "simple" ]; then
330 "$process_line" "$str"
331 else
332 "lineto$1_nop" "${str##disable }"
334 else
335 "$process_line" "$str"
337 done
339 echo
340 "$end"
343 tracetoh()
345 cat <<EOF
346 #ifndef TRACE_H
347 #define TRACE_H
349 /* This file is autogenerated by tracetool, do not edit. */
351 #include "qemu-common.h"
353 convert h
354 echo "#endif /* TRACE_H */"
357 tracetoc()
359 echo "/* This file is autogenerated by tracetool, do not edit. */"
360 convert c
363 # Choose backend
364 case "$1" in
365 "--nop" | "--simple" | "--ust") backend="${1#--}" ;;
366 *) usage ;;
367 esac
368 shift
370 case "$1" in
371 "-h") tracetoh ;;
372 "-c") tracetoc ;;
373 "--check-backend") exit 0 ;; # used by ./configure to test for backend
374 *) usage ;;
375 esac
377 exit 0