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