xpcom/idl-parser/typelib.py

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 #!/usr/bin/env python
     2 # typelib.py - Generate XPCOM typelib files from IDL.
     3 #
     4 # This Source Code Form is subject to the terms of the Mozilla Public
     5 # License, v. 2.0. If a copy of the MPL was not distributed with this
     6 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
     8 """Generate an XPIDL typelib for the IDL files specified on the command line"""
    10 import os
    11 import sys
    12 import xpidl, xpt
    14 # A map of xpidl.py types to xpt.py types
    15 TypeMap = {
    16     # nsresult is not strictly an xpidl.py type, but it's useful here
    17     'nsresult':           xpt.Type.Tags.uint32,
    18     # builtins
    19     'boolean':            xpt.Type.Tags.boolean,
    20     'void':               xpt.Type.Tags.void,
    21     'int16_t':            xpt.Type.Tags.int16,
    22     'int32_t':            xpt.Type.Tags.int32,
    23     'int64_t':            xpt.Type.Tags.int64,
    24     'uint8_t':            xpt.Type.Tags.uint8,
    25     'uint16_t':           xpt.Type.Tags.uint16,
    26     'uint32_t':           xpt.Type.Tags.uint32,
    27     'uint64_t':           xpt.Type.Tags.uint64,
    28     'octet':              xpt.Type.Tags.uint8,
    29     'short':              xpt.Type.Tags.int16,
    30     'long':               xpt.Type.Tags.int32,
    31     'long long':          xpt.Type.Tags.int64,
    32     'unsigned short':     xpt.Type.Tags.uint16,
    33     'unsigned long':      xpt.Type.Tags.uint32,
    34     'unsigned long long': xpt.Type.Tags.uint64,
    35     'float':              xpt.Type.Tags.float,
    36     'double':             xpt.Type.Tags.double,
    37     'char':               xpt.Type.Tags.char,
    38     'string':             xpt.Type.Tags.char_ptr,
    39     'wchar':              xpt.Type.Tags.wchar_t,
    40     'wstring':            xpt.Type.Tags.wchar_t_ptr,
    41     # special types
    42     'nsid':               xpt.Type.Tags.nsIID,
    43     'domstring':          xpt.Type.Tags.DOMString,
    44     'astring':            xpt.Type.Tags.AString,
    45     'utf8string':         xpt.Type.Tags.UTF8String,
    46     'cstring':            xpt.Type.Tags.CString,
    47     'jsval':              xpt.Type.Tags.jsval
    48 }
    50 # XXXkhuey dipper types should go away (bug 677784)
    51 def isDipperType(type):
    52     return type == xpt.Type.Tags.DOMString or type == xpt.Type.Tags.AString or type == xpt.Type.Tags.CString or type == xpt.Type.Tags.UTF8String
    54 def build_interface(iface, ifaces):
    55     def get_type(type, calltype, iid_is=None, size_is=None):
    56         """ Return the appropriate xpt.Type object for this param """
    58         while isinstance(type, xpidl.Typedef):
    59             type = type.realtype
    61         if isinstance(type, xpidl.Builtin):
    62             if type.name == 'string' and size_is != None:
    63                   return xpt.StringWithSizeType(size_is, size_is)
    64             elif type.name == 'wstring' and size_is != None:
    65                   return xpt.WideStringWithSizeType(size_is, size_is)
    66             else:
    67                   tag = TypeMap[type.name]
    68                   isPtr = (tag == xpt.Type.Tags.char_ptr or tag == xpt.Type.Tags.wchar_t_ptr)
    69                   return xpt.SimpleType(tag,
    70                                         pointer=isPtr,
    71                                         reference=False)
    73         if isinstance(type, xpidl.Array):
    74             # NB: For an Array<T> we pass down the iid_is to get the type of T.
    75             #     This allows Arrays of InterfaceIs types to work.
    76             return xpt.ArrayType(get_type(type.type, calltype, iid_is), size_is,
    77                                  #XXXkhuey length_is duplicates size_is (bug 677788),
    78                                  size_is)
    80         if isinstance(type, xpidl.Interface) or isinstance(type, xpidl.Forward):
    81             xptiface = None
    82             for i in ifaces:
    83                 if i.name == type.name:
    84                     xptiface = i
    86             if not xptiface:
    87                 xptiface = xpt.Interface(name=type.name)
    88                 ifaces.append(xptiface)
    90             return xpt.InterfaceType(xptiface)
    92         if isinstance(type, xpidl.Native):
    93             if type.specialtype:
    94                 # XXXkhuey jsval is marked differently in the typelib and in the headers :-(
    95                 isPtr = (type.isPtr(calltype) or type.isRef(calltype)) and not type.specialtype == 'jsval'
    96                 isRef = type.isRef(calltype) and not type.specialtype == 'jsval'
    97                 return xpt.SimpleType(TypeMap[type.specialtype],
    98                                       pointer=isPtr,
    99                                       reference=isRef)
   100             elif iid_is != None:
   101                 return xpt.InterfaceIsType(iid_is)
   102             else:
   103                 # void ptr
   104                 return xpt.SimpleType(TypeMap['void'],
   105                                       pointer=True,
   106                                       reference=False)
   108         raise Exception("Unknown type!")
   110     def get_nsresult():
   111         return xpt.SimpleType(TypeMap['nsresult'])
   113     def build_nsresult_param():
   114         return xpt.Param(get_nsresult())
   116     def get_result_type(m):
   117         if not m.notxpcom:
   118             return get_nsresult()
   120         return get_type(m.realtype, '')
   122     def build_result_param(m):
   123         return xpt.Param(get_result_type(m))
   125     def build_retval_param(m):
   126         type = get_type(m.realtype, 'out')
   127         if isDipperType(type.tag):
   128             # NB: The retval bit needs to be set here, contrary to what the
   129             # xpt spec says.
   130             return xpt.Param(type, in_=True, retval=True, dipper=True)
   131         return xpt.Param(type, in_=False, out=True, retval=True)
   133     def build_attr_param(a, getter=False, setter=False):
   134         if not (getter or setter):
   135             raise Exception("Attribute param must be for a getter or a setter!")
   137         type = get_type(a.realtype, getter and 'out' or 'in')
   138         if setter:
   139             return xpt.Param(type)
   140         else:
   141             if isDipperType(type.tag):
   142                 # NB: The retval bit needs to be set here, contrary to what the
   143                 # xpt spec says.
   144                 return xpt.Param(type, in_=True, retval=True, dipper=True)
   145             return xpt.Param(type, in_=False, out=True, retval=True)
   147     if iface.namemap is None:
   148         raise Exception("Interface was not resolved.")
   150     consts = []
   151     methods = []
   153     def build_const(c):
   154         consts.append(xpt.Constant(c.name, get_type(c.basetype, ''), c.getValue()))
   156     def build_method(m):
   157         params = []
   159         def build_param(p):
   160             def findattr(p, attr):
   161                 if hasattr(p, attr) and getattr(p, attr):
   162                     for i, param in enumerate(m.params):
   163                         if param.name == getattr(p, attr):
   164                             return i
   165                     return None
   167             iid_is = findattr(p, 'iid_is')
   168             size_is = findattr(p, 'size_is')
   170             in_ = p.paramtype.count("in")
   171             out = p.paramtype.count("out")
   172             dipper = False
   173             type = get_type(p.realtype, p.paramtype, iid_is=iid_is, size_is=size_is)
   174             if out and isDipperType(type.tag):
   175                 out = False
   176                 dipper = True
   178             return xpt.Param(type, in_, out, p.retval, p.shared, dipper, p.optional)
   180         for p in m.params:
   181             params.append(build_param(p))
   183         if not m.notxpcom and m.realtype.name != 'void':
   184             params.append(build_retval_param(m))
   186         methods.append(xpt.Method(m.name, build_result_param(m), params,
   187                                   getter=False, setter=False, notxpcom=m.notxpcom,
   188                                   constructor=False, hidden=m.noscript,
   189                                   optargc=m.optional_argc,
   190                                   implicit_jscontext=m.implicit_jscontext))
   192     def build_attr(a):
   193         # Write the getter
   194         methods.append(xpt.Method(a.name, build_nsresult_param(),
   195                                   [build_attr_param(a, getter=True)],
   196                                   getter=True, setter=False,
   197                                   constructor=False, hidden=a.noscript,
   198                                   optargc=False,
   199                                   implicit_jscontext=a.implicit_jscontext))
   201         # And maybe the setter
   202         if not a.readonly:
   203             methods.append(xpt.Method(a.name, build_nsresult_param(),
   204                                       [build_attr_param(a, setter=True)],
   205                                       getter=False, setter=True,
   206                                       constructor=False, hidden=a.noscript,
   207                                       optargc=False,
   208                                       implicit_jscontext=a.implicit_jscontext))
   210     for member in iface.members:
   211         if isinstance(member, xpidl.ConstMember):
   212             build_const(member)
   213         elif isinstance(member, xpidl.Attribute):
   214             build_attr(member)
   215         elif isinstance(member, xpidl.Method):
   216             build_method(member)
   217         elif isinstance(member, xpidl.CDATA):
   218             pass
   219         else:
   220             raise Exception("Unexpected interface member: %s" % member)
   222     parent = None
   223     if iface.base:
   224         for i in ifaces:
   225             if i.name == iface.base:
   226                 parent = i
   227         if not parent:
   228             parent = xpt.Interface(name=iface.base)
   229             ifaces.append(parent)
   231     return xpt.Interface(iface.name, iface.attributes.uuid, methods=methods,
   232                          constants=consts, resolved=True, parent=parent,
   233                          scriptable=iface.attributes.scriptable,
   234                          function=iface.attributes.function,
   235                          builtinclass=iface.attributes.builtinclass)
   237 def write_typelib(idl, fd, filename):
   238     """ Generate the typelib. """
   240     # We only care about interfaces
   241     ifaces = []
   242     for p in idl.productions:
   243         if p.kind == 'interface':
   244             ifaces.append(build_interface(p, ifaces))
   246     typelib = xpt.Typelib(interfaces=ifaces)
   247     typelib.writefd(fd)
   249 if __name__ == '__main__':
   250     from optparse import OptionParser
   251     o = OptionParser()
   252     o.add_option('-I', action='append', dest='incdirs', default=['.'],
   253                  help="Directory to search for imported files")
   254     o.add_option('--cachedir', dest='cachedir', default=None,
   255                  help="Directory in which to cache lex/parse tables.")
   256     o.add_option('-o', dest='outfile', default=None,
   257                  help="Output file")
   258     o.add_option('-d', dest='depfile', default=None,
   259                  help="Generate a make dependency file")
   260     o.add_option('--regen', action='store_true', dest='regen', default=False,
   261                  help="Regenerate IDL Parser cache")
   262     options, args = o.parse_args()
   263     file = args[0] if args else None
   265     if options.cachedir is not None:
   266         if not os.path.isdir(options.cachedir):
   267             os.mkdir(options.cachedir)
   268         sys.path.append(options.cachedir)
   270     if options.regen:
   271         if options.cachedir is None:
   272             print >>sys.stderr, "--regen requires --cachedir"
   273             sys.exit(1)
   275         p = xpidl.IDLParser(outputdir=options.cachedir, regen=True)
   276         sys.exit(0)
   278     if options.depfile is not None and options.outfile is None:
   279         print >>sys.stderr, "-d requires -o"
   280         sys.exit(1)
   282     if options.outfile is not None:
   283         outfd = open(options.outfile, 'wb')
   284         closeoutfd = True
   285     else:
   286         raise "typelib generation requires an output file"
   288     p = xpidl.IDLParser(outputdir=options.cachedir)
   289     idl = p.parse(open(file).read(), filename=file)
   290     idl.resolve(options.incdirs, p)
   291     write_typelib(idl, outfd, file)
   293     if closeoutfd:
   294         outfd.close()
   296     if options.depfile is not None:
   297         depfd = open(options.depfile, 'w')
   298         deps = [dep.replace('\\', '/') for dep in idl.deps]
   300         print >>depfd, "%s: %s" % (options.outfile, " ".join(deps))
   301         for dep in deps:
   302             print >>depfd, "%s:" % dep

mercurial