summaryrefslogtreecommitdiffstats
path: root/src/libs/xpcom18a4/python/xpt.py
diff options
context:
space:
mode:
Diffstat (limited to '')
-rwxr-xr-xsrc/libs/xpcom18a4/python/xpt.py471
1 files changed, 471 insertions, 0 deletions
diff --git a/src/libs/xpcom18a4/python/xpt.py b/src/libs/xpcom18a4/python/xpt.py
new file mode 100755
index 00000000..67021572
--- /dev/null
+++ b/src/libs/xpcom18a4/python/xpt.py
@@ -0,0 +1,471 @@
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is the Python XPCOM language bindings.
+#
+# The Initial Developer of the Original Code is
+# ActiveState Tool Corp.
+# Portions created by the Initial Developer are Copyright (C) 2000, 2001
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# David Ascher <DavidA@ActiveState.com> (original author)
+# Mark Hammond <mhammond@skippinet.com.au>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+"""
+Program: xpt.py
+
+Task: describe interfaces etc using XPCOM reflection.
+
+Subtasks:
+ output (nearly) exactly the same stuff as xpt_dump, for verification
+ output Python source code that can be used as a template for an interface
+
+Status: Works pretty well if you ask me :-)
+
+Author:
+ David Ascher did an original version that parsed XPT files
+ directly. Mark Hammond changed it to use the reflection interfaces,
+ but kept most of the printing logic.
+
+
+Revision:
+
+ 0.1: March 6, 2000
+ 0.2: April 2000 - Mark removed lots of Davids lovely parsing code in favour
+ of the new xpcom interfaces that provide this info.
+
+ May 2000 - Moved into Perforce - track the log there!
+ Early 2001 - Moved into the Mozilla CVS tree - track the log there!
+
+Todo:
+ Fill out this todo list.
+
+"""
+
+import string, sys
+import xpcom
+import xpcom._xpcom
+
+from .xpcom_consts import *
+
+class Interface:
+ def __init__(self, iid):
+ iim = xpcom._xpcom.XPTI_GetInterfaceInfoManager()
+ if hasattr(iid, "upper"): # Is it a stringy thing.
+ item = iim.GetInfoForName(iid)
+ else:
+ item = iim.GetInfoForIID(iid)
+ self.interface_info = item
+ self.namespace = "" # where does this come from?
+ self.methods = Methods(item)
+ self.constants = Constants(item)
+
+ # delegate attributes to the real interface
+ def __getattr__(self, attr):
+ return getattr(self.interface_info, attr)
+
+ def GetParent(self):
+ try:
+ raw_parent = self.interface_info.GetParent()
+ if raw_parent is None:
+ return None
+ return Interface(raw_parent.GetIID())
+ except xpcom.Exception:
+ # Parent interface is probably not scriptable - assume nsISupports.
+ if xpcom.verbose:
+ # The user may be confused as to why this is happening!
+ print("The parent interface of IID '%s' can not be located - assuming nsISupports")
+ return Interface(xpcom._xpcom.IID_nsISupports)
+
+ def Describe_Python(self):
+ method_reprs = []
+ methods = [m for m in self.methods if not m.IsNotXPCOM()]
+ for m in methods:
+ method_reprs.append(m.Describe_Python())
+ method_joiner = "\n"
+ methods_repr = method_joiner.join(method_reprs)
+ return \
+"""class %s:
+ _com_interfaces_ = xpcom.components.interfaces.%s
+ # If this object needs to be registered, the following 2 are also needed.
+ # _reg_clsid_ = "{a new clsid generated for this object}"
+ # _reg_contractid_ = "The.Object.Name"\n%s""" % (self.GetName(), self.GetIID().name, methods_repr)
+
+ def Describe(self):
+ # Make the IID look like xtp_dump - "(" instead of "{"
+ iid_use = "(" + str(self.GetIID())[1:-1] + ")"
+ s = ' - '+self.namespace+'::'+ self.GetName() + ' ' + iid_use + ':\n'
+
+ parent = self.GetParent()
+ if parent is not None:
+ s = s + ' Parent: ' + parent.namespace + '::' + parent.GetName() + '\n'
+ s = s + ' Flags:\n'
+ if self.IsScriptable(): word = 'TRUE'
+ else: word = 'FALSE'
+ s = s + ' Scriptable: ' + word + '\n'
+ s = s + ' Methods:\n'
+ methods = [m for m in self.methods if not m.IsNotXPCOM()]
+ if len(methods):
+ for m in methods:
+ s = s + ' ' + m.Describe() + '\n'
+ else:
+ s = s + ' No Methods\n'
+ s = s + ' Constants:\n'
+ if self.constants:
+ for c in self.constants:
+ s = s + ' ' + c.Describe() + '\n'
+ else:
+ s = s + ' No Constants\n'
+
+ return s
+
+# A class that allows caching and iterating of methods.
+class Methods:
+ def __init__(self, interface_info):
+ self.interface_info = interface_info
+ try:
+ self.items = [None] * interface_info.GetMethodCount()
+ except xpcom.Exception:
+ if xpcom.verbose:
+ print("** GetMethodCount failed?? - assuming no methods")
+ self.items = []
+ def __len__(self):
+ return len(self.items)
+ def __getitem__(self, index):
+ ret = self.items[index]
+ if ret is None:
+ mi = self.interface_info.GetMethodInfo(index)
+ ret = self.items[index] = Method(mi, index, self.interface_info)
+ return ret
+
+class Method:
+
+ def __init__(self, method_info, method_index, interface_info = None):
+ self.interface_info = interface_info
+ self.method_index = method_index
+ self.flags, self.name, param_descs, self.result_desc = method_info
+ # Build the params.
+ self.params = []
+ pi=0
+ for pd in param_descs:
+ self.params.append( Parameter(pd, pi, method_index, interface_info) )
+ pi = pi + 1
+ # Run over the params setting the "sizeof" params to hidden.
+ for p in self.params:
+ td = p.type_desc
+ tag = XPT_TDP_TAG(td[0])
+ if tag==T_ARRAY and p.IsIn():
+ self.params[td[1]].hidden_indicator = 2
+ elif tag in [T_PSTRING_SIZE_IS, T_PWSTRING_SIZE_IS] and p.IsIn():
+ self.params[td[1]].hidden_indicator = 1
+
+ def IsGetter(self):
+ return (self.flags & XPT_MD_GETTER)
+ def IsSetter(self):
+ return (self.flags & XPT_MD_SETTER)
+ def IsNotXPCOM(self):
+ return (self.flags & XPT_MD_NOTXPCOM)
+ def IsConstructor(self):
+ return (self.flags & XPT_MD_CTOR)
+ def IsHidden(self):
+ return (self.flags & XPT_MD_HIDDEN)
+
+ def Describe_Python(self):
+ if self.method_index < 3: # Ignore QI etc
+ return ""
+ base_name = self.name
+ if self.IsGetter():
+ name = "get_%s" % (base_name,)
+ elif self.IsSetter():
+ name = "set_%s" % (base_name,)
+ else:
+ name = base_name
+ param_decls = ["self"]
+ in_comments = []
+ out_descs = []
+ result_comment = "Result: void - None"
+ for p in self.params:
+ in_desc, in_desc_comments, out_desc, this_result_comment = p.Describe_Python()
+ if in_desc is not None:
+ param_decls.append(in_desc)
+ if in_desc_comments is not None:
+ in_comments.append(in_desc_comments)
+ if out_desc is not None:
+ out_descs.append(out_desc)
+ if this_result_comment is not None:
+ result_comment = this_result_comment
+ joiner = "\n # "
+ in_comment = out_desc = ""
+ if in_comments: in_comment = joiner + joiner.join(in_comments)
+ if out_descs: out_desc = joiner + joiner.join(out_descs)
+
+ return """ def %s( %s ):
+ # %s%s%s
+ pass""" % (name, ", ".join(param_decls), result_comment, in_comment, out_desc)
+
+ def Describe(self):
+ s = ''
+ if self.IsGetter():
+ G = 'G'
+ else:
+ G = ' '
+ if self.IsSetter():
+ S = 'S'
+ else: S = ' '
+ if self.IsHidden():
+ H = 'H'
+ else:
+ H = ' '
+ if self.IsNotXPCOM():
+ N = 'N'
+ else:
+ N = ' '
+ if self.IsConstructor():
+ C = 'C'
+ else:
+ C = ' '
+
+ def desc(a): return a.Describe()
+ method_desc = string.join(list(map(desc, self.params)), ', ')
+ result_type = TypeDescriber(self.result_desc[0], None)
+ return_desc = result_type.Describe()
+ i = string.find(return_desc, 'retval ')
+ if i != -1:
+ return_desc = return_desc[:i] + return_desc[i+len('retval '):]
+ return G+S+H+N+C+' '+return_desc+' '+self.name + '('+ method_desc + ');'
+
+class Parameter:
+ def __init__(self, param_desc, param_index, method_index, interface_info = None):
+ self.param_flags, self.type_desc = param_desc
+ self.hidden_indicator = 0 # Is this a special "size" type param that will be hidden from Python?
+ self.param_index = param_index
+ self.method_index= method_index
+ self.interface_info = interface_info
+ def __repr__(self):
+ return "<param %(param_index)d (method %(method_index)d) - flags = 0x%(param_flags)x, type = %(type_desc)s>" % self.__dict__
+ def IsIn(self):
+ return XPT_PD_IS_IN(self.param_flags)
+ def IsOut(self):
+ return XPT_PD_IS_OUT(self.param_flags)
+ def IsInOut(self):
+ return self.IsIn() and self.IsOut()
+ def IsRetval(self):
+ return XPT_PD_IS_RETVAL(self.param_flags)
+ def IsShared(self):
+ return XPT_PD_IS_SHARED(self.param_flags)
+ def IsDipper(self):
+ return XPT_PD_IS_DIPPER(self.param_flags)
+
+ def Describe_Python(self):
+ name = "param%d" % (self.param_index,)
+ if self.hidden_indicator:
+ # Could remove the comment - Im trying to tell the user where that param has
+ # gone from the signature!
+ return None, "%s is a hidden parameter" % (name,), None, None
+ t = TypeDescriber(self.type_desc[0], self)
+ decl = in_comment = out_comment = result_comment = None
+ type_desc = t.Describe()
+ if self.IsIn() and not self.IsDipper():
+ decl = name
+ extra=""
+ if self.IsOut():
+ extra = "Out"
+ in_comment = "In%s: %s: %s" % (extra, name, type_desc)
+ elif self.IsOut() or self.IsDipper():
+ if self.IsRetval():
+ result_comment = "Result: %s" % (type_desc,)
+ else:
+ out_comment = "Out: %s" % (type_desc,)
+ return decl, in_comment, out_comment, result_comment
+
+ def Describe(self):
+ parts = []
+ if self.IsInOut():
+ parts.append('inout')
+ elif self.IsIn():
+ parts.append('in')
+ elif self.IsOut():
+ parts.append('out')
+
+ if self.IsDipper(): parts.append("dipper")
+ if self.IsRetval(): parts.append('retval')
+ if self.IsShared(): parts.append('shared')
+ t = TypeDescriber(self.type_desc[0], self)
+ type_str = t.Describe()
+ parts.append(type_str)
+ return string.join(parts)
+
+# A class that allows caching and iterating of constants.
+class Constants:
+ def __init__(self, interface_info):
+ self.interface_info = interface_info
+ try:
+ self.items = [None] * interface_info.GetConstantCount()
+ except xpcom.Exception:
+ if xpcom.verbose:
+ print("** GetConstantCount failed?? - assuming no constants")
+ self.items = []
+ def __len__(self):
+ return len(self.items)
+ def __getitem__(self, index):
+ ret = self.items[index]
+ if ret is None:
+ ci = self.interface_info.GetConstant(index)
+ ret = self.items[index] = Constant(ci)
+ return ret
+
+class Constant:
+ def __init__(self, ci):
+ self.name, self.type, self.value = ci
+
+ def Describe(self):
+ return TypeDescriber(self.type, None).Describe() + ' ' +self.name+' = '+str(self.value)+';'
+
+ __str__ = Describe
+
+def MakeReprForInvoke(param):
+ tag = param.type_desc[0] & XPT_TDP_TAGMASK
+ if tag == T_INTERFACE:
+ i_info = param.interface_info
+ try:
+ iid = i_info.GetIIDForParam(param.method_index, param.param_index)
+ except xpcom.Exception:
+ # IID not available (probably not scriptable) - just use nsISupports.
+ iid = xpcom._xpcom.IID_nsISupports
+ return param.type_desc[0], 0, 0, str(iid)
+ elif tag == T_ARRAY:
+ i_info = param.interface_info
+ array_desc = i_info.GetTypeForParam(param.method_index, param.param_index, 1)
+ return param.type_desc[:-1] + array_desc[:1]
+ return param.type_desc
+
+
+class TypeDescriber:
+ def __init__(self, type_flags, param):
+ self.type_flags = type_flags
+ self.tag = XPT_TDP_TAG(self.type_flags)
+ self.param = param
+ def IsPointer(self):
+ return XPT_TDP_IS_POINTER(self.type_flags)
+ def IsUniquePointer(self):
+ return XPT_TDP_IS_UNIQUE_POINTER(self.type_flags)
+ def IsReference(self):
+ return XPT_TDP_IS_REFERENCE(self.type_flags)
+ def repr_for_invoke(self):
+ return (self.type_flags,)
+ def GetName(self):
+ is_ptr = self.IsPointer()
+ data = type_info_map.get(self.tag)
+ if data is None:
+ data = ("unknown",)
+ if self.IsReference():
+ if len(data) > 2:
+ return data[2]
+ return data[0] + " &"
+ if self.IsPointer():
+ if len(data)>1:
+ return data[1]
+ return data[0] + " *"
+ return data[0]
+
+ def Describe(self):
+ if self.tag == T_ARRAY:
+ # NOTE - Adding a type specifier to the array is different from xpt_dump.exe
+ if self.param is None or self.param.interface_info is None:
+ type_desc = "" # Dont have explicit info about the array type :-(
+ else:
+ i_info = self.param.interface_info
+ type_code = i_info.GetTypeForParam(self.param.method_index, self.param.param_index, 1)
+ type_desc = TypeDescriber( type_code[0], None).Describe()
+ return self.GetName() + "[" + type_desc + "]"
+ elif self.tag == T_INTERFACE:
+ if self.param is None or self.param.interface_info is None:
+ return "nsISomething" # Dont have explicit info about the IID :-(
+ i_info = self.param.interface_info
+ m_index = self.param.method_index
+ p_index = self.param.param_index
+ try:
+ iid = i_info.GetIIDForParam(m_index, p_index)
+ return iid.name
+ except xpcom.Exception:
+ return "nsISomething"
+ return self.GetName()
+
+# These are just for output purposes, so should be
+# the same as xpt_dump uses
+type_info_map = {
+ T_I8 : ("int8",),
+ T_I16 : ("int16",),
+ T_I32 : ("int32",),
+ T_I64 : ("int64",),
+ T_U8 : ("uint8",),
+ T_U16 : ("uint16",),
+ T_U32 : ("uint32",),
+ T_U64 : ("uint64",),
+ T_FLOAT : ("float",),
+ T_DOUBLE : ("double",),
+ T_BOOL : ("boolean",),
+ T_CHAR : ("char",),
+ T_WCHAR : ("wchar_t", "wstring"),
+ T_VOID : ("void",),
+ T_IID : ("reserved", "nsIID *", "nsIID &"),
+ T_DOMSTRING : ("DOMString",),
+ T_CHAR_STR : ("reserved", "string"),
+ T_WCHAR_STR : ("reserved", "wstring"),
+ T_INTERFACE : ("reserved", "Interface"),
+ T_INTERFACE_IS : ("reserved", "InterfaceIs *"),
+ T_ARRAY : ("reserved", "Array"),
+ T_PSTRING_SIZE_IS : ("reserved", "string_s"),
+ T_PWSTRING_SIZE_IS : ("reserved", "wstring_s"),
+}
+
+def dump_interface(iid, mode):
+ interface = Interface(iid)
+ describer_name = "Describe"
+ if mode == "xptinfo": mode = None
+ if mode is not None:
+ describer_name = describer_name + "_" + mode.capitalize()
+ describer = getattr(interface, describer_name)
+ print(describer())
+
+if __name__=='__main__':
+ if len(sys.argv) == 1:
+ print("Usage: xpt.py [-xptinfo] interface_name, ...")
+ print(" -info: Dump in a style similar to the xptdump tool")
+ print("Dumping nsISupports and nsIInterfaceInfo")
+ sys.argv.append('nsIInterfaceInfo')
+ sys.argv.append('-xptinfo')
+ sys.argv.append('nsISupports')
+ sys.argv.append('nsIInterfaceInfo')
+
+ mode = "Python"
+ for i in sys.argv[1:]:
+ if i[0] == "-":
+ mode = i[1:]
+ else:
+ dump_interface(i, mode)