Message ID | 1308018686-8235-13-git-send-email-mdroth@linux.vnet.ibm.com |
---|---|
State | New |
Headers | show |
On Mon, 13 Jun 2011 21:31:17 -0500 Michael Roth <mdroth@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 <mdroth@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 <aliguori@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()
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 <aliguori@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 */ + +#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()
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 <mdroth@linux.vnet.ibm.com> --- scripts/qapi-types.py | 230 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 230 insertions(+), 0 deletions(-) create mode 100644 scripts/qapi-types.py