1#!/usr/bin/python 2 3import sys,os 4 5import idl 6 7# typename -> ( ocaml_type, c_from_ocaml, ocaml_from_c ) 8builtins = { 9 "bool": ("bool", "%(c)s = Bool_val(%(o)s)", "Val_bool(%(c)s)" ), 10 "int": ("int", "%(c)s = Int_val(%(o)s)", "Val_int(%(c)s)" ), 11 "char *": ("string option", "%(c)s = String_option_val(%(o)s)", "Val_string_option(%(c)s)"), 12 "libxl_domid": ("domid", "%(c)s = Int_val(%(o)s)", "Val_int(%(c)s)" ), 13 "libxl_devid": ("devid", "%(c)s = Int_val(%(o)s)", "Val_int(%(c)s)" ), 14 "libxl_defbool": ("bool option", "%(c)s = Defbool_val(%(o)s)", "Val_defbool(%(c)s)" ), 15 "libxl_uuid": ("int array", "Uuid_val(&%(c)s, %(o)s)", "Val_uuid(&%(c)s)"), 16 "libxl_bitmap": ("bool array", "Bitmap_val(ctx, &%(c)s, %(o)s)", "Val_bitmap(&%(c)s)"), 17 "libxl_key_value_list": ("(string * string) list", "libxl_key_value_list_val(&%(c)s, %(o)s)", "Val_key_value_list(&%(c)s)"), 18 "libxl_string_list": ("string list", "libxl_string_list_val(&%(c)s, %(o)s)", "Val_string_list(&%(c)s)"), 19 "libxl_mac": ("int array", "Mac_val(&%(c)s, %(o)s)", "Val_mac(&%(c)s)"), 20 "libxl_hwcap": ("int32 array", None, "Val_hwcap(&%(c)s)"), 21 "libxl_ms_vm_genid": ("int array", "Ms_vm_genid_val(&%(c)s, %(o)s)", "Val_ms_vm_genid(&%(c)s)"), 22 # The following needs to be sorted out later 23 "libxl_cpuid_policy_list": ("unit", "%(c)s = 0", "Val_unit"), 24 } 25 26DEVICE_FUNCTIONS = [ ("add", ["ctx", "t", "domid", "?async:'a", "unit", "unit"]), 27 ("remove", ["ctx", "t", "domid", "?async:'a", "unit", "unit"]), 28 ("destroy", ["ctx", "t", "domid", "?async:'a", "unit", "unit"]), 29 ] 30DEVICE_LIST = [ ("list", ["ctx", "domid", "t list"]), 31 ] 32 33functions = { # ( name , [type1,type2,....] ) 34 "device_vfb": DEVICE_FUNCTIONS, 35 "device_vkb": DEVICE_FUNCTIONS, 36 "device_disk": DEVICE_FUNCTIONS + DEVICE_LIST + 37 [ ("insert", ["ctx", "t", "domid", "?async:'a", "unit", "unit"]), 38 ("of_vdev", ["ctx", "domid", "string", "t"]), 39 ], 40 "device_nic": DEVICE_FUNCTIONS + DEVICE_LIST + 41 [ ("of_devid", ["ctx", "domid", "int", "t"]), 42 ], 43 "device_pci": DEVICE_FUNCTIONS + DEVICE_LIST + 44 [ ("assignable_add", ["ctx", "t", "bool", "unit"]), 45 ("assignable_remove", ["ctx", "t", "bool", "unit"]), 46 ("assignable_list", ["ctx", "t list"]), 47 ], 48 "dominfo": [ ("list", ["ctx", "t list"]), 49 ("get", ["ctx", "domid", "t"]), 50 ], 51 "physinfo": [ ("get", ["ctx", "t"]), 52 ], 53 "cputopology": [ ("get", ["ctx", "t array"]), 54 ], 55 "domain_sched_params": 56 [ ("get", ["ctx", "domid", "t"]), 57 ("set", ["ctx", "domid", "t", "unit"]), 58 ], 59} 60def stub_fn_name(ty, name): 61 return "stub_xl_%s_%s" % (ty.rawname,name) 62 63def ocaml_type_of(ty): 64 if ty.rawname in ["domid","devid"]: 65 return ty.rawname 66 elif isinstance(ty,idl.UInt): 67 if ty.width in [8, 16]: 68 # handle as ints 69 width = None 70 elif ty.width in [32, 64]: 71 width = ty.width 72 else: 73 raise NotImplementedError("Cannot handle %d-bit int" % ty.width) 74 if width: 75 return "int%d" % ty.width 76 else: 77 return "int" 78 elif isinstance(ty,idl.Array): 79 return "%s array" % ocaml_type_of(ty.elem_type) 80 elif isinstance(ty,idl.Builtin): 81 if not builtins.has_key(ty.typename): 82 raise NotImplementedError("Unknown Builtin %s (%s)" % (ty.typename, type(ty))) 83 typename,_,_ = builtins[ty.typename] 84 if not typename: 85 raise NotImplementedError("No typename for Builtin %s (%s)" % (ty.typename, type(ty))) 86 return typename 87 elif isinstance(ty,idl.KeyedUnion): 88 return ty.union_name 89 elif isinstance(ty,idl.Aggregate): 90 if ty.rawname is None: 91 return ty.anon_struct 92 else: 93 return ty.rawname.capitalize() + ".t" 94 else: 95 return ty.rawname 96 97ocaml_keywords = ['and', 'as', 'assert', 'begin', 'end', 'class', 'constraint', 98 'do', 'done', 'downto', 'else', 'if', 'end', 'exception', 'external', 'false', 99 'for', 'fun', 'function', 'functor', 'if', 'in', 'include', 'inherit', 100 'initializer', 'lazy', 'let', 'match', 'method', 'module', 'mutable', 'new', 101 'object', 'of', 'open', 'or', 'private', 'rec', 'sig', 'struct', 'then', 'to', 102 'true', 'try', 'type', 'val', 'virtual', 'when', 'while', 'with'] 103 104def munge_name(name): 105 if name in ocaml_keywords: 106 return "xl_" + name 107 else: 108 return name 109 110def ocaml_instance_of_field(f): 111 if isinstance(f.type, idl.KeyedUnion): 112 name = f.type.keyvar.name 113 else: 114 name = f.name 115 return "%s : %s" % (munge_name(name), ocaml_type_of(f.type)) 116 117def gen_struct(ty, indent): 118 s = "" 119 for f in ty.fields: 120 if f.type.private: 121 continue 122 x = ocaml_instance_of_field(f) 123 x = x.replace("\n", "\n"+indent) 124 s += indent + x + ";\n" 125 return s 126 127def gen_ocaml_keyedunions(ty, interface, indent, parent = None): 128 s = "" 129 union_type = "" 130 131 if ty.rawname is not None: 132 # Non-anonymous types need no special handling 133 pass 134 elif isinstance(ty, idl.KeyedUnion): 135 if parent is None: 136 nparent = ty.keyvar.name 137 else: 138 nparent = parent + "_" + ty.keyvar.name 139 140 for f in ty.fields: 141 if f.type is None: continue 142 if f.type.rawname is not None: continue 143 if isinstance(f.type, idl.Struct) and not f.type.has_fields(): continue 144 s += "\ntype %s_%s =\n" % (nparent,f.name) 145 s += "{\n" 146 s += gen_struct(f.type, indent + "\t") 147 s += "}\n" 148 149 name = "%s__union" % ty.keyvar.name 150 s += "\n" 151 s += "type %s = " % name 152 u = [] 153 for f in ty.fields: 154 if f.type is None: 155 u.append("%s" % (f.name.capitalize())) 156 elif isinstance(f.type, idl.Struct): 157 if f.type.rawname is not None: 158 u.append("%s of %s.t" % (f.name.capitalize(), f.type.rawname.capitalize())) 159 elif f.type.has_fields(): 160 u.append("%s of %s_%s" % (f.name.capitalize(), nparent, f.name)) 161 else: 162 u.append("%s" % (f.name.capitalize())) 163 else: 164 raise NotImplementedError("Cannot handle KeyedUnion fields which are not Structs") 165 166 s += " | ".join(u) + "\n" 167 ty.union_name = name 168 169 union_type = "?%s:%s" % (munge_name(nparent), ty.keyvar.type.rawname) 170 171 if s == "": 172 return None, None 173 return s.replace("\n", "\n%s" % indent), union_type 174 175def gen_ocaml_anonstruct(ty, interface, indent, parent = None): 176 s= "" 177 178 if ty.rawname is not None: 179 # Non-anonymous types need no special handling 180 pass 181 elif isinstance(ty, idl.Struct): 182 name = "%s__anon" % parent 183 s += "type %s = {\n" % name 184 s += gen_struct(ty, indent) 185 s += "}\n" 186 ty.anon_struct = name 187 if s == "": 188 return None 189 s = indent + s 190 return s.replace("\n", "\n%s" % indent) 191 192def gen_ocaml_ml(ty, interface, indent=""): 193 194 if interface: 195 s = ("""(* %s interface *)\n""" % ty.typename) 196 else: 197 s = ("""(* %s implementation *)\n""" % ty.typename) 198 199 if isinstance(ty, idl.Enumeration): 200 s += "type %s = \n" % ty.rawname 201 for v in ty.values: 202 s += "\t | %s\n" % v.rawname 203 204 if interface: 205 s += "\nval string_of_%s : %s -> string\n" % (ty.rawname, ty.rawname) 206 else: 207 s += "\nlet string_of_%s = function\n" % ty.rawname 208 for v in ty.values: 209 s += '\t| %s -> "%s"\n' % (v.rawname, v.valuename) 210 211 elif isinstance(ty, idl.Aggregate): 212 s += "" 213 214 if ty.typename is None: 215 raise NotImplementedError("%s has no typename" % type(ty)) 216 else: 217 218 module_name = ty.rawname[0].upper() + ty.rawname[1:] 219 220 if interface: 221 s += "module %s : sig\n" % module_name 222 else: 223 s += "module %s = struct\n" % module_name 224 225 # Handle KeyedUnions... 226 union_types = [] 227 for f in ty.fields: 228 ku, union_type = gen_ocaml_keyedunions(f.type, interface, "\t") 229 if ku is not None: 230 s += ku 231 s += "\n" 232 if union_type is not None: 233 union_types.append(union_type) 234 235 # Handle anonymous structs... 236 for f in ty.fields: 237 anon = gen_ocaml_anonstruct(f.type, interface, "\t", f.name) 238 if anon is not None: 239 s += anon 240 s += "\n" 241 242 s += "\ttype t =\n" 243 s += "\t{\n" 244 s += gen_struct(ty, "\t\t") 245 s += "\t}\n" 246 247 if ty.init_fn is not None: 248 union_args = "".join([u + " -> " for u in union_types]) 249 if interface: 250 s += "\tval default : ctx -> %sunit -> t\n" % union_args 251 else: 252 s += "\texternal default : ctx -> %sunit -> t = \"stub_libxl_%s_init\"\n" % (union_args, ty.rawname) 253 254 if functions.has_key(ty.rawname): 255 for name,args in functions[ty.rawname]: 256 s += "\texternal %s : " % name 257 s += " -> ".join(args) 258 s += " = \"%s\"\n" % stub_fn_name(ty,name) 259 260 s += "end\n" 261 262 else: 263 raise NotImplementedError("%s" % type(ty)) 264 return s.replace("\n", "\n%s" % indent) 265 266def c_val(ty, c, o, indent="", parent = None): 267 s = indent 268 if isinstance(ty,idl.UInt): 269 if ty.width in [8, 16]: 270 # handle as ints 271 width = None 272 elif ty.width in [32, 64]: 273 width = ty.width 274 else: 275 raise NotImplementedError("Cannot handle %d-bit int" % ty.width) 276 if width: 277 s += "%s = Int%d_val(%s);" % (c, width, o) 278 else: 279 s += "%s = Int_val(%s);" % (c, o) 280 elif isinstance(ty,idl.Builtin): 281 if not builtins.has_key(ty.typename): 282 raise NotImplementedError("Unknown Builtin %s (%s)" % (ty.typename, type(ty))) 283 _,fn,_ = builtins[ty.typename] 284 if not fn: 285 raise NotImplementedError("No c_val fn for Builtin %s (%s)" % (ty.typename, type(ty))) 286 s += "%s;" % (fn % { "o": o, "c": c }) 287 elif isinstance (ty,idl.Array): 288 s += "{\n" 289 s += "\tint i;\n" 290 s += "\t%s = Wosize_val(%s);\n" % (parent + ty.lenvar.name, o) 291 s += "\t%s = (%s) calloc(%s, sizeof(*%s));\n" % (c, ty.typename, parent + ty.lenvar.name, c) 292 s += "\tfor(i=0; i<%s; i++) {\n" % (parent + ty.lenvar.name) 293 s += c_val(ty.elem_type, c+"[i]", "Field(%s, i)" % o, indent="\t\t", parent=parent) + "\n" 294 s += "\t}\n" 295 s += "}\n" 296 elif isinstance(ty,idl.Enumeration) and (parent is None): 297 n = 0 298 s += "switch(Int_val(%s)) {\n" % o 299 for e in ty.values: 300 s += " case %d: *%s = %s; break;\n" % (n, c, e.name) 301 n += 1 302 s += " default: failwith_xl(ERROR_FAIL, \"cannot convert value to %s\"); break;\n" % ty.typename 303 s += "}" 304 elif isinstance(ty, idl.KeyedUnion): 305 s += "{\n" 306 s += "\tif(Is_long(%s)) {\n" % o 307 n = 0 308 s += "\t\tswitch(Int_val(%s)) {\n" % o 309 for f in ty.fields: 310 if f.type is None or not f.type.has_fields(): 311 s += "\t\t case %d: %s = %s; break;\n" % (n, 312 parent + ty.keyvar.name, 313 f.enumname) 314 n += 1 315 s += "\t\t default: failwith_xl(ERROR_FAIL, \"variant handling bug %s%s (long)\"); break;\n" % (parent, ty.keyvar.name) 316 s += "\t\t}\n" 317 s += "\t} else {\n" 318 s += "\t\t/* Is block... */\n" 319 s += "\t\tswitch(Tag_val(%s)) {\n" % o 320 n = 0 321 for f in ty.fields: 322 if f.type is not None and f.type.has_fields(): 323 if f.type.private: 324 continue 325 s += "\t\t case %d:\n" % (n) 326 s += "\t\t %s = %s;\n" % (parent + ty.keyvar.name, f.enumname) 327 (nparent,fexpr) = ty.member(c, f, False) 328 s += "%s" % c_val(f.type, fexpr, "Field(%s, 0)" % o, parent=nparent, indent=indent+"\t\t ") 329 s += "break;\n" 330 n += 1 331 s += "\t\t default: failwith_xl(ERROR_FAIL, \"variant handling bug %s%s (block)\"); break;\n" % (parent, ty.keyvar.name) 332 s += "\t\t}\n" 333 s += "\t}\n" 334 s += "}" 335 elif isinstance(ty, idl.Aggregate) and (parent is None or ty.rawname is None): 336 n = 0 337 for f in ty.fields: 338 if f.type.private: 339 continue 340 (nparent,fexpr) = ty.member(c, f, ty.rawname is not None) 341 s += "%s\n" % c_val(f.type, fexpr, "Field(%s, %d)" % (o,n), parent=nparent) 342 n = n + 1 343 else: 344 s += "%s_val(ctx, %s, %s);" % (ty.rawname, ty.pass_arg(c, parent is None, passby=idl.PASS_BY_REFERENCE), o) 345 346 return s.replace("\n", "\n%s" % indent) 347 348def gen_c_val(ty, indent=""): 349 s = "/* Convert caml value to %s */\n" % ty.rawname 350 351 s += "static int %s_val (libxl_ctx *ctx, %s, value v)\n" % (ty.rawname, ty.make_arg("c_val", passby=idl.PASS_BY_REFERENCE)) 352 s += "{\n" 353 s += "\tCAMLparam1(v);\n" 354 s += "\n" 355 356 s += c_val(ty, "c_val", "v", indent="\t") + "\n" 357 358 s += "\tCAMLreturn(0);\n" 359 s += "}\n" 360 361 return s.replace("\n", "\n%s" % indent) 362 363def ocaml_Val(ty, o, c, indent="", parent = None): 364 s = indent 365 if isinstance(ty,idl.UInt): 366 if ty.width in [8, 16]: 367 # handle as ints 368 width = None 369 elif ty.width in [32, 64]: 370 width = ty.width 371 else: 372 raise NotImplementedError("Cannot handle %d-bit int" % ty.width) 373 if width: 374 s += "%s = caml_copy_int%d(%s);" % (o, width, c) 375 else: 376 s += "%s = Val_int(%s);" % (o, c) 377 elif isinstance(ty,idl.Builtin): 378 if not builtins.has_key(ty.typename): 379 raise NotImplementedError("Unknown Builtin %s (%s)" % (ty.typename, type(ty))) 380 _,_,fn = builtins[ty.typename] 381 if not fn: 382 raise NotImplementedError("No ocaml Val fn for Builtin %s (%s)" % (ty.typename, type(ty))) 383 s += "%s = %s;" % (o, fn % { "c": c }) 384 elif isinstance(ty, idl.Array): 385 s += "{\n" 386 s += "\t int i;\n" 387 s += "\t CAMLlocal1(array_elem);\n" 388 s += "\t %s = caml_alloc(%s,0);\n" % (o, parent + ty.lenvar.name) 389 s += "\t for(i=0; i<%s; i++) {\n" % (parent + ty.lenvar.name) 390 s += "\t %s\n" % ocaml_Val(ty.elem_type, "array_elem", c + "[i]", "", parent=parent) 391 s += "\t Store_field(%s, i, array_elem);\n" % o 392 s += "\t }\n" 393 s += "\t}" 394 elif isinstance(ty,idl.Enumeration) and (parent is None): 395 n = 0 396 s += "switch(%s) {\n" % c 397 for e in ty.values: 398 s += " case %s: %s = Val_int(%d); break;\n" % (e.name, o, n) 399 n += 1 400 s += " default: failwith_xl(ERROR_FAIL, \"cannot convert value from %s\"); break;\n" % ty.typename 401 s += "}" 402 elif isinstance(ty, idl.KeyedUnion): 403 n = 0 404 m = 0 405 s += "switch(%s) {\n" % (parent + ty.keyvar.name) 406 for f in ty.fields: 407 s += "\t case %s:\n" % f.enumname 408 if f.type is None: 409 s += "\t /* %d: None */\n" % n 410 s += "\t %s = Val_long(%d);\n" % (o,n) 411 n += 1 412 elif not f.type.has_fields(): 413 s += "\t /* %d: Long */\n" % n 414 s += "\t %s = Val_long(%d);\n" % (o,n) 415 n += 1 416 else: 417 s += "\t /* %d: Block */\n" % m 418 (nparent,fexpr) = ty.member(c, f, parent is None) 419 s += "\t {\n" 420 s += "\t\t CAMLlocal1(tmp);\n" 421 s += "\t\t %s = caml_alloc(%d,%d);\n" % (o, 1, m) 422 s += ocaml_Val(f.type, 'tmp', fexpr, indent="\t\t ", parent=nparent) 423 s += "\n" 424 s += "\t\t Store_field(%s, 0, tmp);\n" % o 425 s += "\t }\n" 426 m += 1 427 #s += "\t %s = caml_alloc(%d,%d);\n" % (o,len(f.type.fields),n) 428 s += "\t break;\n" 429 s += "\t default: failwith_xl(ERROR_FAIL, \"cannot convert value from %s\"); break;\n" % ty.typename 430 s += "\t}" 431 elif isinstance(ty,idl.Aggregate) and (parent is None or ty.rawname is None): 432 s += "{\n" 433 if ty.rawname is None: 434 fn = "anon_field" 435 else: 436 fn = "%s_field" % ty.rawname 437 s += "\tCAMLlocal1(%s);\n" % fn 438 s += "\n" 439 s += "\t%s = caml_alloc_tuple(%d);\n" % (o, len(ty.fields)) 440 441 n = 0 442 for f in ty.fields: 443 if f.type.private: 444 continue 445 446 (nparent,fexpr) = ty.member(c, f, parent is None) 447 448 s += "\n" 449 s += "\t%s\n" % ocaml_Val(f.type, fn, ty.pass_arg(fexpr, c), parent=nparent) 450 s += "\tStore_field(%s, %d, %s);\n" % (o, n, fn) 451 n = n + 1 452 s += "}" 453 else: 454 s += "%s = Val_%s(%s);" % (o, ty.rawname, ty.pass_arg(c, parent is None)) 455 456 return s.replace("\n", "\n%s" % indent).rstrip(indent) 457 458def gen_Val_ocaml(ty, indent=""): 459 s = "/* Convert %s to a caml value */\n" % ty.rawname 460 461 s += "static value Val_%s (%s)\n" % (ty.rawname, ty.make_arg(ty.rawname+"_c")) 462 s += "{\n" 463 s += "\tCAMLparam0();\n" 464 s += "\tCAMLlocal1(%s_ocaml);\n" % ty.rawname 465 466 s += ocaml_Val(ty, "%s_ocaml" % ty.rawname, "%s_c" % ty.rawname, indent="\t") + "\n" 467 468 s += "\tCAMLreturn(%s_ocaml);\n" % ty.rawname 469 s += "}\n" 470 return s.replace("\n", "\n%s" % indent) 471 472def gen_c_stub_prototype(ty, fns): 473 s = "/* Stubs for %s */\n" % ty.rawname 474 for name,args in fns: 475 # For N args we return one value and take N-1 values as parameters 476 s += "value %s(" % stub_fn_name(ty, name) 477 s += ", ".join(["value v%d" % v for v in range(1,len(args))]) 478 s += ");\n" 479 return s 480 481def gen_c_default(ty): 482 s = "/* Get the defaults for %s */\n" % ty.rawname 483 # Handle KeyedUnions... 484 union_types = [] 485 for f in ty.fields: 486 if isinstance(f.type, idl.KeyedUnion): 487 union_types.append(f.type.keyvar) 488 489 s += "value stub_libxl_%s_init(value ctx, %svalue unit)\n" % (ty.rawname, 490 "".join(["value " + u.name + ", " for u in union_types])) 491 s += "{\n" 492 s += "\tCAMLparam%d(ctx, %sunit);\n" % (len(union_types) + 2, "".join([u.name + ", " for u in union_types])) 493 s += "\tCAMLlocal1(val);\n" 494 s += "\tlibxl_%s c_val;\n" % ty.rawname 495 s += "\tlibxl_%s_init(&c_val);\n" % ty.rawname 496 for u in union_types: 497 s += "\tif (%s != Val_none) {\n" % u.name 498 s += "\t\t%s c = 0;\n" % u.type.typename 499 s += "\t\t%s_val(CTX, &c, Some_val(%s));\n" % (u.type.rawname, u.name) 500 s += "\t\tlibxl_%s_init_%s(&c_val, c);\n" % (ty.rawname, u.name) 501 s += "\t}\n" 502 s += "\tval = Val_%s(&c_val);\n" % ty.rawname 503 if ty.dispose_fn: 504 s += "\tlibxl_%s_dispose(&c_val);\n" % ty.rawname 505 s += "\tCAMLreturn(val);\n" 506 s += "}\n" 507 return s 508 509def gen_c_defaults(ty): 510 s = gen_c_default(ty) 511 return s 512 513def autogen_header(open_comment, close_comment): 514 s = open_comment + " AUTO-GENERATED FILE DO NOT EDIT " + close_comment + "\n" 515 s += open_comment + " autogenerated by \n" 516 s += reduce(lambda x,y: x + " ", range(len(open_comment + " ")), "") 517 s += "%s" % " ".join(sys.argv) 518 s += "\n " + close_comment + "\n\n" 519 return s 520 521if __name__ == '__main__': 522 if len(sys.argv) < 4: 523 print >>sys.stderr, "Usage: genwrap.py <idl> <mli> <ml> <c-inc>" 524 sys.exit(1) 525 526 (_,types) = idl.parse(sys.argv[1]) 527 528 # Do not generate these yet. 529 blacklist = [ 530 "cpupoolinfo", 531 "vcpuinfo", 532 ] 533 534 for t in blacklist: 535 if t not in [ty.rawname for ty in types]: 536 print "unknown type %s in blacklist" % t 537 538 types = [ty for ty in types if not ty.rawname in blacklist] 539 540 _ml = sys.argv[3] 541 ml = open(_ml, 'w') 542 ml.write(autogen_header("(*", "*)")) 543 544 _mli = sys.argv[2] 545 mli = open(_mli, 'w') 546 mli.write(autogen_header("(*", "*)")) 547 548 _cinc = sys.argv[4] 549 cinc = open(_cinc, 'w') 550 cinc.write(autogen_header("/*", "*/")) 551 552 for ty in types: 553 if ty.private: 554 continue 555 #sys.stdout.write(" TYPE %-20s " % ty.rawname) 556 ml.write(gen_ocaml_ml(ty, False)) 557 ml.write("\n") 558 559 mli.write(gen_ocaml_ml(ty, True)) 560 mli.write("\n") 561 562 if ty.marshal_in(): 563 cinc.write(gen_c_val(ty)) 564 cinc.write("\n") 565 cinc.write(gen_Val_ocaml(ty)) 566 cinc.write("\n") 567 if functions.has_key(ty.rawname): 568 cinc.write(gen_c_stub_prototype(ty, functions[ty.rawname])) 569 cinc.write("\n") 570 if ty.init_fn is not None: 571 cinc.write(gen_c_defaults(ty)) 572 cinc.write("\n") 573 #sys.stdout.write("\n") 574 575 ml.write("(* END OF AUTO-GENERATED CODE *)\n") 576 ml.close() 577 mli.write("(* END OF AUTO-GENERATED CODE *)\n") 578 mli.close() 579 cinc.close() 580