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