Mercurial > pidgin.yaz
comparison src/dbus-analyze-functions.py @ 11171:ebb02ea3c789
[gaim-migrate @ 13272]
Moved DBUS init call from gtkmain.c to core.c
Reimplemented DBUS bindings mechamism to use low-level GLib bindings
as described in my last blog entry. This way plugins can add new DBUS
methods on the fly. Also wrote an example plugin that demonstrate how
to do it.
committer: Tailor Script <tailor@pidgin.im>
author | Piotr Zielinski <zielaj> |
---|---|
date | Sat, 30 Jul 2005 00:23:21 +0000 |
parents | 1c5398ccbeb0 |
children | 57af14280b5f |
comparison
equal
deleted
inserted
replaced
11170:0e9e2b923d09 | 11171:ebb02ea3c789 |
---|---|
8 | 8 |
9 import re | 9 import re |
10 import string | 10 import string |
11 import sys | 11 import sys |
12 | 12 |
13 # mode: "c" or "xml" | 13 options = {} |
14 | |
15 mode = None | |
16 | 14 |
17 for arg in sys.argv[1:]: | 15 for arg in sys.argv[1:]: |
18 if arg.startswith("--mode="): | 16 if arg[0:2] == "--": |
19 mode = arg[len("--mode="):] | 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 | |
20 | 23 |
21 # list of object types | 24 # list of object types |
22 | 25 |
23 objecttypes = [] | 26 # objecttypes = [] |
24 | 27 |
25 for objecttype in file("dbus-auto-structs.txt"): | 28 # for objecttype in file("dbus-auto-structs.txt"): |
26 objecttypes.append(objecttype.strip()) | 29 # objecttypes.append(objecttype.strip()) |
27 | 30 |
28 # a dictionary of simple types | 31 # a dictionary of simple types |
29 # each TYPE maps into a pair (dbus-type-name, compatible-c-type-name) | 32 # each TYPE maps into a pair (dbus-type-name, compatible-c-type-name) |
30 # if compatible-c-type-name is None then it is the same as TYPE | 33 # if compatible-c-type-name is None then it is the same as TYPE |
31 | 34 |
32 simpletypes = { | 35 # simpletypes = { |
33 "int" : ("i", None), | 36 # "int" : ("i", None), |
34 "gint" : ("i", None), | 37 # "gint" : ("i", None), |
35 "guint" : ("u", None), | 38 # "guint" : ("u", None), |
36 "gboolean" : ("i", "int") | 39 # "gboolean" : ("i", "int") |
37 } | 40 # } |
38 | 41 |
39 for enum in file("dbus-auto-enums.txt"): | 42 simpletypes = ["int", "gint", "guint", "gboolean"] |
40 simpletypes[enum.strip()] = ("i", "int") | 43 |
44 # for enum in file("dbus-auto-enums.txt"): | |
45 # simpletypes[enum.strip()] = ("i", "int") | |
41 | 46 |
42 # functions that shouldn't be exported | 47 # functions that shouldn't be exported |
43 | 48 |
44 excluded = ["gaim_accounts_load", "gaim_account_set_presence"] | 49 excluded = ["gaim_accounts_load", "gaim_account_set_presence", |
50 "gaim_conv_placement_get_fnc_id", "gaim_conv_placement_add_fnc"] | |
45 | 51 |
46 pointer = "#pointer#" | 52 pointer = "#pointer#" |
47 prefix = "gaim_object_" | 53 |
54 functions = [] | |
48 | 55 |
49 cparams = [] | 56 cparams = [] |
57 cparamsout = [] | |
50 cdecls = [] | 58 cdecls = [] |
51 ccode = [] | 59 ccode = [] |
52 dargs = [] | 60 ccodeout = [] |
53 | 61 |
54 myexception = "My Exception" | 62 myexception = "My Exception" |
55 | |
56 | 63 |
57 def ctopascal(name): | 64 def ctopascal(name): |
58 newname = "" | 65 newname = "" |
59 for word in name.split("_"): | 66 for word in name.split("_"): |
60 newname += word.capitalize() | 67 newname += word.capitalize() |
61 return newname | 68 return newname |
62 | 69 |
63 def dbus_print(function): | |
64 print '<method name="%s">' % ctopascal(function) | |
65 | |
66 for name, type, direction in dargs: | |
67 print '<arg type="%s" name="%s" direction="%s" />' % \ | |
68 (type, name, direction) | |
69 | |
70 print '</method>' | |
71 print | |
72 | |
73 def dbus_clear(): | |
74 global dargs | |
75 dargs = [] | |
76 | |
77 def c_print(function): | 70 def c_print(function): |
78 print "static gboolean %s%s(GaimObject *gaim_object," % (prefix, function), | 71 print "static DBusMessage *%s_DBUS(DBusMessage *message_DBUS, DBusError *error_DBUS) {" \ |
79 | 72 % function |
80 for param in cparams: | 73 |
81 print "%s," % param, | 74 print "DBusMessage *reply_DBUS;" |
82 | |
83 print "GError **error) {" | |
84 | 75 |
85 for decl in cdecls: | 76 for decl in cdecls: |
86 print decl | 77 print decl |
87 | 78 |
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 | |
88 for code in ccode: | 86 for code in ccode: |
89 print code | 87 print code |
90 | 88 |
91 print "return TRUE;\n}\n" | 89 print "reply_DBUS = dbus_message_new_method_return (message_DBUS);" |
92 | 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 | |
93 def c_clear(): | 106 def c_clear(): |
94 global cparams, cdecls, ccode | 107 global cparams, cdecls, ccode, cparamsout, ccodeout |
95 cparams = [] | 108 cparams = [] |
96 cdecls = [] | 109 cdecls = [] |
97 ccode = [] | 110 ccode = [] |
98 | 111 cparamsout = [] |
112 ccodeout = [] | |
113 | |
114 | |
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)" | |
99 | 123 |
100 # processing an input parameter | 124 # processing an input parameter |
101 | 125 |
102 def inputvar(mytype, name): | 126 def inputvar(mytype, name): |
103 global dargs, ccode, cparams, cdecls | 127 global ccode, cparams, cdecls |
104 const = False | 128 const = False |
105 if mytype[0] == "const": | 129 if mytype[0] == "const": |
106 mytype = mytype[1:] | 130 mytype = mytype[1:] |
107 const = True | 131 const = True |
108 | 132 |
109 # simple types (int, gboolean, etc.) and enums | 133 # simple types (int, gboolean, etc.) and enums |
110 if (len(mytype) == 1) and (mytype[0] in simpletypes): | 134 if (len(mytype) == 1) and \ |
111 dbustype, ctype = simpletypes[mytype[0]] | 135 ((mytype[0] in simpletypes) or (mytype[0].startswith("Gaim"))): |
112 dargs.append((name, dbustype, "in")) | 136 cdecls.append("dbus_int32_t %s;" % name) |
113 if ctype is None: | 137 cparams.append(("INT32", name)) |
114 cparams.append(mytype[0] + " " + name) | |
115 else: | |
116 cparams.append(ctype + " " + name + "_ORIG") | |
117 cdecls .append("%s %s;\n" % (mytype[0], name)) | |
118 ccode .append("%s = (%s) %s_ORIG;\n" % \ | |
119 (name, mytype[0], name)) | |
120 return | 138 return |
121 | 139 |
122 # pointers ... | 140 # pointers ... |
123 | 141 |
124 if (len(mytype) == 2) and (mytype[1] == pointer): | 142 if (len(mytype) == 2) and (mytype[1] == pointer): |
125 # strings | 143 # strings |
126 if mytype[0] == "char": | 144 if mytype[0] == "char": |
127 if const: | 145 if const: |
128 dargs .append((name, "s", "in")) | 146 cdecls.append("const char *%s;" % name) |
129 cparams.append("const char *" + name) | 147 cparams.append(("STRING", name)) |
130 ccode .append("NULLIFY(%s);" % name) | 148 ccode .append("NULLIFY(%s);" % name) |
131 return | 149 return |
132 else: | 150 else: |
133 raise myexception | 151 raise myexception |
134 | 152 |
135 # known object types are transformed to integer handles | 153 # known object types are transformed to integer handles |
136 elif mytype[0] in objecttypes: | 154 elif mytype[0].startswith("Gaim"): |
137 dargs .append((name, "i", "in")) | 155 cdecls.append("dbus_int32_t %s_ID;" % name) |
138 cparams.append("int " + name + "_ID") | 156 cdecls.append("%s *%s;" % (mytype[0], name)) |
139 cdecls .append("%s *%s;" % (mytype[0], name)) | 157 cparams.append(("INT32", name + "_ID")) |
140 ccode .append("GAIM_DBUS_ID_TO_POINTER(%s, %s_ID, %s);" % \ | 158 ccode.append("GAIM_DBUS_ID_TO_POINTER(%s, %s_ID, %s, error_DBUS);" % \ |
141 (name, name, mytype[0])) | 159 (name, name, mytype[0])) |
142 return | 160 return |
143 | 161 |
144 # unknown pointers are always replaced with NULL | 162 # unknown pointers are always replaced with NULL |
145 else: | 163 else: |
146 dargs .append((name, "i", "in")) | 164 cdecls.append("dbus_int32_t %s_NULL;" % name) |
147 cparams.append("int " + name + "_NULL") | |
148 cdecls .append("%s *%s;" % (mytype[0], name)) | 165 cdecls .append("%s *%s;" % (mytype[0], name)) |
166 cparams.append(("INT32", name + "_NULL")) | |
149 ccode .append("%s = NULL;" % name) | 167 ccode .append("%s = NULL;" % name) |
150 return | 168 return |
151 | 169 |
152 raise myexception | 170 raise myexception |
153 | 171 |
161 ccode.append("%s;" % call) # just call the function | 179 ccode.append("%s;" % call) # just call the function |
162 return | 180 return |
163 | 181 |
164 # a constant string | 182 # a constant string |
165 if mytype == ["const", "char", pointer]: | 183 if mytype == ["const", "char", pointer]: |
166 dargs .append((name, "s", "out")) | 184 cdecls.append("const char *%s;" % name) |
167 cparams.append("char **%s" % name) | 185 ccode.append("%s = null_to_empty(%s);" % (name, call)) |
168 ccode .append("*%s = g_strdup(null_to_empty(%s));" % (name, call)) | 186 cparamsout.append(("STRING", name)) |
169 return | 187 return |
170 | 188 |
171 # simple types (ints, booleans, enums, ...) | 189 # simple types (ints, booleans, enums, ...) |
172 if (len(mytype) == 1) and (mytype[0] in simpletypes): | 190 if (len(mytype) == 1) and \ |
173 dbustype, ctype = simpletypes[mytype[0]] | 191 ((mytype[0] in simpletypes) or (mytype[0].startswith("Gaim"))): |
174 | 192 cdecls.append("dbus_int32_t %s;" % name) |
175 if ctype is None: | 193 ccode.append("%s = %s;" % (name, call)) |
176 ctype = mytype[0] | 194 cparamsout.append(("INT32", name)) |
177 | |
178 dargs .append((name, dbustype, "out")) | |
179 ccode .append("*%s = %s;" % (name, call)) | |
180 cparams.append("%s *%s" % (ctype, name)) | |
181 return | 195 return |
182 | 196 |
183 # pointers ... | 197 # pointers ... |
184 if (len(mytype) == 2) and (mytype[1] == pointer): | 198 if (len(mytype) == 2) and (mytype[1] == pointer): |
185 | 199 |
186 # handles | 200 # handles |
187 if mytype[0] in objecttypes: | 201 if mytype[0].startswith("Gaim"): |
188 dargs .append((name, "i", "out")) | 202 cdecls.append("dbus_int32_t %s;" % name) |
189 cparams.append("int *%s" % name) | 203 ccode .append("GAIM_DBUS_POINTER_TO_ID(%s, %s, error_DBUS);" % (name, call)) |
190 ccode .append("GAIM_DBUS_POINTER_TO_ID(*%s, %s);" % (name, call)) | 204 cparamsout.append(("INT32", name)) |
191 return | 205 return |
192 | 206 |
193 # GList*, GSList*, assume that list is a list of objects | 207 # GList*, GSList*, assume that list is a list of objects |
194 # not a list of strings!!! | 208 # not a list of strings!!! |
209 # this does NOT release memory occupied by the list | |
195 if mytype[0] in ["GList", "GSList"]: | 210 if mytype[0] in ["GList", "GSList"]: |
196 dargs .append((name, "ai", "out")) | 211 cdecls.append("dbus_int32_t %s_LEN;" % name) |
197 cparams.append("GArray **%s" % name) | 212 cdecls.append("dbus_int32_t *%s;" % name) |
198 ccode .append("*%s = gaim_dbusify_%s(%s, TRUE);" % \ | 213 ccode.append("%s = gaim_dbusify_%s(%s, FALSE, &%s_LEN);" % \ |
199 (name, mytype[0],call)) | 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) | |
200 return | 218 return |
201 | 219 |
202 raise myexception | 220 raise myexception |
203 | 221 |
204 | 222 |
205 | 223 |
206 def processfunction(functionparam, paramlist): | 224 def processfunction(functionparam, paramlist): |
207 dbus_clear() | |
208 c_clear() | 225 c_clear() |
209 | 226 |
210 ftokens = functionparam.split() | 227 ftokens = functionparam.split() |
211 functiontype, function = ftokens[:-1], ftokens[-1] | 228 functiontype, function = ftokens[:-1], ftokens[-1] |
212 | 229 |
226 names.append(name) | 243 names.append(name) |
227 | 244 |
228 outputvar(functiontype, "RESULT", | 245 outputvar(functiontype, "RESULT", |
229 "%s(%s)" % (origfunction, ", ".join(names))) | 246 "%s(%s)" % (origfunction, ", ".join(names))) |
230 | 247 |
231 if mode == "c": | 248 c_print(function) |
232 c_print(function) | 249 |
233 | 250 |
234 if mode == "xml": | 251 |
235 dbus_print(function) | 252 |
236 | 253 print "/* Generated by %s. Do not edit! */" % sys.argv[0] |
237 | 254 |
238 if mode == "c": | 255 |
239 print "/* Generated by %s. Do not edit! */" % sys.argv[0] | 256 |
240 | 257 regexp = r"^(\w[^()]*)\(([^()]*)\)\s*;\s*$"; |
241 if mode == "xml": | 258 |
242 print "<!-- Generated by %s. Do not edit! -->" % sys.argv[0] | 259 |
243 | 260 if "export-only" in options: |
244 functionregexp = re.compile(r"^(\w[^()]*)\(([^()]*)\)\s*;\s*$") | 261 fprefix = "DBUS_EXPORT\s+" |
262 else: | |
263 fprefix = "" | |
264 | |
265 functionregexp = re.compile("^%s(\w[^()]*)\(([^()]*)\)\s*;\s*$" % fprefix) | |
245 | 266 |
246 inputiter = iter(sys.stdin) | 267 inputiter = iter(sys.stdin) |
247 | 268 |
248 for line in inputiter: | 269 for line in inputiter: |
249 words = line.split() | 270 words = line.split() |
284 sys.stderr.write(myline + "\n") | 305 sys.stderr.write(myline + "\n") |
285 except: | 306 except: |
286 sys.stderr.write(myline + "\n") | 307 sys.stderr.write(myline + "\n") |
287 raise | 308 raise |
288 | 309 |
289 | 310 printdispatchtable() |
290 | 311 |
291 | |
292 |