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):
24 def __len__(self): return 4
25 def __getitem__(self, i):
26 return (self.ptype, self.pname, self.pdflt, self.pnull)[i]
29 if old.pdflt is not None:
30 self.pdflt = old.pdflt
31 if old.pnull is not None:
32 self.pnull = old.pnull
34 # We currently subclass 'str' to make impact on the rest of codegen as
35 # little as possible. Later we can subclass 'object' instead, but
36 # then we must find and adapt all places which expect return types to
38 class ReturnType(str):
39 def __new__(cls, *args, **kwds):
40 return str.__new__(cls, *args[:1])
41 def __init__(self, type_name, optional=False):
43 self.optional = optional
45 # Parameter for property based constructors
46 class Property(object):
47 def __init__(self, pname, optional, argname):
49 self.optional = optional
50 self.argname = argname
52 def __len__(self): return 4
53 def __getitem__(self, i):
54 return ('', self.pname, self.optional, self.argname)[i]
57 if old.optional is not None:
58 self.optional = old.optional
59 if old.argname is not None:
60 self.argname = old.argname
63 class Definition(object):
67 return '%s.%s' % (self.module, self.name)
69 py_name = property(py_name)
71 def __init__(self, *args):
72 """Create a new defs object of this type. The arguments are the
73 components of the definition"""
74 raise RuntimeError("this is an abstract class")
77 """Merge in customisations from older version of definition"""
78 raise RuntimeError("this is an abstract class")
80 def write_defs(self, fp=sys.stdout):
81 """write out this definition in defs file format"""
82 raise RuntimeError("this is an abstract class")
84 def guess_return_value_ownership(self):
85 "return 1 if caller owns return value"
86 if getattr(self, 'is_constructor_of', False):
87 self.caller_owns_return = True
88 elif self.ret in ('char*', 'gchar*', 'string'):
89 self.caller_owns_return = True
91 self.caller_owns_return = False
94 class ObjectDef(Definition):
95 def __init__(self, name, *args):
103 self.class_init_func = None
104 self.has_new_constructor_api = False
105 for arg in get_valid_scheme_definitions(args):
106 if arg[0] == 'in-module':
108 elif arg[0] == 'docstring':
109 self.docstring = make_docstring(arg[1:])
110 elif arg[0] == 'parent':
112 elif arg[0] == 'c-name':
114 elif arg[0] == 'gtype-id':
115 self.typecode = arg[1]
116 elif arg[0] == 'fields':
118 self.fields.append((parg[0], parg[1]))
119 elif arg[0] == 'implements':
120 self.implements.append(arg[1])
121 def merge(self, old):
122 # currently the .h parser doesn't try to work out what fields of
123 # an object structure should be public, so we just copy the list
124 # from the old version ...
125 self.fields = old.fields
126 self.implements = old.implements
127 def write_defs(self, fp=sys.stdout):
128 fp.write('(define-object ' + self.name + '\n')
130 fp.write(' (in-module "' + self.module + '")\n')
131 if self.parent != (None, None):
132 fp.write(' (parent "' + self.parent + '")\n')
133 for interface in self.implements:
134 fp.write(' (implements "' + interface + '")\n')
136 fp.write(' (c-name "' + self.c_name + '")\n')
138 fp.write(' (gtype-id "' + self.typecode + '")\n')
140 fp.write(' (fields\n')
141 for (ftype, fname) in self.fields:
142 fp.write(' \'("' + ftype + '" "' + fname + '")\n')
146 class InterfaceDef(Definition):
147 def __init__(self, name, *args):
154 self.interface_info = None
155 for arg in get_valid_scheme_definitions(args):
156 if arg[0] == 'in-module':
158 elif arg[0] == 'docstring':
159 self.docstring = make_docstring(arg[1:])
160 elif arg[0] == 'c-name':
162 elif arg[0] == 'gtype-id':
163 self.typecode = arg[1]
164 elif arg[0] == 'vtable':
166 if self.vtable is None:
167 self.vtable = self.c_name + "Iface"
168 def write_defs(self, fp=sys.stdout):
169 fp.write('(define-interface ' + self.name + '\n')
171 fp.write(' (in-module "' + self.module + '")\n')
173 fp.write(' (c-name "' + self.c_name + '")\n')
175 fp.write(' (gtype-id "' + self.typecode + '")\n')
178 class EnumDef(Definition):
179 def __init__(self, name, *args):
180 self.deftype = 'enum'
182 self.in_module = None
186 for arg in get_valid_scheme_definitions(args):
187 if arg[0] == 'in-module':
188 self.in_module = arg[1]
189 elif arg[0] == 'c-name':
191 elif arg[0] == 'gtype-id':
192 self.typecode = arg[1]
193 elif arg[0] == 'values':
195 self.values.append((varg[0], varg[1]))
196 def merge(self, old):
198 def write_defs(self, fp=sys.stdout):
199 fp.write('(define-' + self.deftype + ' ' + self.name + '\n')
201 fp.write(' (in-module "' + self.in_module + '")\n')
202 fp.write(' (c-name "' + self.c_name + '")\n')
203 fp.write(' (gtype-id "' + self.typecode + '")\n')
205 fp.write(' (values\n')
206 for name, val in self.values:
207 fp.write(' \'("' + name + '" "' + val + '")\n')
211 class FlagsDef(EnumDef):
212 def __init__(self, *args):
213 apply(EnumDef.__init__, (self,) + args)
214 self.deftype = 'flags'
216 class BoxedDef(Definition):
217 def __init__(self, name, *args):
225 for arg in get_valid_scheme_definitions(args):
226 if arg[0] == 'in-module':
228 elif arg[0] == 'c-name':
230 elif arg[0] == 'gtype-id':
231 self.typecode = arg[1]
232 elif arg[0] == 'copy-func':
234 elif arg[0] == 'release-func':
235 self.release = arg[1]
236 elif arg[0] == 'fields':
238 self.fields.append((parg[0], parg[1]))
239 def merge(self, old):
240 # currently the .h parser doesn't try to work out what fields of
241 # an object structure should be public, so we just copy the list
242 # from the old version ...
243 self.fields = old.fields
244 def write_defs(self, fp=sys.stdout):
245 fp.write('(define-boxed ' + self.name + '\n')
247 fp.write(' (in-module "' + self.module + '")\n')
249 fp.write(' (c-name "' + self.c_name + '")\n')
251 fp.write(' (gtype-id "' + self.typecode + '")\n')
253 fp.write(' (copy-func "' + self.copy + '")\n')
255 fp.write(' (release-func "' + self.release + '")\n')
257 fp.write(' (fields\n')
258 for (ftype, fname) in self.fields:
259 fp.write(' \'("' + ftype + '" "' + fname + '")\n')
263 class PointerDef(Definition):
264 def __init__(self, name, *args):
270 for arg in get_valid_scheme_definitions(args):
271 if arg[0] == 'in-module':
273 elif arg[0] == 'c-name':
275 elif arg[0] == 'gtype-id':
276 self.typecode = arg[1]
277 elif arg[0] == 'fields':
279 self.fields.append((parg[0], parg[1]))
280 def merge(self, old):
281 # currently the .h parser doesn't try to work out what fields of
282 # an object structure should be public, so we just copy the list
283 # from the old version ...
284 self.fields = old.fields
285 def write_defs(self, fp=sys.stdout):
286 fp.write('(define-pointer ' + self.name + '\n')
288 fp.write(' (in-module "' + self.module + '")\n')
290 fp.write(' (c-name "' + self.c_name + '")\n')
292 fp.write(' (gtype-id "' + self.typecode + '")\n')
294 fp.write(' (fields\n')
295 for (ftype, fname) in self.fields:
296 fp.write(' \'("' + ftype + '" "' + fname + '")\n')
300 class MethodDefBase(Definition):
301 def __init__(self, name, *args):
305 self.caller_owns_return = None
306 self.unblock_threads = None
309 self.of_object = None
310 self.params = [] # of form (type, name, default, nullok)
312 self.deprecated = None
313 for arg in get_valid_scheme_definitions(args):
314 if arg[0] == 'of-object':
315 self.of_object = arg[1]
316 elif arg[0] == 'docstring':
317 self.docstring = make_docstring(arg[1:])
318 elif arg[0] == 'c-name':
320 elif arg[0] == 'gtype-id':
321 self.typecode = arg[1]
322 elif arg[0] == 'return-type':
326 if prop[0] == 'optional':
328 self.ret = ReturnType(type_name, optional)
329 elif arg[0] == 'caller-owns-return':
330 self.caller_owns_return = arg[1] in ('t', '#t')
331 elif arg[0] == 'unblock-threads':
332 self.unblock_threads = arg[1] in ('t', '#t')
333 elif arg[0] == 'parameters':
340 for farg in parg[2:]:
341 assert isinstance(farg, tuple)
342 if farg[0] == 'default':
344 elif farg[0] == 'null-ok':
346 elif farg[0] == 'direction':
348 self.params.append(Parameter(ptype, pname, pdflt, pnull, pdir))
349 elif arg[0] == 'varargs':
350 self.varargs = arg[1] in ('t', '#t')
351 elif arg[0] == 'deprecated':
352 self.deprecated = arg[1]
354 sys.stderr.write("Warning: %s argument unsupported.\n"
358 self.write_defs(sys.stderr)
360 if self.caller_owns_return is None and self.ret is not None:
361 self.guess_return_value_ownership()
363 def merge(self, old, parmerge):
364 self.caller_owns_return = old.caller_owns_return
365 self.varargs = old.varargs
366 # here we merge extra parameter flags accross to the new object.
368 self.params = copy.deepcopy(old.params)
370 for i in range(len(self.params)):
371 ptype, pname, pdflt, pnull = self.params[i]
372 for p2 in old.params:
374 self.params[i] = (ptype, pname, p2[2], p2[3])
376 def _write_defs(self, fp=sys.stdout):
377 if self.of_object != (None, None):
378 fp.write(' (of-object "' + self.of_object + '")\n')
380 fp.write(' (c-name "' + self.c_name + '")\n')
382 fp.write(' (gtype-id "' + self.typecode + '")\n')
383 if self.caller_owns_return:
384 fp.write(' (caller-owns-return #t)\n')
385 if self.unblock_threads:
386 fp.write(' (unblock_threads #t)\n')
388 fp.write(' (return-type "' + self.ret + '")\n')
390 fp.write(' (deprecated "' + self.deprecated + '")\n')
392 fp.write(' (parameters\n')
393 for ptype, pname, pdflt, pnull in self.params:
394 fp.write(' \'("' + ptype + '" "' + pname +'"')
395 if pdflt: fp.write(' (default "' + pdflt + '")')
396 if pnull: fp.write(' (null-ok)')
400 fp.write(' (varargs #t)\n')
404 class MethodDef(MethodDefBase):
405 def __init__(self, name, *args):
406 MethodDefBase.__init__(self, name, *args)
407 for item in ('c_name', 'of_object'):
408 if self.__dict__[item] == None:
409 self.write_defs(sys.stderr)
410 raise RuntimeError("definition missing required %s" % (item,))
412 def write_defs(self, fp=sys.stdout):
413 fp.write('(define-method ' + self.name + '\n')
416 class VirtualDef(MethodDefBase):
417 def write_defs(self, fp=sys.stdout):
418 fp.write('(define-virtual ' + self.name + '\n')
421 class FunctionDef(Definition):
422 def __init__(self, name, *args):
425 self.in_module = None
426 self.is_constructor_of = None
428 self.caller_owns_return = None
429 self.unblock_threads = None
432 self.params = [] # of form (type, name, default, nullok)
434 self.deprecated = None
435 for arg in get_valid_scheme_definitions(args):
436 if arg[0] == 'in-module':
437 self.in_module = arg[1]
438 elif arg[0] == 'docstring':
439 self.docstring = make_docstring(arg[1:])
440 elif arg[0] == 'is-constructor-of':
441 self.is_constructor_of = arg[1]
442 elif arg[0] == 'c-name':
444 elif arg[0] == 'gtype-id':
445 self.typecode = arg[1]
446 elif arg[0] == 'return-type':
448 elif arg[0] == 'caller-owns-return':
449 self.caller_owns_return = arg[1] in ('t', '#t')
450 elif arg[0] == 'unblock-threads':
451 self.unblock_threads = arg[1] in ('t', '#t')
452 elif arg[0] == 'parameters':
458 for farg in parg[2:]:
459 if farg[0] == 'default':
461 elif farg[0] == 'null-ok':
463 self.params.append(Parameter(ptype, pname, pdflt, pnull))
464 elif arg[0] == 'properties':
465 if self.is_constructor_of is None:
466 print >> sys.stderr, "Warning: (properties ...) "\
467 "is only valid for constructors"
472 for farg in prop[1:]:
473 if farg[0] == 'optional':
475 elif farg[0] == 'argname':
477 self.params.append(Property(pname, optional, argname))
478 elif arg[0] == 'varargs':
479 self.varargs = arg[1] in ('t', '#t')
480 elif arg[0] == 'deprecated':
481 self.deprecated = arg[1]
483 sys.stderr.write("Warning: %s argument unsupported\n"
487 self.write_defs(sys.stderr)
489 if self.caller_owns_return is None and self.ret is not None:
490 self.guess_return_value_ownership()
491 for item in ('c_name',):
492 if self.__dict__[item] == None:
493 self.write_defs(sys.stderr)
494 raise RuntimeError("definition missing required %s" % (item,))
496 _method_write_defs = MethodDef.__dict__['write_defs']
498 def merge(self, old, parmerge):
499 self.caller_owns_return = old.caller_owns_return
500 self.varargs = old.varargs
502 self.params = copy.deepcopy(old.params)
504 # here we merge extra parameter flags accross to the new object.
505 def merge_param(param):
506 for old_param in old.params:
507 if old_param.pname == param.pname:
508 if isinstance(old_param, Property):
509 # h2def never scans Property's, therefore if
510 # we have one it was manually written, so we
512 return copy.deepcopy(old_param)
514 param.merge(old_param)
516 raise RuntimeError("could not find %s in old_parameters %r" % (
517 param.pname, [p.pname for p in old.params]))
519 self.params = map(merge_param, self.params)
521 # parameter names changed and we can't find a match; it's
522 # safer to keep the old parameter list untouched.
523 self.params = copy.deepcopy(old.params)
525 if not self.is_constructor_of:
527 self.is_constructor_of = old.is_constructor_of
528 except AttributeError:
530 if isinstance(old, MethodDef):
532 # transmogrify from function into method ...
533 self.write_defs = self._method_write_defs
534 self.of_object = old.of_object
536 def write_defs(self, fp=sys.stdout):
537 fp.write('(define-function ' + self.name + '\n')
539 fp.write(' (in-module "' + self.in_module + '")\n')
540 if self.is_constructor_of:
541 fp.write(' (is-constructor-of "' + self.is_constructor_of +'")\n')
543 fp.write(' (c-name "' + self.c_name + '")\n')
545 fp.write(' (gtype-id "' + self.typecode + '")\n')
546 if self.caller_owns_return:
547 fp.write(' (caller-owns-return #t)\n')
548 if self.unblock_threads:
549 fp.write(' (unblock-threads #t)\n')
551 fp.write(' (return-type "' + self.ret + '")\n')
553 fp.write(' (deprecated "' + self.deprecated + '")\n')
555 if isinstance(self.params[0], Parameter):
556 fp.write(' (parameters\n')
557 for ptype, pname, pdflt, pnull in self.params:
558 fp.write(' \'("' + ptype + '" "' + pname +'"')
559 if pdflt: fp.write(' (default "' + pdflt + '")')
560 if pnull: fp.write(' (null-ok)')
563 elif isinstance(self.params[0], Property):
564 fp.write(' (properties\n')
565 for prop in self.params:
566 fp.write(' \'("' + prop.pname +'"')
567 if prop.optional: fp.write(' (optional)')
571 assert False, "strange parameter list %r" % self.params[0]
573 fp.write(' (varargs #t)\n')