1# 2# QAPI types generator 3# 4# Copyright IBM, Corp. 2011 5# 6# Authors: 7# Anthony Liguori <aliguori@us.ibm.com> 8# 9# This work is licensed under the terms of the GNU GPLv2. 10# See the COPYING.LIB file in the top-level directory. 11 12from ordereddict import OrderedDict 13from qapi import * 14import sys 15import os 16import getopt 17import errno 18 19def generate_fwd_struct(name, members): 20 return mcgen(''' 21typedef struct %(name)s %(name)s; 22 23typedef struct %(name)sList 24{ 25 %(name)s *value; 26 struct %(name)sList *next; 27} %(name)sList; 28''', 29 name=name) 30 31def generate_struct(structname, fieldname, members): 32 ret = mcgen(''' 33struct %(name)s 34{ 35''', 36 name=structname) 37 38 for argname, argentry, optional, structured in parse_args(members): 39 if optional: 40 ret += mcgen(''' 41 bool has_%(c_name)s; 42''', 43 c_name=c_var(argname)) 44 if structured: 45 push_indent() 46 ret += generate_struct("", argname, argentry) 47 pop_indent() 48 else: 49 ret += mcgen(''' 50 %(c_type)s %(c_name)s; 51''', 52 c_type=c_type(argentry), c_name=c_var(argname)) 53 54 if len(fieldname): 55 fieldname = " " + fieldname 56 ret += mcgen(''' 57}%(field)s; 58''', 59 field=fieldname) 60 61 return ret 62 63def generate_enum_lookup(name, values): 64 ret = mcgen(''' 65const char *%(name)s_lookup[] = { 66''', 67 name=name) 68 i = 0 69 for value in values: 70 ret += mcgen(''' 71 "%(value)s", 72''', 73 value=value) 74 75 ret += mcgen(''' 76 NULL, 77}; 78 79''') 80 return ret 81 82def generate_enum_name(name): 83 if name.isupper(): 84 return c_fun(name) 85 new_name = '' 86 for c in c_fun(name): 87 if c.isupper(): 88 new_name += '_' 89 new_name += c 90 return new_name.lstrip('_').upper() 91 92def generate_enum(name, values): 93 lookup_decl = mcgen(''' 94extern const char *%(name)s_lookup[]; 95''', 96 name=name) 97 98 enum_decl = mcgen(''' 99typedef enum %(name)s 100{ 101''', 102 name=name) 103 104 # append automatically generated _MAX value 105 enum_values = values + [ 'MAX' ] 106 107 i = 0 108 for value in enum_values: 109 enum_decl += mcgen(''' 110 %(abbrev)s_%(value)s = %(i)d, 111''', 112 abbrev=de_camel_case(name).upper(), 113 value=generate_enum_name(value), 114 i=i) 115 i += 1 116 117 enum_decl += mcgen(''' 118} %(name)s; 119''', 120 name=name) 121 122 return lookup_decl + enum_decl 123 124def generate_union(name, typeinfo): 125 ret = mcgen(''' 126struct %(name)s 127{ 128 %(name)sKind kind; 129 union { 130 void *data; 131''', 132 name=name) 133 134 for key in typeinfo: 135 ret += mcgen(''' 136 %(c_type)s %(c_name)s; 137''', 138 c_type=c_type(typeinfo[key]), 139 c_name=c_fun(key)) 140 141 ret += mcgen(''' 142 }; 143}; 144''') 145 146 return ret 147 148def generate_type_cleanup_decl(name): 149 ret = mcgen(''' 150void qapi_free_%(type)s(%(c_type)s obj); 151''', 152 c_type=c_type(name),type=name) 153 return ret 154 155def generate_type_cleanup(name): 156 ret = mcgen(''' 157void qapi_free_%(type)s(%(c_type)s obj) 158{ 159 QapiDeallocVisitor *md; 160 Visitor *v; 161 162 if (!obj) { 163 return; 164 } 165 166 md = qapi_dealloc_visitor_new(); 167 v = qapi_dealloc_get_visitor(md); 168 visit_type_%(type)s(v, &obj, NULL, NULL); 169 qapi_dealloc_visitor_cleanup(md); 170} 171''', 172 c_type=c_type(name),type=name) 173 return ret 174 175 176try: 177 opts, args = getopt.gnu_getopt(sys.argv[1:], "chp:o:", 178 ["source", "header", "prefix=", "output-dir="]) 179except getopt.GetoptError, err: 180 print str(err) 181 sys.exit(1) 182 183output_dir = "" 184prefix = "" 185c_file = 'qapi-types.c' 186h_file = 'qapi-types.h' 187 188do_c = False 189do_h = False 190 191for o, a in opts: 192 if o in ("-p", "--prefix"): 193 prefix = a 194 elif o in ("-o", "--output-dir"): 195 output_dir = a + "/" 196 elif o in ("-c", "--source"): 197 do_c = True 198 elif o in ("-h", "--header"): 199 do_h = True 200 201if not do_c and not do_h: 202 do_c = True 203 do_h = True 204 205c_file = output_dir + prefix + c_file 206h_file = output_dir + prefix + h_file 207 208try: 209 os.makedirs(output_dir) 210except os.error, e: 211 if e.errno != errno.EEXIST: 212 raise 213 214def maybe_open(really, name, opt): 215 if really: 216 return open(name, opt) 217 else: 218 import StringIO 219 return StringIO.StringIO() 220 221fdef = maybe_open(do_c, c_file, 'w') 222fdecl = maybe_open(do_h, h_file, 'w') 223 224fdef.write(mcgen(''' 225/* AUTOMATICALLY GENERATED, DO NOT MODIFY */ 226 227/* 228 * deallocation functions for schema-defined QAPI types 229 * 230 * Copyright IBM, Corp. 2011 231 * 232 * Authors: 233 * Anthony Liguori <aliguori@us.ibm.com> 234 * Michael Roth <mdroth@linux.vnet.ibm.com> 235 * 236 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. 237 * See the COPYING.LIB file in the top-level directory. 238 * 239 */ 240 241#include "qapi/qapi-dealloc-visitor.h" 242#include "%(prefix)sqapi-types.h" 243#include "%(prefix)sqapi-visit.h" 244 245''', prefix=prefix)) 246 247fdecl.write(mcgen(''' 248/* AUTOMATICALLY GENERATED, DO NOT MODIFY */ 249 250/* 251 * schema-defined QAPI types 252 * 253 * Copyright IBM, Corp. 2011 254 * 255 * Authors: 256 * Anthony Liguori <aliguori@us.ibm.com> 257 * 258 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. 259 * See the COPYING.LIB file in the top-level directory. 260 * 261 */ 262 263#ifndef %(guard)s 264#define %(guard)s 265 266#include "qemu-common.h" 267 268''', 269 guard=guardname(h_file))) 270 271exprs = parse_schema(sys.stdin) 272exprs = filter(lambda expr: not expr.has_key('gen'), exprs) 273 274for expr in exprs: 275 ret = "\n" 276 if expr.has_key('type'): 277 ret += generate_fwd_struct(expr['type'], expr['data']) 278 elif expr.has_key('enum'): 279 ret += generate_enum(expr['enum'], expr['data']) 280 fdef.write(generate_enum_lookup(expr['enum'], expr['data'])) 281 elif expr.has_key('union'): 282 ret += generate_fwd_struct(expr['union'], expr['data']) + "\n" 283 ret += generate_enum('%sKind' % expr['union'], expr['data'].keys()) 284 fdef.write(generate_enum_lookup('%sKind' % expr['union'], expr['data'].keys())) 285 else: 286 continue 287 fdecl.write(ret) 288 289for expr in exprs: 290 ret = "\n" 291 if expr.has_key('type'): 292 ret += generate_struct(expr['type'], "", expr['data']) + "\n" 293 ret += generate_type_cleanup_decl(expr['type'] + "List") 294 fdef.write(generate_type_cleanup(expr['type'] + "List") + "\n") 295 ret += generate_type_cleanup_decl(expr['type']) 296 fdef.write(generate_type_cleanup(expr['type']) + "\n") 297 elif expr.has_key('union'): 298 ret += generate_union(expr['union'], expr['data']) 299 ret += generate_type_cleanup_decl(expr['union'] + "List") 300 fdef.write(generate_type_cleanup(expr['union'] + "List") + "\n") 301 ret += generate_type_cleanup_decl(expr['union']) 302 fdef.write(generate_type_cleanup(expr['union']) + "\n") 303 else: 304 continue 305 fdecl.write(ret) 306 307fdecl.write(''' 308#endif 309''') 310 311fdecl.flush() 312fdecl.close() 313 314fdef.flush() 315fdef.close() 316