Mercurial > pidgin
comparison src/dbus-analyze-functions.py @ 11241:66f872f30e40
[gaim-migrate @ 13404]
New shared library libgaim-client, which provides C bindings to
communicate with gaim.
committer: Tailor Script <tailor@pidgin.im>
author | Piotr Zielinski <zielaj> |
---|---|
date | Fri, 12 Aug 2005 16:56:45 +0000 |
parents | 744c0708d11f |
children | 421a8523ad04 |
comparison
equal
deleted
inserted
replaced
11240:2ab2de8add8b | 11241:66f872f30e40 |
---|---|
2 # | 2 # |
3 # with option --mode=xml: xml dbus specification | 3 # with option --mode=xml: xml dbus specification |
4 # with option --mode=c: C wrappers | 4 # with option --mode=c: C wrappers |
5 # | 5 # |
6 | 6 |
7 | |
8 | |
9 import re | 7 import re |
10 import string | 8 import string |
11 import sys | 9 import sys |
10 | |
11 | |
12 # list of object types | |
13 | |
14 # objecttypes = [] | |
15 | |
16 # for objecttype in file("dbus-auto-structs.txt"): | |
17 # objecttypes.append(objecttype.strip()) | |
18 | |
19 # a dictionary of simple types | |
20 # each TYPE maps into a pair (dbus-type-name, compatible-c-type-name) | |
21 # if compatible-c-type-name is None then it is the same as TYPE | |
22 | |
23 # simpletypes = { | |
24 # "int" : ("i", None), | |
25 # "gint" : ("i", None), | |
26 # "guint" : ("u", None), | |
27 # "gboolean" : ("i", "int") | |
28 # } | |
29 | |
30 | |
31 simpletypes = ["int", "gint", "guint", "gboolean"] | |
32 | |
33 # for enum in file("dbus-auto-enums.txt"): | |
34 # simpletypes[enum.strip()] = ("i", "int") | |
35 | |
36 # functions that shouldn't be exported | |
37 | |
38 excluded = ["gaim_accounts_load", "gaim_account_set_presence", | |
39 "gaim_conv_placement_get_fnc_id", "gaim_conv_placement_add_fnc", | |
40 "gaim_presence_add_list"] | |
41 | |
42 stringlists = [] | |
43 | |
44 pointer = "#pointer#" | |
45 myexception = "My Exception" | |
46 | |
47 def ctopascal(name): | |
48 newname = "" | |
49 for word in name.split("_"): | |
50 newname += word.capitalize() | |
51 return newname | |
52 | |
53 class Parameter: | |
54 def __init__(self, type, name): | |
55 self.name = name | |
56 self.type = type | |
57 | |
58 def fromtokens(tokens, parameternumber = -1): | |
59 if len(tokens) == 0: | |
60 raise myexception | |
61 if (len(tokens) == 1) or (tokens[-1] == pointer): | |
62 if parameternumber >= 0: | |
63 return Parameter(tokens, "param%i" % parameternumber) | |
64 else: | |
65 raise myexception | |
66 else: | |
67 return Parameter(tokens[:-1], tokens[-1]) | |
68 | |
69 fromtokens = staticmethod(fromtokens) | |
70 | |
71 class Binding: | |
72 def __init__(self, functiontext, paramtexts): | |
73 self.function = Parameter.fromtokens(functiontext.split()) | |
74 | |
75 if self.function.name in excluded: | |
76 raise myexception | |
77 | |
78 self.params = [] | |
79 for i in range(len(paramtexts)): | |
80 self.params.append(Parameter.fromtokens(paramtexts[i].split(), i)) | |
81 | |
82 self.call = "%s(%s)" % (self.function.name, | |
83 ", ".join([param.name for param in self.params])) | |
84 | |
85 | |
86 def process(self): | |
87 for param in self.params: | |
88 self.processinput(param.type, param.name) | |
89 | |
90 self.processoutput(self.function.type, "RESULT") | |
91 self.flush() | |
92 | |
93 | |
94 def processinput(self, type, name): | |
95 const = False | |
96 if type[0] == "const": | |
97 type = type[1:] | |
98 const = True | |
99 | |
100 if len(type) == 1: | |
101 # simple types (int, gboolean, etc.) and enums | |
102 if (type[0] in simpletypes) or (type[0].startswith("Gaim")): | |
103 return self.inputsimple(type, name) | |
104 | |
105 | |
106 # va_list, replace by NULL | |
107 if type[0] == "va_list": | |
108 return self.inputvalist(type, name) | |
109 | |
110 # pointers ... | |
111 if (len(type) == 2) and (type[1] == pointer): | |
112 # strings | |
113 if type[0] == "char": | |
114 if const: | |
115 return self.inputstring(type, name) | |
116 else: | |
117 raise myexception | |
118 | |
119 elif type[0] == "GHashTable": | |
120 return self.inputhash(type, name) | |
121 | |
122 # known object types are transformed to integer handles | |
123 elif type[0].startswith("Gaim"): | |
124 return self.inputgaimstructure(type, name) | |
125 | |
126 # unknown pointers are always replaced with NULL | |
127 else: | |
128 return self.inputpointer(type, name) | |
129 return | |
130 | |
131 raise myexception | |
132 | |
133 | |
134 def processoutput(self, type, name): | |
135 # the "void" type is simple ... | |
136 if type == ["void"]: | |
137 return self.outputvoid(type, name) | |
138 | |
139 const = False | |
140 if type[0] == "const": | |
141 type = type[1:] | |
142 const = True | |
143 | |
144 # a string | |
145 if type == ["char", pointer]: | |
146 return self.outputstring(type, name, const) | |
147 | |
148 # simple types (ints, booleans, enums, ...) | |
149 if (len(type) == 1) and \ | |
150 ((type[0] in simpletypes) or (type[0].startswith("Gaim"))): | |
151 return self.outputsimple(type, name) | |
152 | |
153 # pointers ... | |
154 if (len(type) == 2) and (type[1] == pointer): | |
155 | |
156 # handles | |
157 if type[0].startswith("Gaim"): | |
158 return self.outputgaimstructure(type, name) | |
159 | |
160 if type[0] in ["GList", "GSList"]: | |
161 return self.outputlist(type, name) | |
162 | |
163 raise myexception | |
164 | |
165 | |
166 class ClientBinding (Binding): | |
167 def __init__(self, functiontext, paramtexts, knowntypes, headersonly): | |
168 Binding.__init__(self, functiontext, paramtexts) | |
169 self.knowntypes = knowntypes | |
170 self.headersonly = headersonly | |
171 self.paramshdr = [] | |
172 self.decls = [] | |
173 self.inputparams = [] | |
174 self.outputparams = [] | |
175 self.returncode = [] | |
176 | |
177 def flush(self): | |
178 print "%s %s(%s)" % (self.functiontype, self.function.name, | |
179 ", ".join(self.paramshdr)), | |
180 | |
181 if self.headersonly: | |
182 print ";" | |
183 return | |
184 | |
185 print "{" | |
186 | |
187 for decl in self.decls: | |
188 print decl | |
189 | |
190 print 'dbus_g_proxy_call(gaim_proxy, "%s", NULL,' % ctopascal(self.function.name) | |
191 | |
192 for type_name in self.inputparams: | |
193 print "G_TYPE_%s, %s, " % type_name, | |
194 print "G_TYPE_INVALID," | |
195 | |
196 for type_name in self.outputparams: | |
197 print "G_TYPE_%s, &%s, " % type_name, | |
198 print "G_TYPE_INVALID);" | |
199 | |
200 for code in self.returncode: | |
201 print code | |
202 | |
203 print "}\n" | |
204 | |
205 | |
206 def definegaimstructure(self, type): | |
207 if (self.headersonly) and (type[0] not in self.knowntypes): | |
208 print "struct _%s;" % type[0] | |
209 print "typedef struct _%s %s;" % (type[0], type[0]) | |
210 self.knowntypes.append(type[0]) | |
211 | |
212 # fixme | |
213 def definegaimenum(self, type): | |
214 if (self.headersonly) and (type[0] not in self.knowntypes) \ | |
215 and (type[0] not in simpletypes): | |
216 print "typedef int %s;" % type[0] | |
217 self.knowntypes.append(type[0]) | |
218 | |
219 def inputsimple(self, type, name): | |
220 self.paramshdr.append("%s %s" % (type[0], name)) | |
221 self.inputparams.append(("INT", name)) | |
222 self.definegaimenum(type) | |
223 | |
224 def inputvalist(self, type, name): | |
225 self.paramshdr.append("...") | |
226 | |
227 def inputstring(self, type, name): | |
228 self.paramshdr.append("const char *%s" % name) | |
229 self.inputparams.append(("STRING", name)) | |
230 | |
231 def inputgaimstructure(self, type, name): | |
232 self.paramshdr.append("%s *%s" % (type[0], name)) | |
233 self.inputparams.append(("INT", "GPOINTER_TO_INT(%s)" % name)) | |
234 self.definegaimstructure(type) | |
235 | |
236 def inputpointer(self, type, name): | |
237 self.paramshdr.append("%s *%s" % (type[0], name)) | |
238 self.inputparams.append(("INT", "0")) | |
239 | |
240 def inputhash(self, type, name): | |
241 raise myexception | |
242 | |
243 | |
244 def outputvoid(self, type, name): | |
245 self.functiontype = "void" | |
246 | |
247 def outputstring(self, type, name, const): | |
248 self.functiontype = "char*" | |
249 self.decls.append("char *%s = NULL;" % name) | |
250 self.outputparams.append(("STRING", name)) | |
251 # self.returncode.append("NULLIFY(%s);" % name) | |
252 self.returncode.append("return %s;" % name); | |
253 | |
254 def outputsimple(self, type, name): | |
255 self.functiontype = type[0] | |
256 self.decls.append("%s %s = 0;" % (type[0], name)) | |
257 self.outputparams.append(("INT", name)) | |
258 self.returncode.append("return %s;" % name); | |
259 self.definegaimenum(type) | |
260 | |
261 def outputgaimstructure(self, type, name): | |
262 name = name + "_ID" | |
263 self.functiontype = "%s*" % type[0] | |
264 self.decls.append("int %s = 0;" % name) | |
265 self.outputparams.append(("INT", "%s" % name)) | |
266 self.returncode.append("return (%s*) GINT_TO_POINTER(%s);" % (type[0], name)); | |
267 self.definegaimstructure(type) | |
268 | |
269 def outputlist(self, type, name): | |
270 raise myexception | |
271 | |
272 | |
273 | |
274 class ServerBinding (Binding): | |
275 def __init__(self, functiontext, paramtexts): | |
276 Binding.__init__(self, functiontext, paramtexts) | |
277 self.dparams = "" | |
278 self.cparams = [] | |
279 self.cdecls = [] | |
280 self.ccode = [] | |
281 self.cparamsout = [] | |
282 self.ccodeout = [] | |
283 self.argfunc = "dbus_message_get_args" | |
284 | |
285 def flush(self): | |
286 print "static DBusMessage*" | |
287 print "%s_DBUS(DBusMessage *message_DBUS, DBusError *error_DBUS) {" % \ | |
288 self.function.name | |
289 | |
290 print "DBusMessage *reply_DBUS;" | |
291 | |
292 for decl in self.cdecls: | |
293 print decl | |
294 | |
295 print "%s(message_DBUS, error_DBUS, " % self.argfunc, | |
296 for param in self.cparams: | |
297 print "DBUS_TYPE_%s, &%s," % param, | |
298 print "DBUS_TYPE_INVALID);" | |
299 | |
300 print "CHECK_ERROR(error_DBUS);" | |
301 | |
302 for code in self.ccode: | |
303 print code | |
304 | |
305 print "reply_DBUS = dbus_message_new_method_return (message_DBUS);" | |
306 | |
307 print "dbus_message_append_args(reply_DBUS, ", | |
308 for param in self.cparamsout: | |
309 if type(param) is str: | |
310 print "%s, " % param | |
311 else: | |
312 print "DBUS_TYPE_%s, &%s, " % param, | |
313 print "DBUS_TYPE_INVALID);" | |
314 | |
315 for code in self.ccodeout: | |
316 print code | |
317 | |
318 print "return reply_DBUS;\n}\n" | |
319 | |
320 | |
321 def addstring(self, *items): | |
322 for item in items: | |
323 self.dparams += item + r"\0" | |
324 | |
325 def addintype(self, type, name): | |
326 self.addstring("in", type, name) | |
327 | |
328 def addouttype(self, type, name): | |
329 self.addstring("out", type, name) | |
330 | |
331 | |
332 # input parameters | |
333 | |
334 def inputsimple(self, type, name): | |
335 self.cdecls.append("dbus_int32_t %s;" % name) | |
336 self.cparams.append(("INT32", name)) | |
337 self.addintype("i", name) | |
338 | |
339 def inputvalist(self, type, name): | |
340 self.cdecls.append("va_list %s;" % name); | |
341 self.ccode.append("%s = NULL;" % name); | |
342 | |
343 def inputstring(self, type, name): | |
344 self.cdecls.append("const char *%s;" % name) | |
345 self.cparams.append(("STRING", name)) | |
346 self.ccode .append("NULLIFY(%s);" % name) | |
347 self.addintype("s", name) | |
348 | |
349 def inputhash(self, type, name): | |
350 self.argfunc = "gaim_dbus_message_get_args" | |
351 self.cdecls.append("DBusMessageIter %s_ITER;" % name) | |
352 self.cdecls.append("GHashTable *%s;" % name) | |
353 self.cparams.append(("ARRAY", "%s_ITER" % name)) | |
354 self.ccode.append("%s = gaim_dbus_iter_hash_table(&%s_ITER, error_DBUS);" \ | |
355 % (name, name)) | |
356 self.ccode.append("CHECK_ERROR(error_DBUS);") | |
357 self.ccodeout.append("g_hash_table_destroy(%s);" % name) | |
358 self.addintype("a{ss}", name) | |
359 | |
360 def inputgaimstructure(self, type, name): | |
361 self.cdecls.append("dbus_int32_t %s_ID;" % name) | |
362 self.cdecls.append("%s *%s;" % (type[0], name)) | |
363 self.cparams.append(("INT32", name + "_ID")) | |
364 self.ccode.append("GAIM_DBUS_ID_TO_POINTER(%s, %s_ID, %s, error_DBUS);" % \ | |
365 (name, name, type[0])) | |
366 self.addintype("i", name) | |
367 | |
368 def inputpointer(self, type, name): | |
369 self.cdecls.append("dbus_int32_t %s_NULL;" % name) | |
370 self.cdecls .append("%s *%s;" % (type[0], name)) | |
371 self.cparams.append(("INT32", name + "_NULL")) | |
372 self.ccode .append("%s = NULL;" % name) | |
373 self.addintype("i", name) | |
374 | |
375 # output parameters | |
376 | |
377 def outputvoid(self, type, name): | |
378 self.ccode.append("%s;" % self.call) # just call the function | |
379 | |
380 def outputstring(self, type, name, const): | |
381 self.cdecls.append("const char *%s;" % name) | |
382 self.ccode.append("%s = null_to_empty(%s);" % (name, self.call)) | |
383 self.cparamsout.append(("STRING", name)) | |
384 self.addouttype("s", name) | |
385 if not const: | |
386 self.ccodeout.append("g_free(%s);" % name) | |
387 | |
388 def outputsimple(self, type, name): | |
389 self.cdecls.append("dbus_int32_t %s;" % name) | |
390 self.ccode.append("%s = %s;" % (name, self.call)) | |
391 self.cparamsout.append(("INT32", name)) | |
392 self.addouttype("i", name) | |
393 | |
394 def outputgaimstructure(self, type, name): | |
395 self.cdecls.append("dbus_int32_t %s;" % name) | |
396 self.ccode .append("GAIM_DBUS_POINTER_TO_ID(%s, %s, error_DBUS);" % (name, self.call)) | |
397 self.cparamsout.append(("INT32", name)) | |
398 self.addouttype("i", name) | |
399 | |
400 # GList*, GSList*, assume that list is a list of objects | |
401 | |
402 # fixme: at the moment, we do NOT free the memory occupied by | |
403 # the list, we should free it if the list has NOT been declared const | |
404 | |
405 # fixme: we assume that this is a list of objects, not a list | |
406 # of strings | |
407 | |
408 def outputlist(self, type, name): | |
409 self.cdecls.append("dbus_int32_t %s_LEN;" % name) | |
410 self.ccodeout.append("g_free(%s);" % name) | |
411 | |
412 if self.function.name in stringlists: | |
413 self.cdecls.append("char **%s;" % name) | |
414 self.ccode.append("%s = gaim_%s_to_array(%s, FALSE, &%s_LEN);" % \ | |
415 (name, type[0], self.call, name)) | |
416 self.cparamsout.append("DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &%s, %s_LEN" \ | |
417 % (name, name)) | |
418 self.addouttype("as", name) | |
419 else: | |
420 self.cdecls.append("dbus_int32_t *%s;" % name) | |
421 self.ccode.append("%s = gaim_dbusify_%s(%s, FALSE, &%s_LEN);" % \ | |
422 (name, type[0], self.call, name)) | |
423 self.cparamsout.append("DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, &%s, %s_LEN" \ | |
424 % (name, name)) | |
425 self.addouttype("ai", name) | |
426 | |
427 | |
428 class BindingSet: | |
429 regexp = r"^(\w[^()]*)\(([^()]*)\)\s*;\s*$"; | |
430 | |
431 def __init__(self, inputfile, fprefix): | |
432 self.inputiter = iter(inputfile) | |
433 self.functionregexp = \ | |
434 re.compile("^%s(\w[^()]*)\(([^()]*)\)\s*;\s*$" % fprefix) | |
435 | |
436 | |
437 | |
438 def process(self): | |
439 print "/* Generated by %s. Do not edit! */" % sys.argv[0] | |
440 | |
441 for line in self.inputiter: | |
442 words = line.split() | |
443 if len(words) == 0: # empty line | |
444 continue | |
445 if line[0] == "#": # preprocessor directive | |
446 continue | |
447 if words[0] in ["typedef", "struct", "enum", "static"]: | |
448 continue | |
449 | |
450 # accumulate lines until the parentheses are balance or an | |
451 # empty line has been encountered | |
452 myline = line.strip() | |
453 while myline.count("(") > myline.count(")"): | |
454 newline = self.inputiter.next().strip() | |
455 if len(newline) == 0: | |
456 break | |
457 myline += " " + newline | |
458 | |
459 # is this a function declaration? | |
460 thematch = self.functionregexp.match( | |
461 myline.replace("*", " " + pointer + " ")) | |
462 | |
463 if thematch is None: | |
464 continue | |
465 | |
466 functiontext = thematch.group(1) | |
467 paramstext = thematch.group(2).strip() | |
468 | |
469 if (paramstext == "void") or (paramstext == ""): | |
470 paramtexts = [] | |
471 else: | |
472 paramtexts = paramstext.split(",") | |
473 | |
474 try: | |
475 self.processfunction(functiontext, paramtexts) | |
476 except myexception: | |
477 sys.stderr.write(myline + "\n") | |
478 except: | |
479 sys.stderr.write(myline + "\n") | |
480 raise | |
481 | |
482 self.flush() | |
483 | |
484 class ServerBindingSet (BindingSet): | |
485 def __init__(self, inputfile, fprefix): | |
486 BindingSet.__init__(self, inputfile, fprefix) | |
487 self.functions = [] | |
488 | |
489 | |
490 def processfunction(self, functiontext, paramtexts): | |
491 binding = ServerBinding(functiontext, paramtexts) | |
492 binding.process() | |
493 self.functions.append((binding.function.name, binding.dparams)) | |
494 | |
495 def flush(self): | |
496 print "static GaimDBusBinding bindings_DBUS[] = { " | |
497 for function, params in self.functions: | |
498 print '{"%s", "%s", %s_DBUS},' % \ | |
499 (ctopascal(function), params, function) | |
500 | |
501 print "{NULL, NULL}" | |
502 print "};" | |
503 | |
504 print "#define GAIM_DBUS_REGISTER_BINDINGS(handle) gaim_dbus_register_bindings(handle, bindings_DBUS)" | |
505 | |
506 class ClientBindingSet (BindingSet): | |
507 def __init__(self, inputfile, fprefix, headersonly): | |
508 BindingSet.__init__(self, inputfile, fprefix) | |
509 self.functions = [] | |
510 self.knowntypes = [] | |
511 self.headersonly = headersonly | |
512 | |
513 def processfunction(self, functiontext, paramtexts): | |
514 binding = ClientBinding(functiontext, paramtexts, self.knowntypes, self.headersonly) | |
515 binding.process() | |
516 | |
517 def flush(self): | |
518 pass | |
519 | |
520 # Main program | |
12 | 521 |
13 options = {} | 522 options = {} |
14 | 523 |
15 for arg in sys.argv[1:]: | 524 for arg in sys.argv[1:]: |
16 if arg[0:2] == "--": | 525 if arg[0:2] == "--": |
19 if len(mylist) > 1: | 528 if len(mylist) > 1: |
20 options[command] = mylist[1] | 529 options[command] = mylist[1] |
21 else: | 530 else: |
22 options[command] = None | 531 options[command] = None |
23 | 532 |
24 # list of object types | |
25 | |
26 # objecttypes = [] | |
27 | |
28 # for objecttype in file("dbus-auto-structs.txt"): | |
29 # objecttypes.append(objecttype.strip()) | |
30 | |
31 # a dictionary of simple types | |
32 # each TYPE maps into a pair (dbus-type-name, compatible-c-type-name) | |
33 # if compatible-c-type-name is None then it is the same as TYPE | |
34 | |
35 # simpletypes = { | |
36 # "int" : ("i", None), | |
37 # "gint" : ("i", None), | |
38 # "guint" : ("u", None), | |
39 # "gboolean" : ("i", "int") | |
40 # } | |
41 | |
42 | |
43 simpletypes = ["int", "gint", "guint", "gboolean"] | |
44 | |
45 # for enum in file("dbus-auto-enums.txt"): | |
46 # simpletypes[enum.strip()] = ("i", "int") | |
47 | |
48 # functions that shouldn't be exported | |
49 | |
50 excluded = ["gaim_accounts_load", "gaim_account_set_presence", | |
51 "gaim_conv_placement_get_fnc_id", "gaim_conv_placement_add_fnc", | |
52 "gaim_presence_add_list"] | |
53 | |
54 stringlists = [] | |
55 | |
56 pointer = "#pointer#" | |
57 | |
58 functions = [] | |
59 | |
60 dparams = "" | |
61 cparams = [] | |
62 cparamsout = [] | |
63 cdecls = [] | |
64 ccode = [] | |
65 ccodeout = [] | |
66 | |
67 myexception = "My Exception" | |
68 | |
69 def ctopascal(name): | |
70 newname = "" | |
71 for word in name.split("_"): | |
72 newname += word.capitalize() | |
73 return newname | |
74 | |
75 def c_print(function): | |
76 print "static DBusMessage *%s_DBUS(DBusMessage *message_DBUS, DBusError *error_DBUS) {" \ | |
77 % function | |
78 | |
79 print "DBusMessage *reply_DBUS;" | |
80 | |
81 for decl in cdecls: | |
82 print decl | |
83 | |
84 print "%s(message_DBUS, error_DBUS, " % argfunc, | |
85 for param in cparams: | |
86 print "DBUS_TYPE_%s, &%s," % param, | |
87 print "DBUS_TYPE_INVALID);" | |
88 | |
89 print "CHECK_ERROR(error_DBUS);" | |
90 | |
91 for code in ccode: | |
92 print code | |
93 | |
94 print "reply_DBUS = dbus_message_new_method_return (message_DBUS);" | |
95 | |
96 print "dbus_message_append_args(reply_DBUS, ", | |
97 for param in cparamsout: | |
98 if type(param) is str: | |
99 print "%s, " % param | |
100 else: | |
101 print "DBUS_TYPE_%s, &%s, " % param, | |
102 print "DBUS_TYPE_INVALID);" | |
103 | |
104 for code in ccodeout: | |
105 print code | |
106 | |
107 print "return reply_DBUS;\n}\n" | |
108 | |
109 functions.append((function, dparams)) | |
110 | |
111 def c_clear(): | |
112 global cparams, cdecls, ccode, cparamsout, ccodeout, dparams, argfunc | |
113 dparams = "" | |
114 cparams = [] | |
115 cdecls = [] | |
116 ccode = [] | |
117 cparamsout = [] | |
118 ccodeout = [] | |
119 argfunc = "dbus_message_get_args" | |
120 | |
121 | |
122 def addstring(*items): | |
123 global dparams | |
124 for item in items: | |
125 dparams += item + r"\0" | |
126 | |
127 def addintype(type, name): | |
128 addstring("in", type, name) | |
129 | |
130 def addouttype(type, name): | |
131 addstring("out", type, name) | |
132 | |
133 def printdispatchtable(): | |
134 print "static GaimDBusBinding bindings_DBUS[] = { " | |
135 for function, params in functions: | |
136 print '{"%s", "%s", %s_DBUS},' % (ctopascal(function), params, function) | |
137 print "{NULL, NULL}" | |
138 print "};" | |
139 | |
140 print "#define GAIM_DBUS_REGISTER_BINDINGS(handle) gaim_dbus_register_bindings(handle, bindings_DBUS)" | |
141 | |
142 # processing an input parameter | |
143 | |
144 def inputvar(mytype, name): | |
145 global ccode, cparams, cdecls, ccodeout, argfunc | |
146 const = False | |
147 if mytype[0] == "const": | |
148 mytype = mytype[1:] | |
149 const = True | |
150 | |
151 | |
152 | |
153 | |
154 if len(mytype) == 1: | |
155 # simple types (int, gboolean, etc.) and enums | |
156 if (mytype[0] in simpletypes) or (mytype[0].startswith("Gaim")): | |
157 cdecls.append("dbus_int32_t %s;" % name) | |
158 cparams.append(("INT32", name)) | |
159 addintype("i", name) | |
160 return | |
161 | |
162 # va_list, replace by NULL | |
163 if mytype[0] == "va_list": | |
164 cdecls.append("va_list %s;" % name); | |
165 ccode.append("%s = NULL;" % name); | |
166 return | |
167 | |
168 # pointers ... | |
169 if (len(mytype) == 2) and (mytype[1] == pointer): | |
170 # strings | |
171 if mytype[0] == "char": | |
172 if const: | |
173 cdecls.append("const char *%s;" % name) | |
174 cparams.append(("STRING", name)) | |
175 ccode .append("NULLIFY(%s);" % name) | |
176 addintype("s", name) | |
177 return | |
178 else: | |
179 raise myexception | |
180 | |
181 # memory leak if an error occurs later ... | |
182 elif mytype[0] == "GHashTable": | |
183 argfunc = "gaim_dbus_message_get_args" | |
184 cdecls.append("DBusMessageIter %s_ITER;" % name) | |
185 cdecls.append("GHashTable *%s;" % name) | |
186 cparams.append(("ARRAY", "%s_ITER" % name)) | |
187 ccode.append("%s = gaim_dbus_iter_hash_table(&%s_ITER, error_DBUS);" \ | |
188 % (name, name)) | |
189 ccode.append("CHECK_ERROR(error_DBUS);") | |
190 ccodeout.append("g_hash_table_destroy(%s);" % name) | |
191 addintype("a{ss}", name) | |
192 return | |
193 | |
194 # known object types are transformed to integer handles | |
195 elif mytype[0].startswith("Gaim"): | |
196 cdecls.append("dbus_int32_t %s_ID;" % name) | |
197 cdecls.append("%s *%s;" % (mytype[0], name)) | |
198 cparams.append(("INT32", name + "_ID")) | |
199 ccode.append("GAIM_DBUS_ID_TO_POINTER(%s, %s_ID, %s, error_DBUS);" % \ | |
200 (name, name, mytype[0])) | |
201 addintype("i", name) | |
202 return | |
203 | |
204 # unknown pointers are always replaced with NULL | |
205 else: | |
206 cdecls.append("dbus_int32_t %s_NULL;" % name) | |
207 cdecls .append("%s *%s;" % (mytype[0], name)) | |
208 cparams.append(("INT32", name + "_NULL")) | |
209 ccode .append("%s = NULL;" % name) | |
210 addintype("i", name) | |
211 return | |
212 | |
213 raise myexception | |
214 | |
215 | |
216 | |
217 # processing an output parameter | |
218 | |
219 def outputvar(mytype, name, call, function): | |
220 # the "void" type is simple ... | |
221 if mytype == ["void"]: | |
222 ccode.append("%s;" % call) # just call the function | |
223 return | |
224 | |
225 const = False | |
226 if mytype[0] == "const": | |
227 mytype = mytype[1:] | |
228 const = True | |
229 | |
230 | |
231 # a string | |
232 if mytype == ["char", pointer]: | |
233 cdecls.append("const char *%s;" % name) | |
234 ccode.append("%s = null_to_empty(%s);" % (name, call)) | |
235 cparamsout.append(("STRING", name)) | |
236 addouttype("s", name) | |
237 if not const: | |
238 ccodeout.append("g_free(%s);" % name) | |
239 return | |
240 | |
241 # simple types (ints, booleans, enums, ...) | |
242 if (len(mytype) == 1) and \ | |
243 ((mytype[0] in simpletypes) or (mytype[0].startswith("Gaim"))): | |
244 cdecls.append("dbus_int32_t %s;" % name) | |
245 ccode.append("%s = %s;" % (name, call)) | |
246 cparamsout.append(("INT32", name)) | |
247 addouttype("i", name) | |
248 return | |
249 | |
250 # pointers ... | |
251 if (len(mytype) == 2) and (mytype[1] == pointer): | |
252 | |
253 # handles | |
254 if mytype[0].startswith("Gaim"): | |
255 cdecls.append("dbus_int32_t %s;" % name) | |
256 ccode .append("GAIM_DBUS_POINTER_TO_ID(%s, %s, error_DBUS);" % (name, call)) | |
257 cparamsout.append(("INT32", name)) | |
258 addouttype("i", name) | |
259 return | |
260 | |
261 # GList*, GSList*, assume that list is a list of objects | |
262 | |
263 # fixme: at the moment, we do NOT free the memory occupied by | |
264 # the list, we should free it if the list has NOT been declared const | |
265 | |
266 # fixme: we assume that this is a list of objects, not a list | |
267 # of strings | |
268 | |
269 if mytype[0] in ["GList", "GSList"]: | |
270 cdecls.append("dbus_int32_t %s_LEN;" % name) | |
271 ccodeout.append("g_free(%s);" % name) | |
272 | |
273 if function in stringlists: | |
274 cdecls.append("char **%s;" % name) | |
275 ccode.append("%s = gaim_%s_to_array(%s, FALSE, &%s_LEN);" % \ | |
276 (name, mytype[0], call, name)) | |
277 cparamsout.append("DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &%s, %s_LEN" \ | |
278 % (name, name)) | |
279 addouttype("as", name) | |
280 else: | |
281 cdecls.append("dbus_int32_t *%s;" % name) | |
282 ccode.append("%s = gaim_dbusify_%s(%s, FALSE, &%s_LEN);" % \ | |
283 (name, mytype[0], call, name)) | |
284 cparamsout.append("DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, &%s, %s_LEN" \ | |
285 % (name, name)) | |
286 addouttype("ai", name) | |
287 return | |
288 | |
289 raise myexception | |
290 | |
291 | |
292 | |
293 def processfunction(functionparam, paramlist): | |
294 c_clear() | |
295 | |
296 ftokens = functionparam.split() | |
297 functiontype, function = ftokens[:-1], ftokens[-1] | |
298 | |
299 if function in excluded: | |
300 return | |
301 | |
302 origfunction = function | |
303 function = function.lower() | |
304 | |
305 names = [] | |
306 unnamed = 0 | |
307 for param in paramlist: | |
308 tokens = param.split() | |
309 if len(tokens) == 0: | |
310 raise myexception | |
311 if (len(tokens) == 1) or (tokens[-1] == pointer): | |
312 unnamed += 1 | |
313 type, name = tokens, "param%i" % unnamed | |
314 else: | |
315 type, name = tokens[:-1], tokens[-1] | |
316 inputvar(type, name) | |
317 names.append(name) | |
318 | |
319 outputvar(functiontype, "RESULT", | |
320 "%s(%s)" % (origfunction, ", ".join(names)), function) | |
321 | |
322 c_print(function) | |
323 | |
324 | |
325 | |
326 | |
327 print "/* Generated by %s. Do not edit! */" % sys.argv[0] | |
328 | |
329 | |
330 | |
331 regexp = r"^(\w[^()]*)\(([^()]*)\)\s*;\s*$"; | |
332 | |
333 | |
334 if "export-only" in options: | 533 if "export-only" in options: |
335 fprefix = "DBUS_EXPORT\s+" | 534 fprefix = "DBUS_EXPORT\s+" |
336 else: | 535 else: |
337 fprefix = "" | 536 fprefix = "" |
338 | 537 |
339 functionregexp = re.compile("^%s(\w[^()]*)\(([^()]*)\)\s*;\s*$" % fprefix) | 538 if "client" in options: |
340 | 539 bindings = ClientBindingSet(sys.stdin, fprefix, |
341 inputiter = iter(sys.stdin) | 540 options.has_key("headers")) |
342 | 541 else: |
343 for line in inputiter: | 542 bindings = ServerBindingSet(sys.stdin, fprefix) |
344 words = line.split() | 543 bindings.process() |
345 if len(words) == 0: # empty line | 544 |
346 continue | 545 |
347 if line[0] == "#": # preprocessor directive | 546 |
348 continue | 547 |
349 if words[0] in ["typedef", "struct", "enum", "static"]: | |
350 continue | |
351 | |
352 # accumulate lines until the parentheses are balance or an | |
353 # empty line has been encountered | |
354 myline = line.strip() | |
355 while myline.count("(") > myline.count(")"): | |
356 newline = inputiter.next().strip() | |
357 if len(newline) == 0: | |
358 break | |
359 myline += " " + newline | |
360 | |
361 # is this a function declaration? | |
362 thematch = functionregexp.match( | |
363 myline.replace("*", " " + pointer + " ")) | |
364 | |
365 if thematch is None: | |
366 continue | |
367 | |
368 function = thematch.group(1) | |
369 parameters = thematch.group(2).strip() | |
370 | |
371 if (parameters == "void") or (parameters == ""): | |
372 paramlist = [] | |
373 else: | |
374 paramlist = parameters.split(",") | |
375 | |
376 try: | |
377 processfunction(function, paramlist) | |
378 except myexception: | |
379 sys.stderr.write(myline + "\n") | |
380 except: | |
381 sys.stderr.write(myline + "\n") | |
382 raise | |
383 | |
384 printdispatchtable() | |
385 |