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