11146
|
1 # This programs takes a C header file as the input and produces:
|
|
2 #
|
|
3 # with option --mode=xml: xml dbus specification
|
|
4 # with option --mode=c: C wrappers
|
|
5 #
|
|
6
|
|
7
|
|
8
|
|
9 import re
|
|
10 import string
|
|
11 import sys
|
|
12
|
11171
|
13 options = {}
|
11146
|
14
|
|
15 for arg in sys.argv[1:]:
|
11171
|
16 if arg[0:2] == "--":
|
|
17 mylist = arg[2:].split("=",1)
|
|
18 command = mylist[0]
|
|
19 if len(mylist) > 1:
|
|
20 options[command] = mylist[1]
|
|
21 else:
|
|
22 options[command] = None
|
11146
|
23
|
|
24 # list of object types
|
|
25
|
11171
|
26 # objecttypes = []
|
11146
|
27
|
11171
|
28 # for objecttype in file("dbus-auto-structs.txt"):
|
|
29 # objecttypes.append(objecttype.strip())
|
11146
|
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
|
11171
|
35 # simpletypes = {
|
|
36 # "int" : ("i", None),
|
|
37 # "gint" : ("i", None),
|
|
38 # "guint" : ("u", None),
|
|
39 # "gboolean" : ("i", "int")
|
|
40 # }
|
11146
|
41
|
11187
|
42
|
11171
|
43 simpletypes = ["int", "gint", "guint", "gboolean"]
|
|
44
|
|
45 # for enum in file("dbus-auto-enums.txt"):
|
|
46 # simpletypes[enum.strip()] = ("i", "int")
|
11146
|
47
|
|
48 # functions that shouldn't be exported
|
|
49
|
11171
|
50 excluded = ["gaim_accounts_load", "gaim_account_set_presence",
|
11187
|
51 "gaim_conv_placement_get_fnc_id", "gaim_conv_placement_add_fnc",
|
|
52 "gaim_presence_add_list"]
|
|
53
|
|
54 stringlists = []
|
11146
|
55
|
|
56 pointer = "#pointer#"
|
11171
|
57
|
|
58 functions = []
|
11146
|
59
|
11175
|
60 dparams = ""
|
11146
|
61 cparams = []
|
11171
|
62 cparamsout = []
|
11146
|
63 cdecls = []
|
|
64 ccode = []
|
11171
|
65 ccodeout = []
|
11146
|
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
|
11171
|
75 def c_print(function):
|
|
76 print "static DBusMessage *%s_DBUS(DBusMessage *message_DBUS, DBusError *error_DBUS) {" \
|
|
77 % function
|
11146
|
78
|
11171
|
79 print "DBusMessage *reply_DBUS;"
|
11146
|
80
|
|
81 for decl in cdecls:
|
|
82 print decl
|
|
83
|
11187
|
84 print "%s(message_DBUS, error_DBUS, " % argfunc,
|
11171
|
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
|
11146
|
91 for code in ccode:
|
|
92 print code
|
|
93
|
11171
|
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
|
11175
|
109 functions.append((function, dparams))
|
11171
|
110
|
11146
|
111 def c_clear():
|
11187
|
112 global cparams, cdecls, ccode, cparamsout, ccodeout, dparams, argfunc
|
11175
|
113 dparams = ""
|
11146
|
114 cparams = []
|
|
115 cdecls = []
|
|
116 ccode = []
|
11171
|
117 cparamsout = []
|
|
118 ccodeout = []
|
11187
|
119 argfunc = "dbus_message_get_args"
|
11146
|
120
|
|
121
|
11175
|
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
|
11171
|
133 def printdispatchtable():
|
|
134 print "static GaimDBusBinding bindings_DBUS[] = { "
|
11175
|
135 for function, params in functions:
|
|
136 print '{"%s", "%s", %s_DBUS},' % (ctopascal(function), params, function)
|
11171
|
137 print "{NULL, NULL}"
|
|
138 print "};"
|
|
139
|
|
140 print "#define GAIM_DBUS_REGISTER_BINDINGS(handle) gaim_dbus_register_bindings(handle, bindings_DBUS)"
|
|
141
|
11146
|
142 # processing an input parameter
|
|
143
|
|
144 def inputvar(mytype, name):
|
11187
|
145 global ccode, cparams, cdecls, ccodeout, argfunc
|
11146
|
146 const = False
|
|
147 if mytype[0] == "const":
|
|
148 mytype = mytype[1:]
|
|
149 const = True
|
|
150
|
11187
|
151
|
|
152
|
11146
|
153
|
11187
|
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
|
11146
|
161
|
11187
|
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 ...
|
11146
|
169 if (len(mytype) == 2) and (mytype[1] == pointer):
|
|
170 # strings
|
|
171 if mytype[0] == "char":
|
|
172 if const:
|
11171
|
173 cdecls.append("const char *%s;" % name)
|
|
174 cparams.append(("STRING", name))
|
11146
|
175 ccode .append("NULLIFY(%s);" % name)
|
11175
|
176 addintype("s", name)
|
11146
|
177 return
|
|
178 else:
|
|
179 raise myexception
|
|
180
|
11187
|
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
|
11146
|
194 # known object types are transformed to integer handles
|
11171
|
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);" % \
|
11146
|
200 (name, name, mytype[0]))
|
11175
|
201 addintype("i", name)
|
11146
|
202 return
|
|
203
|
|
204 # unknown pointers are always replaced with NULL
|
|
205 else:
|
11171
|
206 cdecls.append("dbus_int32_t %s_NULL;" % name)
|
11146
|
207 cdecls .append("%s *%s;" % (mytype[0], name))
|
11171
|
208 cparams.append(("INT32", name + "_NULL"))
|
11146
|
209 ccode .append("%s = NULL;" % name)
|
11175
|
210 addintype("i", name)
|
11146
|
211 return
|
|
212
|
|
213 raise myexception
|
|
214
|
|
215
|
|
216
|
|
217 # processing an output parameter
|
|
218
|
11187
|
219 def outputvar(mytype, name, call, function):
|
11146
|
220 # the "void" type is simple ...
|
|
221 if mytype == ["void"]:
|
|
222 ccode.append("%s;" % call) # just call the function
|
|
223 return
|
|
224
|
11187
|
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]:
|
11171
|
233 cdecls.append("const char *%s;" % name)
|
|
234 ccode.append("%s = null_to_empty(%s);" % (name, call))
|
|
235 cparamsout.append(("STRING", name))
|
11175
|
236 addouttype("s", name)
|
11187
|
237 if not const:
|
|
238 ccodeout.append("g_free(%s);" % name)
|
11146
|
239 return
|
|
240
|
|
241 # simple types (ints, booleans, enums, ...)
|
11171
|
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))
|
11175
|
247 addouttype("i", name)
|
11146
|
248 return
|
|
249
|
|
250 # pointers ...
|
|
251 if (len(mytype) == 2) and (mytype[1] == pointer):
|
|
252
|
|
253 # handles
|
11171
|
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))
|
11175
|
258 addouttype("i", name)
|
11146
|
259 return
|
|
260
|
|
261 # GList*, GSList*, assume that list is a list of objects
|
11187
|
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
|
11146
|
269 if mytype[0] in ["GList", "GSList"]:
|
11171
|
270 cdecls.append("dbus_int32_t %s_LEN;" % name)
|
11187
|
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" \
|
11171
|
278 % (name, name))
|
11187
|
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)
|
11146
|
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 = []
|
11187
|
306 unnamed = 0
|
11146
|
307 for param in paramlist:
|
|
308 tokens = param.split()
|
11187
|
309 if len(tokens) == 0:
|
11146
|
310 raise myexception
|
11187
|
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]
|
11146
|
316 inputvar(type, name)
|
|
317 names.append(name)
|
|
318
|
|
319 outputvar(functiontype, "RESULT",
|
11187
|
320 "%s(%s)" % (origfunction, ", ".join(names)), function)
|
11146
|
321
|
11171
|
322 c_print(function)
|
|
323
|
|
324
|
11146
|
325
|
11171
|
326
|
|
327 print "/* Generated by %s. Do not edit! */" % sys.argv[0]
|
|
328
|
11146
|
329
|
|
330
|
11171
|
331 regexp = r"^(\w[^()]*)\(([^()]*)\)\s*;\s*$";
|
|
332
|
11146
|
333
|
11171
|
334 if "export-only" in options:
|
|
335 fprefix = "DBUS_EXPORT\s+"
|
|
336 else:
|
|
337 fprefix = ""
|
|
338
|
|
339 functionregexp = re.compile("^%s(\w[^()]*)\(([^()]*)\)\s*;\s*$" % fprefix)
|
11146
|
340
|
|
341 inputiter = iter(sys.stdin)
|
|
342
|
|
343 for line in inputiter:
|
|
344 words = line.split()
|
|
345 if len(words) == 0: # empty line
|
|
346 continue
|
|
347 if line[0] == "#": # preprocessor directive
|
|
348 continue
|
|
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
|
11171
|
384 printdispatchtable()
|
11146
|
385
|