diff options
Diffstat (limited to 'scripts')
-rwxr-xr-x | scripts/cleanup-trace-events.pl | 51 | ||||
-rwxr-xr-x | scripts/create_config | 26 | ||||
-rw-r--r-- | scripts/qapi-commands.py | 17 | ||||
-rw-r--r-- | scripts/qapi-types.py | 118 | ||||
-rw-r--r-- | scripts/qapi-visit.py | 219 | ||||
-rw-r--r-- | scripts/qapi.py | 295 | ||||
-rwxr-xr-x | scripts/tracetool.py | 18 |
7 files changed, 584 insertions, 160 deletions
diff --git a/scripts/cleanup-trace-events.pl b/scripts/cleanup-trace-events.pl new file mode 100755 index 0000000000..cffbf165dc --- /dev/null +++ b/scripts/cleanup-trace-events.pl @@ -0,0 +1,51 @@ +#!/usr/bin/perl +# Copyright (C) 2013 Red Hat, Inc. +# +# Authors: +# Markus Armbruster <armbru@redhat.com> +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. + +# Usage: cleanup-trace-events.pl trace-events +# +# Print cleaned up trace-events to standard output. + +use warnings; +use strict; + +my $buf = ''; +my %seen = (); + +sub out { + print $buf; + $buf = ''; + %seen = (); +} + +while (<>) { + if (/^(disable )?([a-z_0-9]+)\(/) { + open GREP, '-|', 'git', 'grep', '-l', "trace_$2" + or die "run git grep: $!"; + my $fname; + while ($fname = <GREP>) { + chomp $fname; + next if $seen{$fname} || $fname eq 'trace-events'; + $seen{$fname} = 1; + $buf = "# $fname\n" . $buf; + } + unless (close GREP) { + die "close git grep: $!" + if $!; + next; + } + } elsif (/^# ([^ ]*\.[ch])$/) { + out; + next; + } elsif (!/^#|^$/) { + warn "unintelligible line"; + } + $buf .= $_; +} + +out; diff --git a/scripts/create_config b/scripts/create_config index c471e8caf9..b1adbf5897 100755 --- a/scripts/create_config +++ b/scripts/create_config @@ -34,8 +34,15 @@ case $line in done echo "" ;; - CONFIG_BDRV_WHITELIST=*) - echo "#define CONFIG_BDRV_WHITELIST \\" + CONFIG_BDRV_RW_WHITELIST=*) + echo "#define CONFIG_BDRV_RW_WHITELIST\\" + for drv in ${line#*=}; do + echo " \"${drv}\",\\" + done + echo " NULL" + ;; + CONFIG_BDRV_RO_WHITELIST=*) + echo "#define CONFIG_BDRV_RO_WHITELIST\\" for drv in ${line#*=}; do echo " \"${drv}\",\\" done @@ -70,16 +77,10 @@ case $line in value=${line#*=} echo "#define $name $value" ;; - TARGET_ARCH=*) # configuration - target_arch=${line#*=} - echo "#define TARGET_ARCH \"$target_arch\"" - ;; TARGET_BASE_ARCH=*) # configuration target_base_arch=${line#*=} - if [ "$target_base_arch" != "$target_arch" ]; then - base_arch_name=`echo $target_base_arch | LC_ALL=C tr '[a-z]' '[A-Z]'` - echo "#define TARGET_$base_arch_name 1" - fi + base_arch_name=`echo $target_base_arch | LC_ALL=C tr '[a-z]' '[A-Z]'` + echo "#define TARGET_$base_arch_name 1" ;; TARGET_XML_FILES=*) # do nothing @@ -87,8 +88,9 @@ case $line in TARGET_ABI_DIR=*) # do nothing ;; - TARGET_ARCH2=*) - # do nothing + TARGET_NAME=*) + target_name=${line#*=} + echo "#define TARGET_NAME \"$target_name\"" ;; TARGET_DIRS=*) # do nothing diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py index e06332bd55..b12b6964ef 100644 --- a/scripts/qapi-commands.py +++ b/scripts/qapi-commands.py @@ -128,12 +128,15 @@ bool has_%(argname)s = false; def gen_visitor_input_block(args, obj, dealloc=False): ret = "" + errparg = 'errp' + if len(args) == 0: return ret push_indent() if dealloc: + errparg = 'NULL' ret += mcgen(''' md = qapi_dealloc_visitor_new(); v = qapi_dealloc_get_visitor(md); @@ -148,22 +151,22 @@ v = qmp_input_get_visitor(mi); for argname, argtype, optional, structured in parse_args(args): if optional: ret += mcgen(''' -visit_start_optional(v, &has_%(c_name)s, "%(name)s", errp); +visit_start_optional(v, &has_%(c_name)s, "%(name)s", %(errp)s); if (has_%(c_name)s) { ''', - c_name=c_var(argname), name=argname) + c_name=c_var(argname), name=argname, errp=errparg) push_indent() ret += mcgen(''' -%(visitor)s(v, &%(c_name)s, "%(name)s", errp); +%(visitor)s(v, &%(c_name)s, "%(name)s", %(errp)s); ''', c_name=c_var(argname), name=argname, argtype=argtype, - visitor=type_visitor(argtype)) + visitor=type_visitor(argtype), errp=errparg) if optional: pop_indent() ret += mcgen(''' } -visit_end_optional(v, errp); -''') +visit_end_optional(v, %(errp)s); +''', errp=errparg) if dealloc: ret += mcgen(''' @@ -194,7 +197,7 @@ static void qmp_marshal_output_%(c_name)s(%(c_ret_type)s ret_in, QObject **ret_o } qmp_output_visitor_cleanup(mo); v = qapi_dealloc_get_visitor(md); - %(visitor)s(v, &ret_in, "unused", errp); + %(visitor)s(v, &ret_in, "unused", NULL); qapi_dealloc_visitor_cleanup(md); } ''', diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py index 9e19920970..5ee46ea1b3 100644 --- a/scripts/qapi-types.py +++ b/scripts/qapi-types.py @@ -16,13 +16,32 @@ import os import getopt import errno -def generate_fwd_struct(name, members): +def generate_fwd_struct(name, members, builtin_type=False): + if builtin_type: + return mcgen(''' + +typedef struct %(name)sList +{ + union { + %(type)s value; + uint64_t padding; + }; + struct %(name)sList *next; +} %(name)sList; +''', + type=c_type(name), + name=name) + return mcgen(''' + typedef struct %(name)s %(name)s; typedef struct %(name)sList { - %(name)s *value; + union { + %(name)s *value; + uint64_t padding; + }; struct %(name)sList *next; } %(name)sList; ''', @@ -131,7 +150,48 @@ typedef enum %(name)s return lookup_decl + enum_decl -def generate_union(name, typeinfo): +def generate_anon_union_qtypes(expr): + + name = expr['union'] + members = expr['data'] + + ret = mcgen(''' +const int %(name)s_qtypes[QTYPE_MAX] = { +''', + name=name) + + for key in members: + qapi_type = members[key] + if builtin_type_qtypes.has_key(qapi_type): + qtype = builtin_type_qtypes[qapi_type] + elif find_struct(qapi_type): + qtype = "QTYPE_QDICT" + elif find_union(qapi_type): + qtype = "QTYPE_QDICT" + else: + assert False, "Invalid anonymous union member" + + ret += mcgen(''' + [ %(qtype)s ] = %(abbrev)s_KIND_%(enum)s, +''', + qtype = qtype, + abbrev = de_camel_case(name).upper(), + enum = c_fun(de_camel_case(key),False).upper()) + + ret += mcgen(''' +}; +''') + return ret + + +def generate_union(expr): + + name = expr['union'] + typeinfo = expr['data'] + + base = expr.get('base') + discriminator = expr.get('discriminator') + ret = mcgen(''' struct %(name)s { @@ -150,8 +210,26 @@ struct %(name)s ret += mcgen(''' }; +''') + + if base: + base_fields = find_struct(base)['data'] + if discriminator: + base_fields = base_fields.copy() + del base_fields[discriminator] + ret += generate_struct_fields(base_fields) + else: + assert not discriminator + + ret += mcgen(''' }; ''') + if discriminator == {}: + ret += mcgen(''' +extern const int %(name)s_qtypes[]; +''', + name=name) + return ret @@ -164,6 +242,7 @@ void qapi_free_%(type)s(%(c_type)s obj); def generate_type_cleanup(name): ret = mcgen(''' + void qapi_free_%(type)s(%(c_type)s obj) { QapiDeallocVisitor *md; @@ -184,8 +263,9 @@ void qapi_free_%(type)s(%(c_type)s obj) try: - opts, args = getopt.gnu_getopt(sys.argv[1:], "chp:o:", - ["source", "header", "prefix=", "output-dir="]) + opts, args = getopt.gnu_getopt(sys.argv[1:], "chbp:o:", + ["source", "header", "builtins", + "prefix=", "output-dir="]) except getopt.GetoptError, err: print str(err) sys.exit(1) @@ -197,6 +277,7 @@ h_file = 'qapi-types.h' do_c = False do_h = False +do_builtins = False for o, a in opts: if o in ("-p", "--prefix"): @@ -207,6 +288,8 @@ for o, a in opts: do_c = True elif o in ("-h", "--header"): do_h = True + elif o in ("-b", "--builtins"): + do_builtins = True if not do_c and not do_h: do_c = True @@ -282,6 +365,11 @@ fdecl.write(mcgen(''' exprs = parse_schema(sys.stdin) exprs = filter(lambda expr: not expr.has_key('gen'), exprs) +fdecl.write(guardstart("QAPI_TYPES_BUILTIN_STRUCT_DECL")) +for typename in builtin_types: + fdecl.write(generate_fwd_struct(typename, None, builtin_type=True)) +fdecl.write(guardend("QAPI_TYPES_BUILTIN_STRUCT_DECL")) + for expr in exprs: ret = "\n" if expr.has_key('type'): @@ -294,10 +382,28 @@ for expr in exprs: ret += generate_fwd_struct(expr['union'], expr['data']) + "\n" ret += generate_enum('%sKind' % expr['union'], expr['data'].keys()) fdef.write(generate_enum_lookup('%sKind' % expr['union'], expr['data'].keys())) + if expr.get('discriminator') == {}: + fdef.write(generate_anon_union_qtypes(expr)) else: continue fdecl.write(ret) +# to avoid header dependency hell, we always generate declarations +# for built-in types in our header files and simply guard them +fdecl.write(guardstart("QAPI_TYPES_BUILTIN_CLEANUP_DECL")) +for typename in builtin_types: + fdecl.write(generate_type_cleanup_decl(typename + "List")) +fdecl.write(guardend("QAPI_TYPES_BUILTIN_CLEANUP_DECL")) + +# ...this doesn't work for cases where we link in multiple objects that +# have the functions defined, so we use -b option to provide control +# over these cases +if do_builtins: + fdef.write(guardstart("QAPI_TYPES_BUILTIN_CLEANUP_DEF")) + for typename in builtin_types: + fdef.write(generate_type_cleanup(typename + "List")) + fdef.write(guardend("QAPI_TYPES_BUILTIN_CLEANUP_DEF")) + for expr in exprs: ret = "\n" if expr.has_key('type'): @@ -307,7 +413,7 @@ for expr in exprs: ret += generate_type_cleanup_decl(expr['type']) fdef.write(generate_type_cleanup(expr['type']) + "\n") elif expr.has_key('union'): - ret += generate_union(expr['union'], expr['data']) + ret += generate_union(expr) ret += generate_type_cleanup_decl(expr['union'] + "List") fdef.write(generate_type_cleanup(expr['union'] + "List") + "\n") ret += generate_type_cleanup_decl(expr['union']) diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py index a276540a18..597cca4b66 100644 --- a/scripts/qapi-visit.py +++ b/scripts/qapi-visit.py @@ -17,34 +17,31 @@ import os import getopt import errno -def generate_visit_struct_body(field_prefix, name, members): - ret = mcgen(''' -if (!error_is_set(errp)) { -''') - push_indent() +def generate_visit_struct_fields(name, field_prefix, fn_prefix, members): + substructs = [] + ret = '' + full_name = name if not fn_prefix else "%s_%s" % (name, fn_prefix) - if len(field_prefix): - field_prefix = field_prefix + "." - ret += mcgen(''' -Error **errp = &err; /* from outer scope */ -Error *err = NULL; -visit_start_struct(m, NULL, "", "%(name)s", 0, &err); -''', - name=name) - else: - ret += mcgen(''' -Error *err = NULL; -visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), &err); -''', - name=name) + for argname, argentry, optional, structured in parse_args(members): + if structured: + if not fn_prefix: + nested_fn_prefix = argname + else: + nested_fn_prefix = "%s_%s" % (fn_prefix, argname) + + nested_field_prefix = "%s%s." % (field_prefix, argname) + ret += generate_visit_struct_fields(name, nested_field_prefix, + nested_fn_prefix, argentry) ret += mcgen(''' -if (!err) { - if (!obj || *obj) { -''') +static void visit_type_%(full_name)s_fields(Visitor *m, %(name)s ** obj, Error **errp) +{ + Error *err = NULL; +''', + name=name, full_name=full_name) push_indent() - push_indent() + for argname, argentry, optional, structured in parse_args(members): if optional: ret += mcgen(''' @@ -56,7 +53,7 @@ if (obj && (*obj)->%(prefix)shas_%(c_name)s) { push_indent() if structured: - ret += generate_visit_struct_body(field_prefix + argname, argname, argentry) + ret += generate_visit_struct_body(full_name, argname, argentry) else: ret += mcgen(''' visit_type_%(type)s(m, obj ? &(*obj)->%(c_prefix)s%(c_name)s : NULL, "%(name)s", &err); @@ -76,11 +73,43 @@ visit_end_optional(m, &err); ret += mcgen(''' error_propagate(errp, err); - err = NULL; } ''') + return ret + + +def generate_visit_struct_body(field_prefix, name, members): + ret = mcgen(''' +if (!error_is_set(errp)) { +''') + push_indent() + + full_name = name if not field_prefix else "%s_%s" % (field_prefix, name) + + if len(field_prefix): + ret += mcgen(''' +Error **errp = &err; /* from outer scope */ +Error *err = NULL; +visit_start_struct(m, NULL, "", "%(name)s", 0, &err); +''', + name=name) + else: + ret += mcgen(''' +Error *err = NULL; +visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), &err); +''', + name=name) + + ret += mcgen(''' +if (!err) { + if (!obj || *obj) { + visit_type_%(name)s_fields(m, obj, &err); + error_propagate(errp, err); + err = NULL; + } +''', + name=full_name) - pop_indent() pop_indent() ret += mcgen(''' /* Always call end_struct if start_struct succeeded. */ @@ -92,7 +121,9 @@ visit_end_optional(m, &err); return ret def generate_visit_struct(name, members): - ret = mcgen(''' + ret = generate_visit_struct_fields(name, "", "", members) + + ret += mcgen(''' void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **errp) { @@ -145,9 +176,70 @@ void visit_type_%(name)s(Visitor *m, %(name)s * obj, const char *name, Error **e ''', name=name) -def generate_visit_union(name, members): +def generate_visit_anon_union(name, members): + ret = mcgen(''' + +void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **errp) +{ + Error *err = NULL; + + if (!error_is_set(errp)) { + visit_start_implicit_struct(m, (void**) obj, sizeof(%(name)s), &err); + visit_get_next_type(m, (int*) &(*obj)->kind, %(name)s_qtypes, name, &err); + switch ((*obj)->kind) { +''', + name=name) + + for key in members: + assert (members[key] in builtin_types + or find_struct(members[key]) + or find_union(members[key])), "Invalid anonymous union member" + + ret += mcgen(''' + case %(abbrev)s_KIND_%(enum)s: + visit_type_%(c_type)s(m, &(*obj)->%(c_name)s, name, &err); + break; +''', + abbrev = de_camel_case(name).upper(), + enum = c_fun(de_camel_case(key),False).upper(), + c_type = type_name(members[key]), + c_name = c_fun(key)) + + ret += mcgen(''' + default: + abort(); + } + error_propagate(errp, err); + err = NULL; + visit_end_implicit_struct(m, &err); + } +} +''') + + return ret + + +def generate_visit_union(expr): + + name = expr['union'] + members = expr['data'] + + base = expr.get('base') + discriminator = expr.get('discriminator') + + if discriminator == {}: + assert not base + return generate_visit_anon_union(name, members) + ret = generate_visit_enum('%sKind' % name, members.keys()) + if base: + base_fields = find_struct(base)['data'] + if discriminator: + base_fields = base_fields.copy() + del base_fields[discriminator] + ret += generate_visit_struct_fields(name, "", "", base_fields) + ret += mcgen(''' void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **errp) @@ -158,23 +250,48 @@ void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error ** visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), &err); if (!err) { if (obj && *obj) { - visit_type_%(name)sKind(m, &(*obj)->kind, "type", &err); - if (!err) { - switch ((*obj)->kind) { ''', name=name) + push_indent() push_indent() + push_indent() + + if base: + ret += mcgen(''' + visit_type_%(name)s_fields(m, obj, &err); +''', + name=name) + + pop_indent() + ret += mcgen(''' + visit_type_%(name)sKind(m, &(*obj)->kind, "%(type)s", &err); + if (!err) { + switch ((*obj)->kind) { +''', + name=name, type="type" if not discriminator else discriminator) + for key in members: + if not discriminator: + fmt = 'visit_type_%(c_type)s(m, &(*obj)->%(c_name)s, "data", &err);' + else: + fmt = '''visit_start_implicit_struct(m, (void**) &(*obj)->%(c_name)s, sizeof(%(c_type)s), &err); + if (!err) { + visit_type_%(c_type)s_fields(m, &(*obj)->%(c_name)s, &err); + error_propagate(errp, err); + err = NULL; + visit_end_implicit_struct(m, &err); + }''' + ret += mcgen(''' case %(abbrev)s_KIND_%(enum)s: - visit_type_%(c_type)s(m, &(*obj)->%(c_name)s, "data", &err); + ''' + fmt + ''' break; ''', abbrev = de_camel_case(name).upper(), enum = c_fun(de_camel_case(key),False).upper(), - c_type=members[key], + c_type=type_name(members[key]), c_name=c_fun(key)) ret += mcgen(''' @@ -202,12 +319,14 @@ void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error ** return ret -def generate_declaration(name, members, genlist=True): - ret = mcgen(''' +def generate_declaration(name, members, genlist=True, builtin_type=False): + ret = "" + if not builtin_type: + ret += mcgen(''' void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **errp); ''', - name=name) + name=name) if genlist: ret += mcgen(''' @@ -235,8 +354,9 @@ void visit_type_%(name)s(Visitor *m, %(name)s * obj, const char *name, Error **e name=name) try: - opts, args = getopt.gnu_getopt(sys.argv[1:], "chp:o:", - ["source", "header", "prefix=", "output-dir="]) + opts, args = getopt.gnu_getopt(sys.argv[1:], "chbp:o:", + ["source", "header", "builtins", "prefix=", + "output-dir="]) except getopt.GetoptError, err: print str(err) sys.exit(1) @@ -248,6 +368,7 @@ h_file = 'qapi-visit.h' do_c = False do_h = False +do_builtins = False for o, a in opts: if o in ("-p", "--prefix"): @@ -258,6 +379,8 @@ for o, a in opts: do_c = True elif o in ("-h", "--header"): do_h = True + elif o in ("-b", "--builtins"): + do_builtins = True if not do_c and not do_h: do_c = True @@ -324,11 +447,29 @@ fdecl.write(mcgen(''' #include "qapi/visitor.h" #include "%(prefix)sqapi-types.h" + ''', prefix=prefix, guard=guardname(h_file))) exprs = parse_schema(sys.stdin) +# to avoid header dependency hell, we always generate declarations +# for built-in types in our header files and simply guard them +fdecl.write(guardstart("QAPI_VISIT_BUILTIN_VISITOR_DECL")) +for typename in builtin_types: + fdecl.write(generate_declaration(typename, None, genlist=True, + builtin_type=True)) +fdecl.write(guardend("QAPI_VISIT_BUILTIN_VISITOR_DECL")) + +# ...this doesn't work for cases where we link in multiple objects that +# have the functions defined, so we use -b option to provide control +# over these cases +if do_builtins: + fdef.write(guardstart("QAPI_VISIT_BUILTIN_VISITOR_DEF")) + for typename in builtin_types: + fdef.write(generate_visit_list(typename, None)) + fdef.write(guardend("QAPI_VISIT_BUILTIN_VISITOR_DEF")) + for expr in exprs: if expr.has_key('type'): ret = generate_visit_struct(expr['type'], expr['data']) @@ -338,7 +479,7 @@ for expr in exprs: ret = generate_declaration(expr['type'], expr['data']) fdecl.write(ret) elif expr.has_key('union'): - ret = generate_visit_union(expr['union'], expr['data']) + ret = generate_visit_union(expr) ret += generate_visit_list(expr['union'], expr['data']) fdef.write(ret) diff --git a/scripts/qapi.py b/scripts/qapi.py index afc5f32aeb..0ebea945bb 100644 --- a/scripts/qapi.py +++ b/scripts/qapi.py @@ -2,109 +2,189 @@ # QAPI helper library # # Copyright IBM, Corp. 2011 +# Copyright (c) 2013 Red Hat Inc. # # Authors: # Anthony Liguori <aliguori@us.ibm.com> +# Markus Armbruster <armbru@redhat.com> # # This work is licensed under the terms of the GNU GPLv2. # See the COPYING.LIB file in the top-level directory. from ordereddict import OrderedDict - -def tokenize(data): - while len(data): - ch = data[0] - data = data[1:] - if ch in ['{', '}', ':', ',', '[', ']']: - yield ch - elif ch in ' \n': - None - elif ch == "'": - string = '' - esc = False - while True: - if (data == ''): - raise Exception("Mismatched quotes") - ch = data[0] - data = data[1:] - if esc: - string += ch - esc = False - elif ch == "\\": - esc = True - elif ch == "'": - break - else: - string += ch - yield string - -def parse(tokens): - if tokens[0] == '{': - ret = OrderedDict() - tokens = tokens[1:] - while tokens[0] != '}': - key = tokens[0] - tokens = tokens[1:] - - tokens = tokens[1:] # : - - value, tokens = parse(tokens) - - if tokens[0] == ',': - tokens = tokens[1:] - - ret[key] = value - tokens = tokens[1:] - return ret, tokens - elif tokens[0] == '[': - ret = [] - tokens = tokens[1:] - while tokens[0] != ']': - value, tokens = parse(tokens) - if tokens[0] == ',': - tokens = tokens[1:] - ret.append(value) - tokens = tokens[1:] - return ret, tokens - else: - return tokens[0], tokens[1:] - -def evaluate(string): - return parse(map(lambda x: x, tokenize(string)))[0] +import sys + +builtin_types = [ + 'str', 'int', 'number', 'bool', + 'int8', 'int16', 'int32', 'int64', + 'uint8', 'uint16', 'uint32', 'uint64' +] + +builtin_type_qtypes = { + 'str': 'QTYPE_QSTRING', + 'int': 'QTYPE_QINT', + 'number': 'QTYPE_QFLOAT', + 'bool': 'QTYPE_QBOOL', + 'int8': 'QTYPE_QINT', + 'int16': 'QTYPE_QINT', + 'int32': 'QTYPE_QINT', + 'int64': 'QTYPE_QINT', + 'uint8': 'QTYPE_QINT', + 'uint16': 'QTYPE_QINT', + 'uint32': 'QTYPE_QINT', + 'uint64': 'QTYPE_QINT', +} + +class QAPISchemaError(Exception): + def __init__(self, schema, msg): + self.fp = schema.fp + self.msg = msg + self.line = self.col = 1 + for ch in schema.src[0:schema.pos]: + if ch == '\n': + self.line += 1 + self.col = 1 + elif ch == '\t': + self.col = (self.col + 7) % 8 + 1 + else: + self.col += 1 + + def __str__(self): + return "%s:%s:%s: %s" % (self.fp.name, self.line, self.col, self.msg) + +class QAPISchema: + + def __init__(self, fp): + self.fp = fp + self.src = fp.read() + if self.src == '' or self.src[-1] != '\n': + self.src += '\n' + self.cursor = 0 + self.exprs = [] + self.accept() + + while self.tok != None: + self.exprs.append(self.get_expr(False)) + + def accept(self): + while True: + self.tok = self.src[self.cursor] + self.pos = self.cursor + self.cursor += 1 + self.val = None + + if self.tok == '#': + self.cursor = self.src.find('\n', self.cursor) + elif self.tok in ['{', '}', ':', ',', '[', ']']: + return + elif self.tok == "'": + string = '' + esc = False + while True: + ch = self.src[self.cursor] + self.cursor += 1 + if ch == '\n': + raise QAPISchemaError(self, + 'Missing terminating "\'"') + if esc: + string += ch + esc = False + elif ch == "\\": + esc = True + elif ch == "'": + self.val = string + return + else: + string += ch + elif self.tok == '\n': + if self.cursor == len(self.src): + self.tok = None + return + elif not self.tok.isspace(): + raise QAPISchemaError(self, 'Stray "%s"' % self.tok) + + def get_members(self): + expr = OrderedDict() + if self.tok == '}': + self.accept() + return expr + if self.tok != "'": + raise QAPISchemaError(self, 'Expected string or "}"') + while True: + key = self.val + self.accept() + if self.tok != ':': + raise QAPISchemaError(self, 'Expected ":"') + self.accept() + expr[key] = self.get_expr(True) + if self.tok == '}': + self.accept() + return expr + if self.tok != ',': + raise QAPISchemaError(self, 'Expected "," or "}"') + self.accept() + if self.tok != "'": + raise QAPISchemaError(self, 'Expected string') + + def get_values(self): + expr = [] + if self.tok == ']': + self.accept() + return expr + if not self.tok in [ '{', '[', "'" ]: + raise QAPISchemaError(self, 'Expected "{", "[", "]" or string') + while True: + expr.append(self.get_expr(True)) + if self.tok == ']': + self.accept() + return expr + if self.tok != ',': + raise QAPISchemaError(self, 'Expected "," or "]"') + self.accept() + + def get_expr(self, nested): + if self.tok != '{' and not nested: + raise QAPISchemaError(self, 'Expected "{"') + if self.tok == '{': + self.accept() + expr = self.get_members() + elif self.tok == '[': + self.accept() + expr = self.get_values() + elif self.tok == "'": + expr = self.val + self.accept() + else: + raise QAPISchemaError(self, 'Expected "{", "[" or string') + return expr def parse_schema(fp): + try: + schema = QAPISchema(fp) + except QAPISchemaError as e: + print >>sys.stderr, e + exit(1) + exprs = [] - expr = '' - expr_eval = None - - for line in fp: - if line.startswith('#') or line == '\n': - continue - - if line.startswith(' '): - expr += line - elif expr: - expr_eval = evaluate(expr) - if expr_eval.has_key('enum'): - add_enum(expr_eval['enum']) - elif expr_eval.has_key('union'): - add_enum('%sKind' % expr_eval['union']) - exprs.append(expr_eval) - expr = line - else: - expr += line - if expr: - expr_eval = evaluate(expr) - if expr_eval.has_key('enum'): - add_enum(expr_eval['enum']) - elif expr_eval.has_key('union'): - add_enum('%sKind' % expr_eval['union']) - exprs.append(expr_eval) + for expr in schema.exprs: + if expr.has_key('enum'): + add_enum(expr['enum']) + elif expr.has_key('union'): + add_union(expr) + add_enum('%sKind' % expr['union']) + elif expr.has_key('type'): + add_struct(expr) + exprs.append(expr) return exprs def parse_args(typeinfo): + if isinstance(typeinfo, basestring): + struct = find_struct(typeinfo) + assert struct != None + typeinfo = struct['data'] + for member in typeinfo: argname = member argentry = typeinfo[member] @@ -174,6 +254,30 @@ def type_name(name): return name enum_types = [] +struct_types = [] +union_types = [] + +def add_struct(definition): + global struct_types + struct_types.append(definition) + +def find_struct(name): + global struct_types + for struct in struct_types: + if struct['type'] == name: + return struct + return None + +def add_union(definition): + global union_types + union_types.append(definition) + +def find_union(name): + global union_types + for union in union_types: + if union['union'] == name: + return union + return None def add_enum(name): global enum_types @@ -242,3 +346,20 @@ def guardname(filename): for substr in [".", " ", "-"]: guard = guard.replace(substr, "_") return guard.upper() + '_H' + +def guardstart(name): + return mcgen(''' + +#ifndef %(name)s +#define %(name)s + +''', + name=guardname(name)) + +def guardend(name): + return mcgen(''' + +#endif /* %(name)s */ + +''', + name=guardname(name)) diff --git a/scripts/tracetool.py b/scripts/tracetool.py index a79ec0f096..5f4890f3ab 100755 --- a/scripts/tracetool.py +++ b/scripts/tracetool.py @@ -46,9 +46,9 @@ Options: --check-backend Check if the given backend is valid. --binary <path> Full path to QEMU binary. --target-type <type> QEMU emulator target type ('system' or 'user'). - --target-arch <arch> QEMU emulator target arch. + --target-name <name> QEMU emulator target name. --probe-prefix <prefix> Prefix for dtrace probe names - (default: qemu-<target-type>-<target-arch>).\ + (default: qemu-<target-type>-<target-name>).\ """ % { "script" : _SCRIPT, "backends" : backend_descr, @@ -66,7 +66,7 @@ def main(args): _SCRIPT = args[0] long_opts = [ "backend=", "format=", "help", "list-backends", "check-backend" ] - long_opts += [ "binary=", "target-type=", "target-arch=", "probe-prefix=" ] + long_opts += [ "binary=", "target-type=", "target-name=", "probe-prefix=" ] try: opts, args = getopt.getopt(args[1:], "", long_opts) @@ -78,7 +78,7 @@ def main(args): arg_format = "" binary = None target_type = None - target_arch = None + target_name = None probe_prefix = None for opt, arg in opts: if opt == "--help": @@ -100,8 +100,8 @@ def main(args): binary = arg elif opt == '--target-type': target_type = arg - elif opt == '--target-arch': - target_arch = arg + elif opt == '--target-name': + target_name = arg elif opt == '--probe-prefix': probe_prefix = arg @@ -122,11 +122,11 @@ def main(args): error_opt("--binary is required for SystemTAP tapset generator") if probe_prefix is None and target_type is None: error_opt("--target-type is required for SystemTAP tapset generator") - if probe_prefix is None and target_arch is None: - error_opt("--target-arch is required for SystemTAP tapset generator") + if probe_prefix is None and target_name is None: + error_opt("--target-name is required for SystemTAP tapset generator") if probe_prefix is None: - probe_prefix = ".".join([ "qemu", target_type, target_arch ]) + probe_prefix = ".".join([ "qemu", target_type, target_name ]) try: tracetool.generate(sys.stdin, arg_format, arg_backend, |