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
|
11171
|
42 simpletypes = ["int", "gint", "guint", "gboolean"]
|
|
43
|
|
44 # for enum in file("dbus-auto-enums.txt"):
|
|
45 # simpletypes[enum.strip()] = ("i", "int")
|
11146
|
46
|
|
47 # functions that shouldn't be exported
|
|
48
|
11171
|
49 excluded = ["gaim_accounts_load", "gaim_account_set_presence",
|
|
50 "gaim_conv_placement_get_fnc_id", "gaim_conv_placement_add_fnc"]
|
11146
|
51
|
|
52 pointer = "#pointer#"
|
11171
|
53
|
|
54 functions = []
|
11146
|
55
|
|
56 cparams = []
|
11171
|
57 cparamsout = []
|
11146
|
58 cdecls = []
|
|
59 ccode = []
|
11171
|
60 ccodeout = []
|
11146
|
61
|
|
62 myexception = "My Exception"
|
|
63
|
|
64 def ctopascal(name):
|
|
65 newname = ""
|
|
66 for word in name.split("_"):
|
|
67 newname += word.capitalize()
|
|
68 return newname
|
|
69
|
11171
|
70 def c_print(function):
|
|
71 print "static DBusMessage *%s_DBUS(DBusMessage *message_DBUS, DBusError *error_DBUS) {" \
|
|
72 % function
|
11146
|
73
|
11171
|
74 print "DBusMessage *reply_DBUS;"
|
11146
|
75
|
|
76 for decl in cdecls:
|
|
77 print decl
|
|
78
|
11171
|
79 print "dbus_message_get_args(message_DBUS, error_DBUS, ",
|
|
80 for param in cparams:
|
|
81 print "DBUS_TYPE_%s, &%s," % param,
|
|
82 print "DBUS_TYPE_INVALID);"
|
|
83
|
|
84 print "CHECK_ERROR(error_DBUS);"
|
|
85
|
11146
|
86 for code in ccode:
|
|
87 print code
|
|
88
|
11171
|
89 print "reply_DBUS = dbus_message_new_method_return (message_DBUS);"
|
|
90
|
|
91 print "dbus_message_append_args(reply_DBUS, ",
|
|
92 for param in cparamsout:
|
|
93 if type(param) is str:
|
|
94 print "%s, " % param
|
|
95 else:
|
|
96 print "DBUS_TYPE_%s, &%s, " % param,
|
|
97 print "DBUS_TYPE_INVALID);"
|
|
98
|
|
99 for code in ccodeout:
|
|
100 print code
|
|
101
|
|
102 print "return reply_DBUS;\n}\n"
|
|
103
|
|
104 functions.append(function)
|
|
105
|
11146
|
106 def c_clear():
|
11171
|
107 global cparams, cdecls, ccode, cparamsout, ccodeout
|
11146
|
108 cparams = []
|
|
109 cdecls = []
|
|
110 ccode = []
|
11171
|
111 cparamsout = []
|
|
112 ccodeout = []
|
11146
|
113
|
|
114
|
11171
|
115 def printdispatchtable():
|
|
116 print "static GaimDBusBinding bindings_DBUS[] = { "
|
|
117 for function in functions:
|
|
118 print '{"%s", %s_DBUS},' % (ctopascal(function), function)
|
|
119 print "{NULL, NULL}"
|
|
120 print "};"
|
|
121
|
|
122 print "#define GAIM_DBUS_REGISTER_BINDINGS(handle) gaim_dbus_register_bindings(handle, bindings_DBUS)"
|
|
123
|
11146
|
124 # processing an input parameter
|
|
125
|
|
126 def inputvar(mytype, name):
|
11171
|
127 global ccode, cparams, cdecls
|
11146
|
128 const = False
|
|
129 if mytype[0] == "const":
|
|
130 mytype = mytype[1:]
|
|
131 const = True
|
|
132
|
|
133 # simple types (int, gboolean, etc.) and enums
|
11171
|
134 if (len(mytype) == 1) and \
|
|
135 ((mytype[0] in simpletypes) or (mytype[0].startswith("Gaim"))):
|
|
136 cdecls.append("dbus_int32_t %s;" % name)
|
|
137 cparams.append(("INT32", name))
|
11146
|
138 return
|
|
139
|
|
140 # pointers ...
|
|
141
|
|
142 if (len(mytype) == 2) and (mytype[1] == pointer):
|
|
143 # strings
|
|
144 if mytype[0] == "char":
|
|
145 if const:
|
11171
|
146 cdecls.append("const char *%s;" % name)
|
|
147 cparams.append(("STRING", name))
|
11146
|
148 ccode .append("NULLIFY(%s);" % name)
|
|
149 return
|
|
150 else:
|
|
151 raise myexception
|
|
152
|
|
153 # known object types are transformed to integer handles
|
11171
|
154 elif mytype[0].startswith("Gaim"):
|
|
155 cdecls.append("dbus_int32_t %s_ID;" % name)
|
|
156 cdecls.append("%s *%s;" % (mytype[0], name))
|
|
157 cparams.append(("INT32", name + "_ID"))
|
|
158 ccode.append("GAIM_DBUS_ID_TO_POINTER(%s, %s_ID, %s, error_DBUS);" % \
|
11146
|
159 (name, name, mytype[0]))
|
|
160 return
|
|
161
|
|
162 # unknown pointers are always replaced with NULL
|
|
163 else:
|
11171
|
164 cdecls.append("dbus_int32_t %s_NULL;" % name)
|
11146
|
165 cdecls .append("%s *%s;" % (mytype[0], name))
|
11171
|
166 cparams.append(("INT32", name + "_NULL"))
|
11146
|
167 ccode .append("%s = NULL;" % name)
|
|
168 return
|
|
169
|
|
170 raise myexception
|
|
171
|
|
172
|
|
173
|
|
174 # processing an output parameter
|
|
175
|
|
176 def outputvar(mytype, name, call):
|
|
177 # the "void" type is simple ...
|
|
178 if mytype == ["void"]:
|
|
179 ccode.append("%s;" % call) # just call the function
|
|
180 return
|
|
181
|
|
182 # a constant string
|
|
183 if mytype == ["const", "char", pointer]:
|
11171
|
184 cdecls.append("const char *%s;" % name)
|
|
185 ccode.append("%s = null_to_empty(%s);" % (name, call))
|
|
186 cparamsout.append(("STRING", name))
|
11146
|
187 return
|
|
188
|
|
189 # simple types (ints, booleans, enums, ...)
|
11171
|
190 if (len(mytype) == 1) and \
|
|
191 ((mytype[0] in simpletypes) or (mytype[0].startswith("Gaim"))):
|
|
192 cdecls.append("dbus_int32_t %s;" % name)
|
|
193 ccode.append("%s = %s;" % (name, call))
|
|
194 cparamsout.append(("INT32", name))
|
11146
|
195 return
|
|
196
|
|
197 # pointers ...
|
|
198 if (len(mytype) == 2) and (mytype[1] == pointer):
|
|
199
|
|
200 # handles
|
11171
|
201 if mytype[0].startswith("Gaim"):
|
|
202 cdecls.append("dbus_int32_t %s;" % name)
|
|
203 ccode .append("GAIM_DBUS_POINTER_TO_ID(%s, %s, error_DBUS);" % (name, call))
|
|
204 cparamsout.append(("INT32", name))
|
11146
|
205 return
|
|
206
|
|
207 # GList*, GSList*, assume that list is a list of objects
|
|
208 # not a list of strings!!!
|
11171
|
209 # this does NOT release memory occupied by the list
|
11146
|
210 if mytype[0] in ["GList", "GSList"]:
|
11171
|
211 cdecls.append("dbus_int32_t %s_LEN;" % name)
|
|
212 cdecls.append("dbus_int32_t *%s;" % name)
|
|
213 ccode.append("%s = gaim_dbusify_%s(%s, FALSE, &%s_LEN);" % \
|
|
214 (name, mytype[0], call, name))
|
|
215 cparamsout.append("DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, &%s, %s_LEN" \
|
|
216 % (name, name))
|
|
217 ccodeout.append("g_free(%s);" % name)
|
11146
|
218 return
|
|
219
|
|
220 raise myexception
|
|
221
|
|
222
|
|
223
|
|
224 def processfunction(functionparam, paramlist):
|
|
225 c_clear()
|
|
226
|
|
227 ftokens = functionparam.split()
|
|
228 functiontype, function = ftokens[:-1], ftokens[-1]
|
|
229
|
|
230 if function in excluded:
|
|
231 return
|
|
232
|
|
233 origfunction = function
|
|
234 function = function.lower()
|
|
235
|
|
236 names = []
|
|
237 for param in paramlist:
|
|
238 tokens = param.split()
|
|
239 if len(tokens) < 2:
|
|
240 raise myexception
|
|
241 type, name = tokens[:-1], tokens[-1]
|
|
242 inputvar(type, name)
|
|
243 names.append(name)
|
|
244
|
|
245 outputvar(functiontype, "RESULT",
|
|
246 "%s(%s)" % (origfunction, ", ".join(names)))
|
|
247
|
11171
|
248 c_print(function)
|
|
249
|
|
250
|
11146
|
251
|
11171
|
252
|
|
253 print "/* Generated by %s. Do not edit! */" % sys.argv[0]
|
|
254
|
11146
|
255
|
|
256
|
11171
|
257 regexp = r"^(\w[^()]*)\(([^()]*)\)\s*;\s*$";
|
|
258
|
11146
|
259
|
11171
|
260 if "export-only" in options:
|
|
261 fprefix = "DBUS_EXPORT\s+"
|
|
262 else:
|
|
263 fprefix = ""
|
|
264
|
|
265 functionregexp = re.compile("^%s(\w[^()]*)\(([^()]*)\)\s*;\s*$" % fprefix)
|
11146
|
266
|
|
267 inputiter = iter(sys.stdin)
|
|
268
|
|
269 for line in inputiter:
|
|
270 words = line.split()
|
|
271 if len(words) == 0: # empty line
|
|
272 continue
|
|
273 if line[0] == "#": # preprocessor directive
|
|
274 continue
|
|
275 if words[0] in ["typedef", "struct", "enum", "static"]:
|
|
276 continue
|
|
277
|
|
278 # accumulate lines until the parentheses are balance or an
|
|
279 # empty line has been encountered
|
|
280 myline = line.strip()
|
|
281 while myline.count("(") > myline.count(")"):
|
|
282 newline = inputiter.next().strip()
|
|
283 if len(newline) == 0:
|
|
284 break
|
|
285 myline += " " + newline
|
|
286
|
|
287 # is this a function declaration?
|
|
288 thematch = functionregexp.match(
|
|
289 myline.replace("*", " " + pointer + " "))
|
|
290
|
|
291 if thematch is None:
|
|
292 continue
|
|
293
|
|
294 function = thematch.group(1)
|
|
295 parameters = thematch.group(2).strip()
|
|
296
|
|
297 if (parameters == "void") or (parameters == ""):
|
|
298 paramlist = []
|
|
299 else:
|
|
300 paramlist = parameters.split(",")
|
|
301
|
|
302 try:
|
|
303 processfunction(function, paramlist)
|
|
304 except myexception:
|
|
305 sys.stderr.write(myline + "\n")
|
|
306 except:
|
|
307 sys.stderr.write(myline + "\n")
|
|
308 raise
|
|
309
|
11171
|
310 printdispatchtable()
|
11146
|
311
|