Mercurial > pidgin
view src/dbus-analyze-functions.py @ 11212:46086fcc82b7
[gaim-migrate @ 13343]
Weird things happen when account is NULL in screenname_completion_match_selected_cb(). I fixed that. Then I fixed the bug I introduced that caused account to be NULL all the time.
committer: Tailor Script <tailor@pidgin.im>
author | Richard Laager <rlaager@wiktel.com> |
---|---|
date | Mon, 08 Aug 2005 19:56:41 +0000 |
parents | 744c0708d11f |
children | 66f872f30e40 |
line wrap: on
line source
# This programs takes a C header file as the input and produces: # # with option --mode=xml: xml dbus specification # with option --mode=c: C wrappers # import re import string import sys options = {} for arg in sys.argv[1:]: if arg[0:2] == "--": mylist = arg[2:].split("=",1) command = mylist[0] if len(mylist) > 1: options[command] = mylist[1] else: options[command] = None # list of object types # objecttypes = [] # for objecttype in file("dbus-auto-structs.txt"): # objecttypes.append(objecttype.strip()) # a dictionary of simple types # each TYPE maps into a pair (dbus-type-name, compatible-c-type-name) # if compatible-c-type-name is None then it is the same as TYPE # simpletypes = { # "int" : ("i", None), # "gint" : ("i", None), # "guint" : ("u", None), # "gboolean" : ("i", "int") # } simpletypes = ["int", "gint", "guint", "gboolean"] # for enum in file("dbus-auto-enums.txt"): # simpletypes[enum.strip()] = ("i", "int") # functions that shouldn't be exported excluded = ["gaim_accounts_load", "gaim_account_set_presence", "gaim_conv_placement_get_fnc_id", "gaim_conv_placement_add_fnc", "gaim_presence_add_list"] stringlists = [] pointer = "#pointer#" functions = [] dparams = "" cparams = [] cparamsout = [] cdecls = [] ccode = [] ccodeout = [] myexception = "My Exception" def ctopascal(name): newname = "" for word in name.split("_"): newname += word.capitalize() return newname def c_print(function): print "static DBusMessage *%s_DBUS(DBusMessage *message_DBUS, DBusError *error_DBUS) {" \ % function print "DBusMessage *reply_DBUS;" for decl in cdecls: print decl print "%s(message_DBUS, error_DBUS, " % argfunc, for param in cparams: print "DBUS_TYPE_%s, &%s," % param, print "DBUS_TYPE_INVALID);" print "CHECK_ERROR(error_DBUS);" for code in ccode: print code print "reply_DBUS = dbus_message_new_method_return (message_DBUS);" print "dbus_message_append_args(reply_DBUS, ", for param in cparamsout: if type(param) is str: print "%s, " % param else: print "DBUS_TYPE_%s, &%s, " % param, print "DBUS_TYPE_INVALID);" for code in ccodeout: print code print "return reply_DBUS;\n}\n" functions.append((function, dparams)) def c_clear(): global cparams, cdecls, ccode, cparamsout, ccodeout, dparams, argfunc dparams = "" cparams = [] cdecls = [] ccode = [] cparamsout = [] ccodeout = [] argfunc = "dbus_message_get_args" def addstring(*items): global dparams for item in items: dparams += item + r"\0" def addintype(type, name): addstring("in", type, name) def addouttype(type, name): addstring("out", type, name) def printdispatchtable(): print "static GaimDBusBinding bindings_DBUS[] = { " for function, params in functions: print '{"%s", "%s", %s_DBUS},' % (ctopascal(function), params, function) print "{NULL, NULL}" print "};" print "#define GAIM_DBUS_REGISTER_BINDINGS(handle) gaim_dbus_register_bindings(handle, bindings_DBUS)" # processing an input parameter def inputvar(mytype, name): global ccode, cparams, cdecls, ccodeout, argfunc const = False if mytype[0] == "const": mytype = mytype[1:] const = True if len(mytype) == 1: # simple types (int, gboolean, etc.) and enums if (mytype[0] in simpletypes) or (mytype[0].startswith("Gaim")): cdecls.append("dbus_int32_t %s;" % name) cparams.append(("INT32", name)) addintype("i", name) return # va_list, replace by NULL if mytype[0] == "va_list": cdecls.append("va_list %s;" % name); ccode.append("%s = NULL;" % name); return # pointers ... if (len(mytype) == 2) and (mytype[1] == pointer): # strings if mytype[0] == "char": if const: cdecls.append("const char *%s;" % name) cparams.append(("STRING", name)) ccode .append("NULLIFY(%s);" % name) addintype("s", name) return else: raise myexception # memory leak if an error occurs later ... elif mytype[0] == "GHashTable": argfunc = "gaim_dbus_message_get_args" cdecls.append("DBusMessageIter %s_ITER;" % name) cdecls.append("GHashTable *%s;" % name) cparams.append(("ARRAY", "%s_ITER" % name)) ccode.append("%s = gaim_dbus_iter_hash_table(&%s_ITER, error_DBUS);" \ % (name, name)) ccode.append("CHECK_ERROR(error_DBUS);") ccodeout.append("g_hash_table_destroy(%s);" % name) addintype("a{ss}", name) return # known object types are transformed to integer handles elif mytype[0].startswith("Gaim"): cdecls.append("dbus_int32_t %s_ID;" % name) cdecls.append("%s *%s;" % (mytype[0], name)) cparams.append(("INT32", name + "_ID")) ccode.append("GAIM_DBUS_ID_TO_POINTER(%s, %s_ID, %s, error_DBUS);" % \ (name, name, mytype[0])) addintype("i", name) return # unknown pointers are always replaced with NULL else: cdecls.append("dbus_int32_t %s_NULL;" % name) cdecls .append("%s *%s;" % (mytype[0], name)) cparams.append(("INT32", name + "_NULL")) ccode .append("%s = NULL;" % name) addintype("i", name) return raise myexception # processing an output parameter def outputvar(mytype, name, call, function): # the "void" type is simple ... if mytype == ["void"]: ccode.append("%s;" % call) # just call the function return const = False if mytype[0] == "const": mytype = mytype[1:] const = True # a string if mytype == ["char", pointer]: cdecls.append("const char *%s;" % name) ccode.append("%s = null_to_empty(%s);" % (name, call)) cparamsout.append(("STRING", name)) addouttype("s", name) if not const: ccodeout.append("g_free(%s);" % name) return # simple types (ints, booleans, enums, ...) if (len(mytype) == 1) and \ ((mytype[0] in simpletypes) or (mytype[0].startswith("Gaim"))): cdecls.append("dbus_int32_t %s;" % name) ccode.append("%s = %s;" % (name, call)) cparamsout.append(("INT32", name)) addouttype("i", name) return # pointers ... if (len(mytype) == 2) and (mytype[1] == pointer): # handles if mytype[0].startswith("Gaim"): cdecls.append("dbus_int32_t %s;" % name) ccode .append("GAIM_DBUS_POINTER_TO_ID(%s, %s, error_DBUS);" % (name, call)) cparamsout.append(("INT32", name)) addouttype("i", name) return # GList*, GSList*, assume that list is a list of objects # fixme: at the moment, we do NOT free the memory occupied by # the list, we should free it if the list has NOT been declared const # fixme: we assume that this is a list of objects, not a list # of strings if mytype[0] in ["GList", "GSList"]: cdecls.append("dbus_int32_t %s_LEN;" % name) ccodeout.append("g_free(%s);" % name) if function in stringlists: cdecls.append("char **%s;" % name) ccode.append("%s = gaim_%s_to_array(%s, FALSE, &%s_LEN);" % \ (name, mytype[0], call, name)) cparamsout.append("DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &%s, %s_LEN" \ % (name, name)) addouttype("as", name) else: cdecls.append("dbus_int32_t *%s;" % name) ccode.append("%s = gaim_dbusify_%s(%s, FALSE, &%s_LEN);" % \ (name, mytype[0], call, name)) cparamsout.append("DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, &%s, %s_LEN" \ % (name, name)) addouttype("ai", name) return raise myexception def processfunction(functionparam, paramlist): c_clear() ftokens = functionparam.split() functiontype, function = ftokens[:-1], ftokens[-1] if function in excluded: return origfunction = function function = function.lower() names = [] unnamed = 0 for param in paramlist: tokens = param.split() if len(tokens) == 0: raise myexception if (len(tokens) == 1) or (tokens[-1] == pointer): unnamed += 1 type, name = tokens, "param%i" % unnamed else: type, name = tokens[:-1], tokens[-1] inputvar(type, name) names.append(name) outputvar(functiontype, "RESULT", "%s(%s)" % (origfunction, ", ".join(names)), function) c_print(function) print "/* Generated by %s. Do not edit! */" % sys.argv[0] regexp = r"^(\w[^()]*)\(([^()]*)\)\s*;\s*$"; if "export-only" in options: fprefix = "DBUS_EXPORT\s+" else: fprefix = "" functionregexp = re.compile("^%s(\w[^()]*)\(([^()]*)\)\s*;\s*$" % fprefix) inputiter = iter(sys.stdin) for line in inputiter: words = line.split() if len(words) == 0: # empty line continue if line[0] == "#": # preprocessor directive continue if words[0] in ["typedef", "struct", "enum", "static"]: continue # accumulate lines until the parentheses are balance or an # empty line has been encountered myline = line.strip() while myline.count("(") > myline.count(")"): newline = inputiter.next().strip() if len(newline) == 0: break myline += " " + newline # is this a function declaration? thematch = functionregexp.match( myline.replace("*", " " + pointer + " ")) if thematch is None: continue function = thematch.group(1) parameters = thematch.group(2).strip() if (parameters == "void") or (parameters == ""): paramlist = [] else: paramlist = parameters.split(",") try: processfunction(function, paramlist) except myexception: sys.stderr.write(myline + "\n") except: sys.stderr.write(myline + "\n") raise printdispatchtable()