On Mon, 13 Jun 2011 21:31:17 -0500 Michael Roth <mdr...@linux.vnet.ibm.com> wrote:
> This is the code generator for qapi types. It will generation the > following files: > > $(prefix)qapi-types.h - C types corresponding to types defined in > the schema you pass in > $(prefix)qapi-types.c - Cleanup functions for the above C types > > The $(prefix) is used to as a namespace to keep the generated code from > one schema/code-generation separated from others so code and be > generated from multiple schemas with clobbering previously created code. > > Signed-off-by: Michael Roth <mdr...@linux.vnet.ibm.com> > --- > scripts/qapi-types.py | 230 > +++++++++++++++++++++++++++++++++++++++++++++++++ > 1 files changed, 230 insertions(+), 0 deletions(-) > create mode 100644 scripts/qapi-types.py > > diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py > new file mode 100644 > index 0000000..c8d6b2f > --- /dev/null > +++ b/scripts/qapi-types.py > @@ -0,0 +1,230 @@ > +# > +# QAPI types generator > +# > +# Copyright IBM, Corp. 2011 > +# > +# Authors: > +# Anthony Liguori <aligu...@us.ibm.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 > +from qapi import * > +import sys > +import os > +import getopt > + > +def generate_fwd_struct(name, members): > + return mcgen(''' > +typedef struct %(name)s %(name)s; > + > +typedef struct %(name)sList > +{ > + %(name)s *value; > + struct %(name)sList *next; > +} %(name)sList; > +''', > + name=name) > + > +def generate_struct(structname, fieldname, members): > + ret = mcgen(''' > +struct %(name)s > +{ > +''', > + name=structname) > + > + for argname, argentry, optional, structured in parse_args(members): > + if optional: > + ret += mcgen(''' > + bool has_%(c_name)s; > +''', > + c_name=c_var(argname)) > + if structured: > + push_indent() > + ret += generate_struct("", argname, argentry) > + pop_indent() > + else: > + ret += mcgen(''' > + %(c_type)s %(c_name)s; > +''', > + c_type=c_type(argentry), c_name=c_var(argname)) > + > + if len(fieldname): > + fieldname = " " + fieldname > + ret += mcgen(''' > +}%(field)s; > +''', > + field=fieldname) > + > + return ret > + > +def generate_handle(name, typeinfo): > + return mcgen(''' > +typedef struct %(name)s > +{ > + %(c_type)s handle; > +} %(name)s; > + > +typedef struct %(name)sList > +{ > + %(name)s *value; > + struct %(name)sList *next; > +} %(name)sList; > +''', > + name=name, c_type=c_type(typeinfo)) > + > +def generate_enum(name, values): > + ret = mcgen(''' > +typedef enum %(name)s > +{ > +''', > + name=name) > + > + i = 1 > + for value in values: > + ret += mcgen(''' > + %(abbrev)s_%(value)s = %(i)d, > +''', > + abbrev=de_camel_case(name).upper(), > + value=c_var(value).upper(), > + i=i) > + i += 1 > + > + ret += mcgen(''' > +} %(name)s; > +''', > + name=name) > + > + return ret > + > +def generate_union(name, typeinfo): > + ret = mcgen(''' > +struct %(name)s > +{ > + %(name)sKind kind; > + union { > +''', > + name=name) > + > + for key in typeinfo: > + ret += mcgen(''' > + %(c_type)s %(c_name)s; > +''', > + c_type=c_type(typeinfo[key]), > + c_name=c_var(key)) > + > + ret += mcgen(''' > + }; > +}; > +''') > + > + return ret > + > +def generate_type_cleanup_decl(name): > + ret = mcgen(''' > +void qapi_free_%(type)s(%(c_type)s obj); > +''', > + c_type=c_type(name),type=name) > + return ret > + > +def generate_type_cleanup(name): > + ret = mcgen(''' > +void qapi_free_%(type)s(%(c_type)s obj) > +{ > + QapiDeallocVisitor *md; > + Visitor *v; > + > + if (!obj) { > + return; > + } > + > + md = qapi_dealloc_visitor_new(); > + v = qapi_dealloc_get_visitor(md); > + visit_type_%(type)s(v, &obj, NULL, NULL); > + qapi_dealloc_visitor_cleanup(md); > +} > +''', > + c_type=c_type(name),type=name) > + return ret > + > + > +try: > + opts, args = getopt.gnu_getopt(sys.argv[1:], "p:o:", ["prefix=", > "output-dir="]) > +except getopt.GetoptError, err: > + print str(err) > + sys.exit(1) > + > +output_dir = "" > +prefix = "" > +c_file = 'qapi-types.c' > +h_file = 'qapi-types.h' > + > +for o, a in opts: > + if o in ("-p", "--prefix"): > + prefix = a > + elif o in ("-o", "--output-dir"): > + output_dir = a + "/" > + > +c_file = output_dir + prefix + c_file > +h_file = output_dir + prefix + h_file > + > +if os.path.isdir(output_dir) == False: > + os.makedirs(output_dir) > + > +fdef = open(c_file, 'w') > +fdecl = open(h_file, 'w') > + > +fdef.write(mcgen(''' > +/* AUTOMATICALLY GENERATED, DO NOT MODIFY */ No license, I think all the code generators forget this. > + > +#include "qapi/qapi-dealloc-visitor.h" > +#include "%(prefix)sqapi-types.h" > +#include "%(prefix)sqapi-visit.h" > + > +''', prefix=prefix)) > + > +fdecl.write(mcgen(''' > +/* AUTOMATICALLY GENERATED, DO NOT MODIFY */ > +#ifndef %(guard)s > +#define %(guard)s > + > +#include "qapi/qapi-types-core.h" > +''', > + guard=guardname(h_file))) > + > +exprs = parse_schema(sys.stdin) > + > +for expr in exprs: > + ret = "\n" > + if expr.has_key('type'): > + ret += generate_fwd_struct(expr['type'], expr['data']) > + elif expr.has_key('enum'): > + ret += generate_enum(expr['enum'], expr['data']) > + elif expr.has_key('union'): > + ret += generate_fwd_struct(expr['union'], expr['data']) + "\n" > + ret += generate_enum('%sKind' % expr['union'], expr['data'].keys()) > + else: > + continue > + fdecl.write(ret) > + > +for expr in exprs: > + ret = "\n" > + if expr.has_key('type'): > + ret += generate_struct(expr['type'], "", expr['data']) + "\n" > + ret += generate_type_cleanup_decl(expr['type']) > + fdef.write(generate_type_cleanup(expr['type']) + "\n") > + elif expr.has_key('handle'): > + ret += generate_handle(expr['handle'], expr['data']) > + elif expr.has_key('union'): > + ret += generate_union(expr['union'], expr['data']) > + else: > + continue > + fdecl.write(ret) > + > +fdecl.write(''' > +#endif > +''') > + > +fdecl.flush() > +fdecl.close()