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.

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

mercurial