1#!/usr/bin/python 2 3from __future__ import print_function 4 5import sys 6import re 7 8import idl 9 10def libxl_C_instance_of(ty, instancename): 11 if isinstance(ty, idl.Aggregate) and ty.typename is None: 12 if instancename is None: 13 return libxl_C_type_define(ty) 14 else: 15 return libxl_C_type_define(ty) + " " + instancename 16 17 s = "" 18 if isinstance(ty, idl.Array): 19 s += libxl_C_instance_of(ty.lenvar.type, ty.lenvar.name) + ";\n" 20 21 return s + ty.typename + " " + instancename 22 23def libxl_C_type_define(ty, indent = ""): 24 s = "" 25 if isinstance(ty, idl.Enumeration): 26 if ty.typename is None: 27 s += "enum {\n" 28 else: 29 s += "typedef enum %s {\n" % ty.typename 30 31 for v in ty.values: 32 x = "%s = %d" % (v.name, v.value) 33 x = x.replace("\n", "\n ") 34 s += " " + x + ",\n" 35 if ty.typename is None: 36 s += "}" 37 else: 38 s += "} %s" % ty.typename 39 40 elif isinstance(ty, idl.Aggregate): 41 if isinstance(ty, idl.KeyedUnion): 42 s += libxl_C_instance_of(ty.keyvar.type, ty.keyvar.name) + ";\n" 43 44 if ty.typename is None: 45 s += "%s {\n" % ty.kind 46 else: 47 s += "typedef %s %s {\n" % (ty.kind, ty.typename) 48 49 for f in ty.fields: 50 if isinstance(ty, idl.KeyedUnion) and f.type is None: continue 51 52 x = libxl_C_instance_of(f.type, f.name) 53 if f.const: 54 x = "const " + x 55 x = x.replace("\n", "\n ") 56 s += " " + x + ";\n" 57 if ty.typename is None: 58 s += "}" 59 else: 60 s += "} %s" % ty.typename 61 else: 62 raise NotImplementedError("%s" % type(ty)) 63 return s.replace("\n", "\n%s" % indent) 64 65def libxl_C_type_dispose(ty, v, indent = " ", parent = None): 66 s = "" 67 if isinstance(ty, idl.KeyedUnion): 68 if parent is None: 69 raise Exception("KeyedUnion type must have a parent") 70 s += "switch (%s) {\n" % (parent + ty.keyvar.name) 71 for f in ty.fields: 72 (nparent,fexpr) = ty.member(v, f, parent is None) 73 s += "case %s:\n" % f.enumname 74 if f.type is not None: 75 s += libxl_C_type_dispose(f.type, fexpr, indent + " ", nparent) 76 s += " break;\n" 77 s += "}\n" 78 elif isinstance(ty, idl.Array): 79 if parent is None: 80 raise Exception("Array type must have a parent") 81 if ty.elem_type.dispose_fn is not None: 82 s += "{\n" 83 s += " int i;\n" 84 s += " for (i=0; i<%s; i++)\n" % (parent + ty.lenvar.name) 85 s += libxl_C_type_dispose(ty.elem_type, v+"[i]", 86 indent + " ", parent) 87 if ty.dispose_fn is not None: 88 if ty.elem_type.dispose_fn is not None: 89 s += " " 90 s += "%s(%s);\n" % (ty.dispose_fn, ty.pass_arg(v, parent is None)) 91 if ty.elem_type.dispose_fn is not None: 92 s += "}\n" 93 elif isinstance(ty, idl.Struct) and (parent is None or ty.dispose_fn is None): 94 for f in [f for f in ty.fields if not f.const]: 95 (nparent,fexpr) = ty.member(v, f, parent is None) 96 s += libxl_C_type_dispose(f.type, fexpr, "", nparent) 97 else: 98 if ty.dispose_fn is not None: 99 s += "%s(%s);\n" % (ty.dispose_fn, ty.pass_arg(v, parent is None)) 100 101 if s != "": 102 s = indent + s 103 return s.replace("\n", "\n%s" % indent).rstrip(indent) 104 105def libxl_C_type_copy(ty, v, w, indent = " ", vparent = None, wparent = None): 106 s = "" 107 108 if vparent is None: 109 s += "GC_INIT(ctx);\n"; 110 111 if isinstance(ty, idl.KeyedUnion): 112 if vparent is None or wparent is None: 113 raise Exception("KeyedUnion type must have a parent") 114 s += "%s = %s;\n" % ((vparent + ty.keyvar.name), (wparent + ty.keyvar.name)) 115 s += "switch (%s) {\n" % (wparent + ty.keyvar.name) 116 for f in ty.fields: 117 (vnparent,vfexpr) = ty.member(v, f, vparent is None) 118 (wnparent,wfexpr) = ty.member(w, f, wparent is None) 119 s += "case %s:\n" % f.enumname 120 if f.type is not None: 121 s += libxl_C_type_copy(f.type, vfexpr, wfexpr, indent + " ", 122 vnparent, wnparent) 123 s += " break;\n" 124 s += "}\n" 125 elif isinstance(ty, idl.Array): 126 if vparent is None or wparent is None: 127 raise Exception("Array type must have a parent") 128 s += "%s = libxl__calloc(NOGC, %s, sizeof(*%s));\n" % (ty.pass_arg(v, vparent is None), 129 (wparent + ty.lenvar.name), 130 ty.pass_arg(w, wparent is None)) 131 s += "%s = %s;\n" % ((vparent + ty.lenvar.name), (wparent + ty.lenvar.name)) 132 s += "{\n" 133 s += " int i;\n" 134 s += " for (i=0; i<%s; i++)\n" % (wparent + ty.lenvar.name) 135 s += libxl_C_type_copy(ty.elem_type, v+"[i]", w+"[i]", 136 indent + " ", vparent, wparent) 137 s += "}\n" 138 elif isinstance(ty, idl.Struct) and ((vparent is None and wparent is None) or ty.copy_fn is None): 139 for f in [f for f in ty.fields if not f.const and not f.type.private]: 140 (vnparent,vfexpr) = ty.member(v, f, vparent is None) 141 (wnparent,wfexpr) = ty.member(w, f, wparent is None) 142 s += libxl_C_type_copy(f.type, vfexpr, wfexpr, "", vnparent, wnparent) 143 else: 144 if ty.copy_fn is not None: 145 s += "%s(ctx, %s, %s);\n" % (ty.copy_fn, 146 ty.pass_arg(v, vparent is None, passby=idl.PASS_BY_REFERENCE), 147 ty.pass_arg(w, wparent is None, passby=idl.PASS_BY_REFERENCE)) 148 149 else: 150 s += "%s = %s;\n" % (ty.pass_arg(v, vparent is None, passby=idl.PASS_BY_VALUE), 151 ty.pass_arg(w, wparent is None, passby=idl.PASS_BY_VALUE)) 152 153 if vparent is None: 154 s += "GC_FREE;\n" 155 156 if s != "": 157 s = indent + s 158 return s.replace("\n", "\n%s" % indent).rstrip(indent) 159 160def libxl_init_members(ty, nesting = 0): 161 """Returns a list of members of ty which require a separate init""" 162 163 if isinstance(ty, idl.Aggregate): 164 return [f for f in ty.fields if not f.const and isinstance(f.type,idl.KeyedUnion)] 165 else: 166 return [] 167 168def libxl_C_type_do_init(ty, pass_arg, need_zero=True, indent=" "): 169 s=indent 170 if ty.init_val is not None: 171 s+= "%s = %s;\n" % (pass_arg(idl.PASS_BY_VALUE), ty.init_val) 172 elif ty.init_fn is not None: 173 s+= "%s(%s);\n" % (ty.init_fn, pass_arg(idl.PASS_BY_REFERENCE)) 174 elif need_zero: 175 ptr = pass_arg(idl.PASS_BY_REFERENCE) 176 s+= "memset(%s, 0, sizeof(*%s));\n" % (ptr, ptr) 177 else: 178 s="" 179 return s 180 181def _libxl_C_type_init(ty, v, indent = " ", parent = None, subinit=False): 182 s = "" 183 if isinstance(ty, idl.KeyedUnion): 184 if parent is None: 185 raise Exception("KeyedUnion type must have a parent") 186 if subinit: 187 s += "switch (%s) {\n" % (parent + ty.keyvar.name) 188 for f in ty.fields: 189 (nparent,fexpr) = ty.member(v, f, parent is None) 190 s += "case %s:\n" % f.enumname 191 if f.type is not None: 192 s += _libxl_C_type_init(f.type, fexpr, " ", nparent) 193 s += " break;\n" 194 s += "}\n" 195 else: 196 if ty.keyvar.init_val: 197 s += "%s = %s;\n" % (parent + ty.keyvar.name, ty.keyvar.init_val) 198 elif ty.keyvar.type.init_val: 199 s += "%s = %s;\n" % (parent + ty.keyvar.name, ty.keyvar.type.init_val) 200 elif isinstance(ty, idl.Struct) and (parent is None or ty.init_fn is None): 201 for f in [f for f in ty.fields if not f.const]: 202 (nparent,fexpr) = ty.member(v, f, parent is None) 203 if f.init_val is not None: 204 s += "%s = %s;\n" % (fexpr, f.init_val) 205 else: 206 s += _libxl_C_type_init(f.type, fexpr, "", nparent) 207 else: 208 if ty.init_val is not None: 209 s += "%s = %s;\n" % (ty.pass_arg(v, parent is None), ty.init_val) 210 elif ty.init_fn is not None: 211 s += "%s(%s);\n" % (ty.init_fn, ty.pass_arg(v, parent is None)) 212 213 if s != "": 214 s = indent + s 215 return s.replace("\n", "\n%s" % indent).rstrip(indent) 216 217def libxl_C_type_init(ty): 218 s = "" 219 s += "void %s(%s)\n" % (ty.init_fn, ty.make_arg("p", passby=idl.PASS_BY_REFERENCE)) 220 s += "{\n" 221 s += " memset(p, '\\0', sizeof(*p));\n" 222 s += _libxl_C_type_init(ty, "p") 223 s += "}\n" 224 s += "\n" 225 return s 226 227def libxl_C_type_member_init(ty, field): 228 if not isinstance(field.type, idl.KeyedUnion): 229 raise Exception("Only KeyedUnion is supported for member init") 230 231 ku = field.type 232 233 s = "" 234 s += "void %s(%s, %s)\n" % (ty.init_fn + "_" + ku.keyvar.name, 235 ty.make_arg("p", passby=idl.PASS_BY_REFERENCE), 236 ku.keyvar.type.make_arg(ku.keyvar.name)) 237 s += "{\n" 238 239 if ku.keyvar.init_val is not None: 240 init_val = ku.keyvar.init_val 241 elif ku.keyvar.type.init_val is not None: 242 init_val = ku.keyvar.type.init_val 243 else: 244 init_val = None 245 246 (nparent,fexpr) = ty.member(ty.pass_arg("p"), ku.keyvar, isref=True) 247 if init_val is not None: 248 s += " assert(%s == %s);\n" % (fexpr, init_val) 249 else: 250 s += " assert(!%s);\n" % (fexpr) 251 s += " %s = %s;\n" % (fexpr, ku.keyvar.name) 252 253 (nparent,fexpr) = ty.member(ty.pass_arg("p"), field, isref=True) 254 s += _libxl_C_type_init(ku, fexpr, parent=nparent, subinit=True) 255 s += "}\n" 256 s += "\n" 257 return s 258 259def libxl_C_type_gen_map_key(f, parent, indent = ""): 260 s = "" 261 if isinstance(f.type, idl.KeyedUnion): 262 s += "switch (%s) {\n" % (parent + f.type.keyvar.name) 263 for x in f.type.fields: 264 v = f.type.keyvar.name + "." + x.name 265 s += "case %s:\n" % x.enumname 266 s += " s = yajl_gen_string(hand, (const unsigned char *)\"%s\", sizeof(\"%s\")-1);\n" % (v, v) 267 s += " if (s != yajl_gen_status_ok)\n" 268 s += " goto out;\n" 269 s += " break;\n" 270 s += "}\n" 271 else: 272 s += "s = yajl_gen_string(hand, (const unsigned char *)\"%s\", sizeof(\"%s\")-1);\n" % (f.name, f.name) 273 s += "if (s != yajl_gen_status_ok)\n" 274 s += " goto out;\n" 275 if s != "": 276 s = indent + s 277 return s.replace("\n", "\n%s" % indent).rstrip(indent) 278 279def libxl_C_type_copy_deprecated(field, v, indent = " ", vparent = None): 280 s = "" 281 282 if isinstance(field.type, idl.KeyedUnion): 283 if vparent is None: 284 raise Exception("KeyedUnion type must have a parent") 285 s += "switch (%s) {\n" % (vparent + field.type.keyvar.name) 286 for f in [f for f in field.type.fields if not f.const]: 287 (vnparent,vfexpr) = ty.member(v, f, vparent is None) 288 s += "case %s:\n" % f.enumname 289 if f.type is not None: 290 s += libxl_C_type_copy_deprecated(f, vfexpr, indent, vnparent) 291 s+= " break;\n" 292 s+="}\n"; 293 elif isinstance(field.type, idl.Array) and field.deprecated_by: 294 raise Exception("Array type is not supported for deprecation") 295 elif isinstance(field.type, idl.Struct) and field.type.copy_fn is None: 296 for f in [f for f in field.type.fields if not f.const]: 297 (vnparent,vfexpr) = ty.member(v, f, vparent is None) 298 s += libxl_C_type_copy_deprecated(f, vfexpr, "", vnparent) 299 elif field.deprecated_by is not None: 300 if field.type.check_default_fn is None: 301 raise Exception( 302"Deprecated field %s type doesn't have a default value checker" % field.name) 303 field_pass = lambda by: field.type.pass_arg(v, vparent is None, 304 passby=by) 305 field_val = field_pass(idl.PASS_BY_VALUE) 306 field_ptr = field_pass(idl.PASS_BY_REFERENCE) 307 s+= "if (!%s(&p->%s) && !%s(%s))\n" % (field.type.check_default_fn, 308 field.deprecated_by, 309 field.type.check_default_fn, 310 field_ptr) 311 s+= " return -EINVAL;\n" 312 s+="(void) (&p->%s == %s);\n" % (field.deprecated_by, field_ptr) 313 s+= "if (%s(&p->%s)) {\n" % (field.type.check_default_fn, 314 field.deprecated_by) 315 s+= " " 316 if field.type.copy_fn is not None: 317 s+= "%s(ctx, &p->%s, %s);\n" % (field.type.copy_fn, 318 field.deprecated_by, field_ptr) 319 else: 320 s+= "p->%s = %s;\n" % (field.deprecated_by, field_val) 321 322 if field.type.dispose_fn is not None: 323 s+= " %s(%s);\n" % (field.type.dispose_fn, 324 field.type.pass_arg(v, vparent is None)) 325 s+=libxl_C_type_do_init(field.type, field_pass) 326 s+= "}\n" 327 328 if s != "": 329 s = indent + s 330 return s.replace("\n", "\n%s" % indent).rstrip(indent) 331 332def get_init_val(f): 333 if f.init_val is not None: 334 return f.init_val 335 elif f.type.init_val is not None: 336 return f.type.init_val 337 return None 338 339def get_default_expr(f, nparent, fexpr): 340 if isinstance(f.type, idl.Aggregate): 341 return "1 /* always generate JSON output for aggregate type */" 342 343 if isinstance(f.type, idl.Array): 344 return "%s && %s" % (fexpr, nparent + f.type.lenvar.name) 345 346 init_val = get_init_val(f) 347 if init_val is not None: 348 return "%s != %s" % (fexpr, init_val) 349 350 if f.type.check_default_fn: 351 return "!%s(&%s)" % (f.type.check_default_fn, fexpr) 352 353 return "%s" % fexpr 354 355def libxl_C_type_gen_json(ty, v, indent = " ", parent = None): 356 s = "" 357 if parent is None: 358 s += "yajl_gen_status s;\n" 359 360 if isinstance(ty, idl.Array): 361 if parent is None: 362 raise Exception("Array type must have a parent") 363 s += "{\n" 364 s += " int i;\n" 365 s += " s = yajl_gen_array_open(hand);\n" 366 s += " if (s != yajl_gen_status_ok)\n" 367 s += " goto out;\n" 368 s += " for (i=0; i<%s; i++) {\n" % (parent + ty.lenvar.name) 369 s += libxl_C_type_gen_json(ty.elem_type, v+"[i]", 370 indent + " ", parent) 371 s += " }\n" 372 s += " s = yajl_gen_array_close(hand);\n" 373 s += " if (s != yajl_gen_status_ok)\n" 374 s += " goto out;\n" 375 s += "}\n" 376 elif isinstance(ty, idl.Enumeration): 377 s += "s = libxl__yajl_gen_enum(hand, %s_to_string(%s));\n" % (ty.typename, ty.pass_arg(v, parent is None)) 378 s += "if (s != yajl_gen_status_ok)\n" 379 s += " goto out;\n" 380 elif isinstance(ty, idl.KeyedUnion): 381 if parent is None: 382 raise Exception("KeyedUnion type must have a parent") 383 s += "switch (%s) {\n" % (parent + ty.keyvar.name) 384 for f in ty.fields: 385 (nparent,fexpr) = ty.member(v, f, parent is None) 386 s += "case %s:\n" % f.enumname 387 if f.type is not None: 388 s += libxl_C_type_gen_json(f.type, fexpr, indent + " ", nparent) 389 else: 390 s += " s = yajl_gen_map_open(hand);\n" 391 s += " if (s != yajl_gen_status_ok)\n" 392 s += " goto out;\n" 393 s += " s = yajl_gen_map_close(hand);\n" 394 s += " if (s != yajl_gen_status_ok)\n" 395 s += " goto out;\n" 396 s += " break;\n" 397 s += "}\n" 398 elif isinstance(ty, idl.Struct) and (parent is None or ty.json_gen_fn is None): 399 s += "s = yajl_gen_map_open(hand);\n" 400 s += "if (s != yajl_gen_status_ok)\n" 401 s += " goto out;\n" 402 for f in [f for f in ty.fields if not f.const and not f.type.private]: 403 (nparent,fexpr) = ty.member(v, f, parent is None) 404 default_expr = get_default_expr(f, nparent, fexpr) 405 s += "if (%s) {\n" % default_expr 406 407 s += libxl_C_type_gen_map_key(f, nparent, " ") 408 s += libxl_C_type_gen_json(f.type, fexpr, " ", nparent) 409 410 s += "}\n" 411 412 s += "s = yajl_gen_map_close(hand);\n" 413 s += "if (s != yajl_gen_status_ok)\n" 414 s += " goto out;\n" 415 else: 416 if ty.json_gen_fn is not None: 417 s += "s = %s(hand, %s);\n" % (ty.json_gen_fn, ty.pass_arg(v, parent is None)) 418 s += "if (s != yajl_gen_status_ok)\n" 419 s += " goto out;\n" 420 421 if parent is None: 422 s += "out:\n" 423 s += "return s;\n" 424 425 if s != "": 426 s = indent + s 427 return s.replace("\n", "\n%s" % indent).rstrip(indent) 428 429def libxl_C_type_to_json(ty, v, indent = " "): 430 s = "" 431 gen = "(libxl__gen_json_callback)&%s_gen_json" % ty.typename 432 s += "return libxl__object_to_json(ctx, \"%s\", %s, (void *)%s);\n" % (ty.typename, gen, ty.pass_arg(v, passby=idl.PASS_BY_REFERENCE)) 433 434 if s != "": 435 s = indent + s 436 return s.replace("\n", "\n%s" % indent).rstrip(indent) 437 438def libxl_C_type_parse_json(ty, w, v, indent = " ", parent = None, discriminator = None): 439 s = "" 440 if parent is None: 441 s += "int rc = 0;\n" 442 s += "const libxl__json_object *x __attribute__((__unused__)) = o;\n" 443 444 if isinstance(ty, idl.Array): 445 if parent is None: 446 raise Exception("Array type must have a parent") 447 if discriminator is not None: 448 raise Exception("Only KeyedUnion can have discriminator") 449 lenvar = parent + ty.lenvar.name 450 s += "{\n" 451 s += " libxl__json_object *t;\n" 452 s += " int i;\n" 453 s += " if (!libxl__json_object_is_array(x)) {\n" 454 s += " rc = -1;\n" 455 s += " goto out;\n" 456 s += " }\n" 457 s += " %s = x->u.array->count;\n" % lenvar 458 s += " %s = libxl__calloc(NOGC, %s, sizeof(*%s));\n" % (v, lenvar, v) 459 s += " if (!%s && %s != 0) {\n" % (v, lenvar) 460 s += " rc = -1;\n" 461 s += " goto out;\n" 462 s += " }\n" 463 s += " for (i=0; (t=libxl__json_array_get(x,i)); i++) {\n" 464 s += libxl_C_type_do_init(ty.elem_type, 465 lambda by: ("&" if by == idl.PASS_BY_REFERENCE else "")+ 466 ("%s[i]" % v), 467 need_zero=False, indent=indent+" ") 468 s += libxl_C_type_parse_json(ty.elem_type, "t", v+"[i]", 469 indent + " ", parent) 470 s += " }\n" 471 s += " if (i != %s) {\n" % lenvar 472 s += " rc = -1;\n" 473 s += " goto out;\n" 474 s += " }\n" 475 s += "}\n" 476 elif isinstance(ty, idl.Enumeration): 477 if discriminator is not None: 478 raise Exception("Only KeyedUnion can have discriminator") 479 s += "{\n" 480 s += " const char *enum_str;\n" 481 s += " if (!libxl__json_object_is_string(%s)) {\n" % w 482 s += " rc = -1;\n" 483 s += " goto out;\n" 484 s += " }\n" 485 s += " enum_str = libxl__json_object_get_string(%s);\n" % w 486 s += " rc = %s_from_string(enum_str, %s);\n" % (ty.typename, ty.pass_arg(v, parent is None, idl.PASS_BY_REFERENCE)) 487 s += " if (rc)\n" 488 s += " goto out;\n" 489 s += "}\n" 490 elif isinstance(ty, idl.KeyedUnion): 491 if parent is None: 492 raise Exception("KeyedUnion type must have a parent") 493 if discriminator is None: 494 raise Excpetion("KeyedUnion type must have a discriminator") 495 for f in ty.fields: 496 if f.enumname != discriminator: 497 continue 498 (nparent,fexpr) = ty.member(v, f, parent is None) 499 if f.type is not None: 500 s += libxl_C_type_parse_json(f.type, w, fexpr, indent + " ", nparent) 501 elif isinstance(ty, idl.Struct) and (parent is None or ty.json_parse_fn is None): 502 if discriminator is not None: 503 raise Exception("Only KeyedUnion can have discriminator") 504 for f in [f for f in ty.fields if not f.const and not f.type.private]: 505 saved_var_name = "saved_%s" % f.name 506 s += "{\n" 507 s += " const libxl__json_object *%s = x;\n" % saved_var_name 508 if isinstance(f.type, idl.KeyedUnion): 509 for x in f.type.fields: 510 s += " x = libxl__json_map_get(\"%s\", %s, JSON_MAP);\n" % \ 511 (f.type.keyvar.name + "." + x.name, w) 512 s += " if (x) {\n" 513 (nparent, fexpr) = ty.member(v, f.type.keyvar, parent is None) 514 s += " %s_init_%s(%s, %s);\n" % (ty.typename, f.type.keyvar.name, v, x.enumname) 515 (nparent,fexpr) = ty.member(v, f, parent is None) 516 s += libxl_C_type_parse_json(f.type, "x", fexpr, " ", nparent, x.enumname) 517 s += " }\n" 518 else: 519 s += " x = libxl__json_map_get(\"%s\", %s, %s);\n" % (f.name, w, f.type.json_parse_type) 520 s += " if (x) {\n" 521 (nparent,fexpr) = ty.member(v, f, parent is None) 522 s += libxl_C_type_parse_json(f.type, "x", fexpr, " ", nparent) 523 s += " }\n" 524 s += " x = %s;\n" % saved_var_name 525 s += "}\n" 526 else: 527 if discriminator is not None: 528 raise Exception("Only KeyedUnion can have discriminator") 529 if ty.json_parse_fn is not None: 530 s += "rc = %s(gc, %s, &%s);\n" % (ty.json_parse_fn, w, v) 531 s += "if (rc)\n" 532 s += " goto out;\n" 533 534 if parent is None: 535 s += "out:\n" 536 s += "return rc;\n" 537 538 if s != "": 539 s = indent +s 540 return s.replace("\n", "\n%s" % indent).rstrip(indent) 541 542def libxl_C_type_from_json(ty, v, w, indent = " "): 543 s = "" 544 parse = "(libxl__json_parse_callback)&%s_parse_json" % (ty.namespace + "_" + ty.rawname) 545 s += "return libxl__object_from_json(ctx, \"%s\", %s, %s, %s);\n" % (ty.typename, parse, v, w) 546 547 if s != "": 548 s = indent + s 549 return s.replace("\n", "\n%s" % indent).rstrip(indent) 550 551def libxl_C_enum_to_string(ty, e, indent = " "): 552 s = "" 553 s += "switch(%s) {\n" % e 554 for v in ty.values: 555 s += " case %s:\n" % (v.name) 556 s += " return \"%s\";\n" % (v.valuename.lower()) 557 s += " default:\n " 558 s += " return NULL;\n" 559 s += "}\n" 560 561 if s != "": 562 s = indent + s 563 return s.replace("\n", "\n%s" % indent).rstrip(indent) 564 565def libxl_C_enum_strings(ty, indent=""): 566 s = "" 567 s += "libxl_enum_string_table %s_string_table[] = {\n" % (ty.typename) 568 for v in ty.values: 569 s += " { .s = \"%s\", .v = %s },\n" % (v.valuename.lower(), v.name) 570 s += " { NULL, -1 },\n" 571 s += "};\n" 572 s += "\n" 573 574 if s != "": 575 s = indent + s 576 return s.replace("\n", "\n%s" % indent).rstrip(indent) 577 578def libxl_C_enum_from_string(ty, str, e, indent = " "): 579 s = "" 580 s += "return libxl__enum_from_string(%s_string_table,\n" % ty.typename 581 s += " %s, (int *)%s);\n" % (str, e) 582 583 if s != "": 584 s = indent + s 585 return s.replace("\n", "\n%s" % indent).rstrip(indent) 586 587 588if __name__ == '__main__': 589 if len(sys.argv) != 6: 590 print("Usage: gentypes.py <idl> <header> <header-private> <header-json> <implementation>", file=sys.stderr) 591 sys.exit(1) 592 593 (_, idlname, header, header_private, header_json, impl) = sys.argv 594 595 (builtins,types) = idl.parse(idlname) 596 597 print("outputting libxl type definitions to %s" % header) 598 599 f = open(header, "w") 600 601 header_define = header.upper().replace('.','_') 602 f.write("""#ifndef %s 603#define %s 604 605/* 606 * DO NOT EDIT. 607 * 608 * This file is autogenerated by 609 * "%s" 610 */ 611 612""" % (header_define, header_define, " ".join(sys.argv))) 613 614 for ty in types: 615 f.write(libxl_C_type_define(ty) + ";\n") 616 if ty.dispose_fn is not None: 617 f.write("%svoid %s(%s);\n" % (ty.hidden(), ty.dispose_fn, ty.make_arg("p"))) 618 if ty.copy_deprecated_fn is not None: 619 f.write("%sint %s(libxl_ctx *ctx, %s);\n" % (ty.hidden(), 620 ty.copy_deprecated_fn, 621 ty.make_arg("p"))) 622 if ty.copy_fn is not None: 623 f.write("%svoid %s(libxl_ctx *ctx, %s, const %s);\n" % (ty.hidden(), ty.copy_fn, 624 ty.make_arg("dst"), ty.make_arg("src"))) 625 if ty.init_fn is not None: 626 f.write("%svoid %s(%s);\n" % (ty.hidden(), ty.init_fn, ty.make_arg("p"))) 627 for field in libxl_init_members(ty): 628 if not isinstance(field.type, idl.KeyedUnion): 629 raise Exception("Only KeyedUnion is supported for member init") 630 ku = field.type 631 f.write("%svoid %s(%s, %s);\n" % (ty.hidden(), ty.init_fn + "_" + ku.keyvar.name, 632 ty.make_arg("p"), 633 ku.keyvar.type.make_arg(ku.keyvar.name))) 634 if ty.json_gen_fn is not None: 635 f.write("%schar *%s_to_json(libxl_ctx *ctx, %s);\n" % (ty.hidden(), ty.typename, ty.make_arg("p"))) 636 if ty.json_parse_fn is not None: 637 f.write("%sint %s_from_json(libxl_ctx *ctx, %s, const char *s);\n" % (ty.hidden(), ty.typename, ty.make_arg("p", passby=idl.PASS_BY_REFERENCE))) 638 if isinstance(ty, idl.Enumeration): 639 f.write("%sconst char *%s_to_string(%s);\n" % (ty.hidden(), ty.typename, ty.make_arg("p"))) 640 f.write("%sint %s_from_string(const char *s, %s);\n" % (ty.hidden(), ty.typename, ty.make_arg("e", passby=idl.PASS_BY_REFERENCE))) 641 f.write("%sextern libxl_enum_string_table %s_string_table[];\n" % (ty.hidden(), ty.typename)) 642 f.write("\n") 643 644 f.write("""#endif /* %s */\n""" % (header_define)) 645 f.close() 646 647 print("outputting libxl JSON definitions to %s" % header_json) 648 649 f = open(header_json, "w") 650 651 header_json_define = header_json.upper().replace('.','_') 652 f.write("""#ifndef %s 653#define %s 654 655/* 656 * DO NOT EDIT. 657 * 658 * This file is autogenerated by 659 * "%s" 660 */ 661 662""" % (header_json_define, header_json_define, " ".join(sys.argv))) 663 664 for ty in [ty for ty in types if ty.json_gen_fn is not None]: 665 f.write("%syajl_gen_status %s_gen_json(yajl_gen hand, %s);\n" % (ty.hidden(), ty.typename, ty.make_arg("p", passby=idl.PASS_BY_REFERENCE))) 666 667 f.write("\n") 668 f.write("""#endif /* %s */\n""" % header_json_define) 669 f.close() 670 671 print("outputting libxl type internal definitions to %s" % header_private) 672 673 f = open(header_private, "w") 674 675 header_private_define = header_private.upper().replace('.','_') 676 f.write("""#ifndef %s 677#define %s 678 679/* 680 * DO NOT EDIT. 681 * 682 * This file is autogenerated by 683 * "%s" 684 */ 685 686""" % (header_private_define, header_private_define, " ".join(sys.argv))) 687 688 for ty in [ty for ty in types if ty.json_parse_fn is not None]: 689 f.write("%sint %s_parse_json(libxl__gc *gc, const libxl__json_object *o, %s);\n" % \ 690 (ty.hidden(), ty.namespace + "_" + ty.rawname, 691 ty.make_arg("p", passby=idl.PASS_BY_REFERENCE))) 692 693 f.write("\n") 694 f.write("""#endif /* %s */\n""" % header_json_define) 695 f.close() 696 697 print("outputting libxl type implementations to %s" % impl) 698 699 f = open(impl, "w") 700 f.write(""" 701/* DO NOT EDIT. 702 * 703 * This file is autogenerated by 704 * "%s" 705 */ 706 707#include "libxl_osdeps.h" 708 709#include <stdint.h> 710#include <stdlib.h> 711#include <string.h> 712 713#include "libxl_internal.h" 714 715 716""" % " ".join(sys.argv)) 717 718 for ty in [t for t in types if t.dispose_fn is not None and t.autogenerate_dispose_fn]: 719 f.write("void %s(%s)\n" % (ty.dispose_fn, ty.make_arg("p"))) 720 f.write("{\n") 721 f.write(" if (!p) return;\n") 722 f.write(libxl_C_type_dispose(ty, "p")) 723 f.write(" memset(p, 0, sizeof(*p));\n") 724 f.write("}\n") 725 f.write("\n") 726 727 for ty in [t for t in types if t.copy_fn and t.autogenerate_copy_fn]: 728 f.write("void %s(libxl_ctx *ctx, %s, const %s)\n" % (ty.copy_fn, 729 ty.make_arg("dst", passby=idl.PASS_BY_REFERENCE), 730 ty.make_arg("src", passby=idl.PASS_BY_REFERENCE))) 731 f.write("{\n") 732 f.write(libxl_C_type_copy(ty, "dst", "src")) 733 f.write("}\n") 734 f.write("\n") 735 736 for ty in [t for t in types if t.copy_deprecated_fn]: 737 f.write("int %s(libxl_ctx *ctx, %s)\n" % (ty.copy_deprecated_fn, 738 ty.make_arg("p", passby=idl.PASS_BY_REFERENCE))) 739 f.write("{\n") 740 for field in [field for field in ty.fields if not field.const]: 741 (vnparent,vfexpr) = ty.member("p", field, True) 742 f.write(libxl_C_type_copy_deprecated(field, vfexpr, 743 vparent = vnparent)) 744 f.write(" return 0;\n") 745 f.write("}\n") 746 f.write("\n") 747 748 for ty in [t for t in types if t.init_fn is not None and t.autogenerate_init_fn]: 749 f.write(libxl_C_type_init(ty)) 750 for field in libxl_init_members(ty): 751 f.write(libxl_C_type_member_init(ty, field)) 752 753 for ty in [t for t in types if isinstance(t,idl.Enumeration)]: 754 f.write("const char *%s_to_string(%s e)\n" % (ty.typename, ty.typename)) 755 f.write("{\n") 756 f.write(libxl_C_enum_to_string(ty, "e")) 757 f.write("}\n") 758 f.write("\n") 759 760 f.write(libxl_C_enum_strings(ty)) 761 762 f.write("int %s_from_string(const char *s, %s *e)\n" % (ty.typename, ty.typename)) 763 f.write("{\n") 764 f.write(libxl_C_enum_from_string(ty, "s", "e")) 765 f.write("}\n") 766 f.write("\n") 767 768 for ty in [t for t in types if t.json_gen_fn is not None]: 769 f.write("yajl_gen_status %s_gen_json(yajl_gen hand, %s)\n" % (ty.typename, ty.make_arg("p", passby=idl.PASS_BY_REFERENCE))) 770 f.write("{\n") 771 f.write(libxl_C_type_gen_json(ty, "p")) 772 f.write("}\n") 773 f.write("\n") 774 775 f.write("char *%s_to_json(libxl_ctx *ctx, %s)\n" % (ty.typename, ty.make_arg("p"))) 776 f.write("{\n") 777 f.write(libxl_C_type_to_json(ty, "p")) 778 f.write("}\n") 779 f.write("\n") 780 781 for ty in [t for t in types if t.json_parse_fn is not None]: 782 f.write("int %s_parse_json(libxl__gc *gc, const libxl__json_object *%s, %s)\n" % \ 783 (ty.namespace + "_" + ty.rawname,"o",ty.make_arg("p", passby=idl.PASS_BY_REFERENCE))) 784 f.write("{\n") 785 f.write(libxl_C_type_parse_json(ty, "o", "p")) 786 f.write("}\n") 787 f.write("\n") 788 789 f.write("int %s_from_json(libxl_ctx *ctx, %s, const char *s)\n" % (ty.typename, ty.make_arg("p", passby=idl.PASS_BY_REFERENCE))) 790 f.write("{\n") 791 if not isinstance(ty, idl.Enumeration): 792 f.write(" %s_init(p);\n" % ty.typename) 793 f.write(libxl_C_type_from_json(ty, "p", "s")) 794 f.write("}\n") 795 f.write("\n") 796 797 f.close() 798