1 # -*- Mode: Python; py-indent-offset: 4 -*-
5 def get_valid_scheme_definitions(defs):
6 return [x for x in defs if isinstance(x, tuple) and len(x) >= 2]
9 s = s.replace('\r\n', '\\r\\n').replace('\t', '\\t')
10 return s.replace('\r', '\\r').replace('\n', '\\n')
12 def make_docstring(lines):
13 return "(char *) " + '\n'.join(['"%s"' % unescape(s) for s in lines])
15 # New Parameter class, wich emulates a tuple for compatibility reasons
16 class Parameter(object):
17 def __init__(self, ptype, pname, pdflt, pnull, pdir=None, keeprefcount = False):
23 self.keeprefcount = keeprefcount
25 def __len__(self): return 4
26 def __getitem__(self, i):
27 return (self.ptype, self.pname, self.pdflt, self.pnull)[i]
30 if old.pdflt is not None:
31 self.pdflt = old.pdflt
32 if old.pnull is not None:
33 self.pnull = old.pnull
35 # Parameter for property based constructors
36 class Property(object):
37 def __init__(self, pname, optional, argname):
39 self.optional = optional
40 self.argname = argname
43 if old.optional is not None:
44 self.optional = old.optional
45 if old.argname is not None:
46 self.argname = old.argname
51 def __init__(self, *args):
52 """Create a new defs object of this type. The arguments are the
53 components of the definition"""
54 raise RuntimeError, "this is an abstract class"
56 """Merge in customisations from older version of definition"""
57 raise RuntimeError, "this is an abstract class"
58 def write_defs(self, fp=sys.stdout):
59 """write out this definition in defs file format"""
60 raise RuntimeError, "this is an abstract class"
62 def guess_return_value_ownership(self):
63 "return 1 if caller owns return value"
64 if getattr(self, 'is_constructor_of', False):
65 self.caller_owns_return = True
66 elif self.ret in ('char*', 'gchar*', 'string'):
67 self.caller_owns_return = True
69 self.caller_owns_return = False
72 class ObjectDef(Definition):
73 def __init__(self, name, *args):
81 self.class_init_func = None
82 self.has_new_constructor_api = False
83 for arg in get_valid_scheme_definitions(args):
84 if arg[0] == 'in-module':
86 elif arg[0] == 'docstring':
87 self.docstring = make_docstring(arg[1:])
88 elif arg[0] == 'parent':
90 elif arg[0] == 'c-name':
92 elif arg[0] == 'gtype-id':
93 self.typecode = arg[1]
94 elif arg[0] == 'fields':
96 self.fields.append((parg[0], parg[1]))
97 elif arg[0] == 'implements':
98 self.implements.append(arg[1])
100 # currently the .h parser doesn't try to work out what fields of
101 # an object structure should be public, so we just copy the list
102 # from the old version ...
103 self.fields = old.fields
104 self.implements = old.implements
105 def write_defs(self, fp=sys.stdout):
106 fp.write('(define-object ' + self.name + '\n')
108 fp.write(' (in-module "' + self.module + '")\n')
109 if self.parent != (None, None):
110 fp.write(' (parent "' + self.parent + '")\n')
111 for interface in self.implements:
112 fp.write(' (implements "' + interface + '")\n')
114 fp.write(' (c-name "' + self.c_name + '")\n')
116 fp.write(' (gtype-id "' + self.typecode + '")\n')
118 fp.write(' (fields\n')
119 for (ftype, fname) in self.fields:
120 fp.write(' \'("' + ftype + '" "' + fname + '")\n')
124 class MiniObjectDef(Definition):
125 def __init__(self, name, *args):
134 if type(arg) != type(()) or len(arg) < 2:
136 if arg[0] == 'in-module':
138 elif arg[0] == 'parent':
140 elif arg[0] == 'c-name':
142 elif arg[0] == 'gtype-id':
143 self.typecode = arg[1]
144 elif arg[0] == 'fields':
146 self.fields.append((parg[0], parg[1]))
147 elif arg[0] == 'implements':
148 self.implements.append(arg[1])
149 def merge(self, old):
150 # currently the .h parser doesn't try to work out what fields of
151 # an object structure should be public, so we just copy the list
152 # from the old version ...
153 self.fields = old.fields
154 self.implements = old.implements
155 def write_defs(self, fp=sys.stdout):
156 fp.write('(define-object ' + self.name + '\n')
158 fp.write(' (in-module "' + self.module + '")\n')
159 if self.parent != (None, None):
160 fp.write(' (parent "' + self.parent + '")\n')
161 for interface in self.implements:
162 fp.write(' (implements "' + interface + '")\n')
164 fp.write(' (c-name "' + self.c_name + '")\n')
166 fp.write(' (gtype-id "' + self.typecode + '")\n')
168 fp.write(' (fields\n')
169 for (ftype, fname) in self.fields:
170 fp.write(' \'("' + ftype + '" "' + fname + '")\n')
175 class InterfaceDef(Definition):
176 def __init__(self, name, *args):
183 self.interface_info = None
184 for arg in get_valid_scheme_definitions(args):
185 if arg[0] == 'in-module':
187 elif arg[0] == 'docstring':
188 self.docstring = make_docstring(arg[1:])
189 elif arg[0] == 'c-name':
191 elif arg[0] == 'gtype-id':
192 self.typecode = arg[1]
193 elif arg[0] == 'vtable':
195 if self.vtable is None:
196 self.vtable = self.c_name + "Iface"
197 def write_defs(self, fp=sys.stdout):
198 fp.write('(define-interface ' + self.name + '\n')
200 fp.write(' (in-module "' + self.module + '")\n')
202 fp.write(' (c-name "' + self.c_name + '")\n')
204 fp.write(' (gtype-id "' + self.typecode + '")\n')
207 class EnumDef(Definition):
208 def __init__(self, name, *args):
209 self.deftype = 'enum'
211 self.in_module = None
215 for arg in get_valid_scheme_definitions(args):
216 if arg[0] == 'in-module':
217 self.in_module = arg[1]
218 elif arg[0] == 'c-name':
220 elif arg[0] == 'gtype-id':
221 self.typecode = arg[1]
222 elif arg[0] == 'values':
224 self.values.append((varg[0], varg[1]))
225 def merge(self, old):
227 def write_defs(self, fp=sys.stdout):
228 fp.write('(define-' + self.deftype + ' ' + self.name + '\n')
230 fp.write(' (in-module "' + self.in_module + '")\n')
231 fp.write(' (c-name "' + self.c_name + '")\n')
232 fp.write(' (gtype-id "' + self.typecode + '")\n')
234 fp.write(' (values\n')
235 for name, val in self.values:
236 fp.write(' \'("' + name + '" "' + val + '")\n')
240 class FlagsDef(EnumDef):
241 def __init__(self, *args):
242 apply(EnumDef.__init__, (self,) + args)
243 self.deftype = 'flags'
245 class BoxedDef(Definition):
246 def __init__(self, name, *args):
254 for arg in get_valid_scheme_definitions(args):
255 if arg[0] == 'in-module':
257 elif arg[0] == 'c-name':
259 elif arg[0] == 'gtype-id':
260 self.typecode = arg[1]
261 elif arg[0] == 'copy-func':
263 elif arg[0] == 'release-func':
264 self.release = arg[1]
265 elif arg[0] == 'fields':
267 self.fields.append((parg[0], parg[1]))
268 def merge(self, old):
269 # currently the .h parser doesn't try to work out what fields of
270 # an object structure should be public, so we just copy the list
271 # from the old version ...
272 self.fields = old.fields
273 def write_defs(self, fp=sys.stdout):
274 fp.write('(define-boxed ' + self.name + '\n')
276 fp.write(' (in-module "' + self.module + '")\n')
278 fp.write(' (c-name "' + self.c_name + '")\n')
280 fp.write(' (gtype-id "' + self.typecode + '")\n')
282 fp.write(' (copy-func "' + self.copy + '")\n')
284 fp.write(' (release-func "' + self.release + '")\n')
286 fp.write(' (fields\n')
287 for (ftype, fname) in self.fields:
288 fp.write(' \'("' + ftype + '" "' + fname + '")\n')
292 class PointerDef(Definition):
293 def __init__(self, name, *args):
299 for arg in get_valid_scheme_definitions(args):
300 if arg[0] == 'in-module':
302 elif arg[0] == 'c-name':
304 elif arg[0] == 'gtype-id':
305 self.typecode = arg[1]
306 elif arg[0] == 'fields':
308 self.fields.append((parg[0], parg[1]))
309 def merge(self, old):
310 # currently the .h parser doesn't try to work out what fields of
311 # an object structure should be public, so we just copy the list
312 # from the old version ...
313 self.fields = old.fields
314 def write_defs(self, fp=sys.stdout):
315 fp.write('(define-pointer ' + self.name + '\n')
317 fp.write(' (in-module "' + self.module + '")\n')
319 fp.write(' (c-name "' + self.c_name + '")\n')
321 fp.write(' (gtype-id "' + self.typecode + '")\n')
323 fp.write(' (fields\n')
324 for (ftype, fname) in self.fields:
325 fp.write(' \'("' + ftype + '" "' + fname + '")\n')
329 class MethodDefBase(Definition):
330 def __init__(self, name, *args):
334 self.caller_owns_return = None
335 self.unblock_threads = None
338 self.of_object = None
339 self.params = [] # of form (type, name, default, nullok)
341 self.deprecated = None
342 for arg in get_valid_scheme_definitions(args):
343 if arg[0] == 'of-object':
344 self.of_object = arg[1]
345 elif arg[0] == 'docstring':
346 self.docstring = make_docstring(arg[1:])
347 elif arg[0] == 'c-name':
349 elif arg[0] == 'gtype-id':
350 self.typecode = arg[1]
351 elif arg[0] == 'return-type':
353 elif arg[0] == 'caller-owns-return':
354 self.caller_owns_return = arg[1] in ('t', '#t')
355 elif arg[0] == 'unblock-threads':
356 self.unblock_threads = arg[1] in ('t', '#t')
357 elif arg[0] == 'parameters':
365 for farg in parg[2:]:
366 assert isinstance(farg, tuple)
367 if farg[0] == 'default':
369 elif farg[0] == 'null-ok':
371 elif farg[0] == 'direction':
373 elif farg[0] == 'keep-refcount':
375 self.params.append(Parameter(ptype, pname, pdflt, pnull, pdir,
376 keeprefcount=keeprefcount))
377 elif arg[0] == 'varargs':
378 self.varargs = arg[1] in ('t', '#t')
379 elif arg[0] == 'deprecated':
380 self.deprecated = arg[1]
382 sys.stderr.write("Warning: %s argument unsupported.\n"
386 self.write_defs(sys.stderr)
388 if self.caller_owns_return is None and self.ret is not None:
389 self.guess_return_value_ownership()
391 def merge(self, old, parmerge):
392 self.caller_owns_return = old.caller_owns_return
393 self.varargs = old.varargs
394 # here we merge extra parameter flags accross to the new object.
396 self.params = copy.deepcopy(old.params)
398 for i in range(len(self.params)):
399 ptype, pname, pdflt, pnull = self.params[i]
400 for p2 in old.params:
402 self.params[i] = (ptype, pname, p2[2], p2[3])
404 def _write_defs(self, fp=sys.stdout):
405 if self.of_object != (None, None):
406 fp.write(' (of-object "' + self.of_object + '")\n')
408 fp.write(' (c-name "' + self.c_name + '")\n')
410 fp.write(' (gtype-id "' + self.typecode + '")\n')
411 if self.caller_owns_return:
412 fp.write(' (caller-owns-return #t)\n')
413 if self.unblock_threads:
414 fp.write(' (unblock_threads #t)\n')
416 fp.write(' (return-type "' + self.ret + '")\n')
418 fp.write(' (deprecated "' + self.deprecated + '")\n')
420 fp.write(' (parameters\n')
421 for ptype, pname, pdflt, pnull in self.params:
422 fp.write(' \'("' + ptype + '" "' + pname +'"')
423 if pdflt: fp.write(' (default "' + pdflt + '")')
424 if pnull: fp.write(' (null-ok)')
428 fp.write(' (varargs #t)\n')
432 class MethodDef(MethodDefBase):
433 def __init__(self, name, *args):
434 MethodDefBase.__init__(self, name, *args)
435 for item in ('c_name', 'of_object'):
436 if self.__dict__[item] == None:
437 self.write_defs(sys.stderr)
438 raise RuntimeError, "definition missing required %s" % (item,)
440 def write_defs(self, fp=sys.stdout):
441 fp.write('(define-method ' + self.name + '\n')
444 class VirtualDef(MethodDefBase):
445 def write_defs(self, fp=sys.stdout):
446 fp.write('(define-virtual ' + self.name + '\n')
449 class FunctionDef(Definition):
450 def __init__(self, name, *args):
453 self.in_module = None
454 self.is_constructor_of = None
456 self.caller_owns_return = None
457 self.unblock_threads = None
460 self.params = [] # of form (type, name, default, nullok)
462 self.deprecated = None
463 for arg in get_valid_scheme_definitions(args):
464 if arg[0] == 'in-module':
465 self.in_module = arg[1]
466 elif arg[0] == 'docstring':
467 self.docstring = make_docstring(arg[1:])
468 elif arg[0] == 'is-constructor-of':
469 self.is_constructor_of = arg[1]
470 elif arg[0] == 'c-name':
472 elif arg[0] == 'gtype-id':
473 self.typecode = arg[1]
474 elif arg[0] == 'return-type':
476 elif arg[0] == 'caller-owns-return':
477 self.caller_owns_return = arg[1] in ('t', '#t')
478 elif arg[0] == 'unblock-threads':
479 self.unblock_threads = arg[1] in ('t', '#t')
480 elif arg[0] == 'parameters':
487 for farg in parg[2:]:
488 if farg[0] == 'default':
490 elif farg[0] == 'null-ok':
492 elif farg[0] == 'keep-refcount':
494 self.params.append(Parameter(ptype, pname, pdflt, pnull,
495 keeprefcount = keeprefcount))
496 elif arg[0] == 'properties':
497 if self.is_constructor_of is None:
498 print >> sys.stderr, "Warning: (properties ...) "\
499 "is only valid for constructors"
504 for farg in prop[1:]:
505 if farg[0] == 'optional':
507 elif farg[0] == 'argname':
509 self.params.append(Property(pname, optional, argname))
510 elif arg[0] == 'varargs':
511 self.varargs = arg[1] in ('t', '#t')
512 elif arg[0] == 'deprecated':
513 self.deprecated = arg[1]
515 sys.stderr.write("Warning: %s argument unsupported\n"
519 self.write_defs(sys.stderr)
521 if self.caller_owns_return is None and self.ret is not None:
522 self.guess_return_value_ownership()
523 for item in ('c_name',):
524 if self.__dict__[item] == None:
525 self.write_defs(sys.stderr)
526 raise RuntimeError, "definition missing required %s" % (item,)
528 _method_write_defs = MethodDef.__dict__['write_defs']
530 def merge(self, old, parmerge):
531 self.caller_owns_return = old.caller_owns_return
532 self.varargs = old.varargs
534 self.params = copy.deepcopy(old.params)
536 # here we merge extra parameter flags accross to the new object.
537 def merge_param(param):
538 for old_param in old.params:
539 if old_param.pname == param.pname:
540 if isinstance(old_param, Property):
541 # h2def never scans Property's, therefore if
542 # we have one it was manually written, so we
544 return copy.deepcopy(old_param)
546 param.merge(old_param)
548 raise RuntimeError, "could not find %s in old_parameters %r" % (
549 param.pname, [p.pname for p in old.params])
551 self.params = map(merge_param, self.params)
553 # parameter names changed and we can't find a match; it's
554 # safer to keep the old parameter list untouched.
555 self.params = copy.deepcopy(old.params)
557 if not self.is_constructor_of:
559 self.is_constructor_of = old.is_constructor_of
560 except AttributeError:
562 if isinstance(old, MethodDef):
564 # transmogrify from function into method ...
565 self.write_defs = self._method_write_defs
566 self.of_object = old.of_object
568 def write_defs(self, fp=sys.stdout):
569 fp.write('(define-function ' + self.name + '\n')
571 fp.write(' (in-module "' + self.in_module + '")\n')
572 if self.is_constructor_of:
573 fp.write(' (is-constructor-of "' + self.is_constructor_of +'")\n')
575 fp.write(' (c-name "' + self.c_name + '")\n')
577 fp.write(' (gtype-id "' + self.typecode + '")\n')
578 if self.caller_owns_return:
579 fp.write(' (caller-owns-return #t)\n')
580 if self.unblock_threads:
581 fp.write(' (unblock-threads #t)\n')
583 fp.write(' (return-type "' + self.ret + '")\n')
585 fp.write(' (deprecated "' + self.deprecated + '")\n')
587 if isinstance(self.params[0], Parameter):
588 fp.write(' (parameters\n')
589 for ptype, pname, pdflt, pnull in self.params:
590 fp.write(' \'("' + ptype + '" "' + pname +'"')
591 if pdflt: fp.write(' (default "' + pdflt + '")')
592 if pnull: fp.write(' (null-ok)')
595 elif isinstance(self.params[0], Property):
596 fp.write(' (properties\n')
597 for prop in self.params:
598 fp.write(' \'("' + prop.pname +'"')
599 if prop.optional: fp.write(' (optional)')
603 assert False, "strange parameter list %r" % self.params[0]
605 fp.write(' (varargs #t)\n')