mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-21 14:47:31 +09:00
import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo
This commit is contained in:
commit
dcd9973243
150858 changed files with 23884658 additions and 0 deletions
0
xpcom/idl-parser/xpidl/__init__.py
Normal file
0
xpcom/idl-parser/xpidl/__init__.py
Normal file
566
xpcom/idl-parser/xpidl/header.py
Normal file
566
xpcom/idl-parser/xpidl/header.py
Normal file
|
|
@ -0,0 +1,566 @@
|
|||
#!/usr/bin/env python
|
||||
# header.py - Generate C++ header files from IDL.
|
||||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
"""Print a C++ header file for the IDL files specified on the command line"""
|
||||
|
||||
import sys
|
||||
import os.path
|
||||
import re
|
||||
import xpidl
|
||||
import itertools
|
||||
import glob
|
||||
|
||||
printdoccomments = False
|
||||
|
||||
if printdoccomments:
|
||||
def printComments(fd, clist, indent):
|
||||
for c in clist:
|
||||
fd.write("%s%s\n" % (indent, c))
|
||||
else:
|
||||
def printComments(fd, clist, indent):
|
||||
pass
|
||||
|
||||
|
||||
def firstCap(str):
|
||||
return str[0].upper() + str[1:]
|
||||
|
||||
|
||||
def attributeParamName(a):
|
||||
return "a" + firstCap(a.name)
|
||||
|
||||
|
||||
def attributeParamNames(a):
|
||||
l = [attributeParamName(a)]
|
||||
if a.implicit_jscontext:
|
||||
l.insert(0, "cx")
|
||||
return ", ".join(l)
|
||||
|
||||
|
||||
def attributeNativeName(a, getter):
|
||||
binaryname = a.binaryname is not None and a.binaryname or firstCap(a.name)
|
||||
return "%s%s" % (getter and 'Get' or 'Set', binaryname)
|
||||
|
||||
|
||||
def attributeReturnType(a, macro):
|
||||
"""macro should be NS_IMETHOD or NS_IMETHODIMP"""
|
||||
if a.nostdcall:
|
||||
ret = macro == "NS_IMETHOD" and "virtual nsresult" or "nsresult"
|
||||
else:
|
||||
ret = macro
|
||||
if a.must_use:
|
||||
ret = "MOZ_MUST_USE " + ret
|
||||
return ret
|
||||
|
||||
|
||||
def attributeParamlist(a, getter):
|
||||
l = ["%s%s" % (a.realtype.nativeType(getter and 'out' or 'in'),
|
||||
attributeParamName(a))]
|
||||
if a.implicit_jscontext:
|
||||
l.insert(0, "JSContext* cx")
|
||||
|
||||
return ", ".join(l)
|
||||
|
||||
|
||||
def attributeAsNative(a, getter, declType = 'NS_IMETHOD'):
|
||||
deprecated = a.deprecated and "NS_DEPRECATED " or ""
|
||||
params = {'deprecated': deprecated,
|
||||
'returntype': attributeReturnType(a, declType),
|
||||
'binaryname': attributeNativeName(a, getter),
|
||||
'paramlist': attributeParamlist(a, getter)}
|
||||
return "%(deprecated)s%(returntype)s %(binaryname)s(%(paramlist)s)" % params
|
||||
|
||||
|
||||
def methodNativeName(m):
|
||||
return m.binaryname is not None and m.binaryname or firstCap(m.name)
|
||||
|
||||
|
||||
def methodReturnType(m, macro):
|
||||
"""macro should be NS_IMETHOD or NS_IMETHODIMP"""
|
||||
if m.nostdcall and m.notxpcom:
|
||||
ret = "%s%s" % (macro == "NS_IMETHOD" and "virtual " or "",
|
||||
m.realtype.nativeType('in').strip())
|
||||
elif m.nostdcall:
|
||||
ret = "%snsresult" % (macro == "NS_IMETHOD" and "virtual " or "")
|
||||
elif m.notxpcom:
|
||||
ret = "%s_(%s)" % (macro, m.realtype.nativeType('in').strip())
|
||||
else:
|
||||
ret = macro
|
||||
if m.must_use:
|
||||
ret = "MOZ_MUST_USE " + ret
|
||||
return ret
|
||||
|
||||
|
||||
def methodAsNative(m, declType = 'NS_IMETHOD'):
|
||||
return "%s %s(%s)" % (methodReturnType(m, declType),
|
||||
methodNativeName(m),
|
||||
paramlistAsNative(m))
|
||||
|
||||
|
||||
def paramlistAsNative(m, empty='void'):
|
||||
l = [paramAsNative(p) for p in m.params]
|
||||
|
||||
if m.implicit_jscontext:
|
||||
l.append("JSContext* cx")
|
||||
|
||||
if m.optional_argc:
|
||||
l.append('uint8_t _argc')
|
||||
|
||||
if not m.notxpcom and m.realtype.name != 'void':
|
||||
l.append(paramAsNative(xpidl.Param(paramtype='out',
|
||||
type=None,
|
||||
name='_retval',
|
||||
attlist=[],
|
||||
location=None,
|
||||
realtype=m.realtype)))
|
||||
|
||||
# Set any optional out params to default to nullptr. Skip if we just added
|
||||
# extra non-optional args to l.
|
||||
if len(l) == len(m.params):
|
||||
paramIter = len(m.params) - 1
|
||||
while (paramIter >= 0 and m.params[paramIter].optional and
|
||||
m.params[paramIter].paramtype == "out"):
|
||||
t = m.params[paramIter].type
|
||||
# Strings can't be optional, so this shouldn't happen, but let's make sure:
|
||||
if t == "AString" or t == "ACString" or t == "DOMString" or t == "AUTF8String":
|
||||
break
|
||||
l[paramIter] += " = nullptr"
|
||||
paramIter -= 1
|
||||
|
||||
if len(l) == 0:
|
||||
return empty
|
||||
|
||||
return ", ".join(l)
|
||||
|
||||
|
||||
def paramAsNative(p):
|
||||
return "%s%s" % (p.nativeType(),
|
||||
p.name)
|
||||
|
||||
|
||||
def paramlistNames(m):
|
||||
names = [p.name for p in m.params]
|
||||
|
||||
if m.implicit_jscontext:
|
||||
names.append('cx')
|
||||
|
||||
if m.optional_argc:
|
||||
names.append('_argc')
|
||||
|
||||
if not m.notxpcom and m.realtype.name != 'void':
|
||||
names.append('_retval')
|
||||
|
||||
if len(names) == 0:
|
||||
return ''
|
||||
return ', '.join(names)
|
||||
|
||||
header = """/*
|
||||
* DO NOT EDIT. THIS FILE IS GENERATED FROM %(filename)s
|
||||
*/
|
||||
|
||||
#ifndef __gen_%(basename)s_h__
|
||||
#define __gen_%(basename)s_h__
|
||||
"""
|
||||
|
||||
include = """
|
||||
#ifndef __gen_%(basename)s_h__
|
||||
#include "%(basename)s.h"
|
||||
#endif
|
||||
"""
|
||||
|
||||
jsvalue_include = """
|
||||
#include "js/Value.h"
|
||||
"""
|
||||
|
||||
infallible_includes = """
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
"""
|
||||
|
||||
header_end = """/* For IDL files that don't want to include root IDL files. */
|
||||
#ifndef NS_NO_VTABLE
|
||||
#define NS_NO_VTABLE
|
||||
#endif
|
||||
"""
|
||||
|
||||
footer = """
|
||||
#endif /* __gen_%(basename)s_h__ */
|
||||
"""
|
||||
|
||||
forward_decl = """class %(name)s; /* forward declaration */
|
||||
|
||||
"""
|
||||
|
||||
|
||||
def idl_basename(f):
|
||||
"""returns the base name of a file with the last extension stripped"""
|
||||
return os.path.basename(f).rpartition('.')[0]
|
||||
|
||||
|
||||
def print_header(idl, fd, filename):
|
||||
fd.write(header % {'filename': filename,
|
||||
'basename': idl_basename(filename)})
|
||||
|
||||
foundinc = False
|
||||
for inc in idl.includes():
|
||||
if not foundinc:
|
||||
foundinc = True
|
||||
fd.write('\n')
|
||||
fd.write(include % {'basename': idl_basename(inc.filename)})
|
||||
|
||||
if idl.needsJSTypes():
|
||||
fd.write(jsvalue_include)
|
||||
|
||||
# Include some extra files if any attributes are infallible.
|
||||
for iface in [p for p in idl.productions if p.kind == 'interface']:
|
||||
for attr in [m for m in iface.members if isinstance(m, xpidl.Attribute)]:
|
||||
if attr.infallible:
|
||||
fd.write(infallible_includes)
|
||||
break
|
||||
|
||||
fd.write('\n')
|
||||
fd.write(header_end)
|
||||
|
||||
for p in idl.productions:
|
||||
if p.kind == 'include':
|
||||
continue
|
||||
if p.kind == 'cdata':
|
||||
fd.write(p.data)
|
||||
continue
|
||||
|
||||
if p.kind == 'forward':
|
||||
fd.write(forward_decl % {'name': p.name})
|
||||
continue
|
||||
if p.kind == 'interface':
|
||||
write_interface(p, fd)
|
||||
continue
|
||||
if p.kind == 'typedef':
|
||||
printComments(fd, p.doccomments, '')
|
||||
fd.write("typedef %s %s;\n\n" % (p.realtype.nativeType('in'),
|
||||
p.name))
|
||||
|
||||
fd.write(footer % {'basename': idl_basename(filename)})
|
||||
|
||||
iface_header = r"""
|
||||
/* starting interface: %(name)s */
|
||||
#define %(defname)s_IID_STR "%(iid)s"
|
||||
|
||||
#define %(defname)s_IID \
|
||||
{0x%(m0)s, 0x%(m1)s, 0x%(m2)s, \
|
||||
{ %(m3joined)s }}
|
||||
|
||||
"""
|
||||
|
||||
uuid_decoder = re.compile(r"""(?P<m0>[a-f0-9]{8})-
|
||||
(?P<m1>[a-f0-9]{4})-
|
||||
(?P<m2>[a-f0-9]{4})-
|
||||
(?P<m3>[a-f0-9]{4})-
|
||||
(?P<m4>[a-f0-9]{12})$""", re.X)
|
||||
|
||||
iface_prolog = """ {
|
||||
public:
|
||||
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(%(defname)s_IID)
|
||||
|
||||
"""
|
||||
|
||||
iface_epilog = """};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(%(name)s, %(defname)s_IID)
|
||||
|
||||
/* Use this macro when declaring classes that implement this interface. */
|
||||
#define NS_DECL_%(macroname)s """
|
||||
|
||||
iface_nonvirtual = """
|
||||
|
||||
/* Use this macro when declaring the members of this interface when the
|
||||
class doesn't implement the interface. This is useful for forwarding. */
|
||||
#define NS_DECL_NON_VIRTUAL_%(macroname)s """
|
||||
|
||||
iface_forward = """
|
||||
|
||||
/* Use this macro to declare functions that forward the behavior of this interface to another object. */
|
||||
#define NS_FORWARD_%(macroname)s(_to) """
|
||||
|
||||
iface_forward_safe = """
|
||||
|
||||
/* Use this macro to declare functions that forward the behavior of this interface to another object in a safe way. */
|
||||
#define NS_FORWARD_SAFE_%(macroname)s(_to) """
|
||||
|
||||
iface_template_prolog = """
|
||||
|
||||
#if 0
|
||||
/* Use the code below as a template for the implementation class for this interface. */
|
||||
|
||||
/* Header file */
|
||||
class %(implclass)s : public %(name)s
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_%(macroname)s
|
||||
|
||||
%(implclass)s();
|
||||
|
||||
private:
|
||||
~%(implclass)s();
|
||||
|
||||
protected:
|
||||
/* additional members */
|
||||
};
|
||||
|
||||
/* Implementation file */
|
||||
NS_IMPL_ISUPPORTS(%(implclass)s, %(name)s)
|
||||
|
||||
%(implclass)s::%(implclass)s()
|
||||
{
|
||||
/* member initializers and constructor code */
|
||||
}
|
||||
|
||||
%(implclass)s::~%(implclass)s()
|
||||
{
|
||||
/* destructor code */
|
||||
}
|
||||
|
||||
"""
|
||||
|
||||
example_tmpl = """%(returntype)s %(implclass)s::%(nativeName)s(%(paramList)s)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
"""
|
||||
|
||||
iface_template_epilog = """/* End of implementation class template. */
|
||||
#endif
|
||||
|
||||
"""
|
||||
|
||||
attr_infallible_tmpl = """\
|
||||
inline %(realtype)s%(nativename)s(%(args)s)
|
||||
{
|
||||
%(realtype)sresult;
|
||||
mozilla::DebugOnly<nsresult> rv = %(nativename)s(%(argnames)s&result);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
return result;
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
def write_interface(iface, fd):
|
||||
if iface.namemap is None:
|
||||
raise Exception("Interface was not resolved.")
|
||||
|
||||
# Confirm that no names of methods will overload in this interface
|
||||
names = set()
|
||||
def record_name(name):
|
||||
if name in names:
|
||||
raise Exception("Unexpected overloaded virtual method %s in interface %s"
|
||||
% (name, iface.name))
|
||||
names.add(name)
|
||||
for m in iface.members:
|
||||
if type(m) == xpidl.Attribute:
|
||||
record_name(attributeNativeName(m, getter=True))
|
||||
if not m.readonly:
|
||||
record_name(attributeNativeName(m, getter=False))
|
||||
elif type(m) == xpidl.Method:
|
||||
record_name(methodNativeName(m))
|
||||
|
||||
def write_const_decls(g):
|
||||
fd.write(" enum {\n")
|
||||
enums = []
|
||||
for c in g:
|
||||
printComments(fd, c.doccomments, ' ')
|
||||
basetype = c.basetype
|
||||
value = c.getValue()
|
||||
enums.append(" %(name)s = %(value)s%(signed)s" % {
|
||||
'name': c.name,
|
||||
'value': value,
|
||||
'signed': (not basetype.signed) and 'U' or ''})
|
||||
fd.write(",\n".join(enums))
|
||||
fd.write("\n };\n\n")
|
||||
|
||||
def write_method_decl(m):
|
||||
printComments(fd, m.doccomments, ' ')
|
||||
|
||||
fd.write(" /* %s */\n" % m.toIDL())
|
||||
fd.write(" %s = 0;\n\n" % methodAsNative(m))
|
||||
|
||||
def write_attr_decl(a):
|
||||
printComments(fd, a.doccomments, ' ')
|
||||
|
||||
fd.write(" /* %s */\n" % a.toIDL())
|
||||
|
||||
fd.write(" %s = 0;\n" % attributeAsNative(a, True))
|
||||
if a.infallible:
|
||||
fd.write(attr_infallible_tmpl %
|
||||
{'realtype': a.realtype.nativeType('in'),
|
||||
'nativename': attributeNativeName(a, getter=True),
|
||||
'args': '' if not a.implicit_jscontext else 'JSContext* cx',
|
||||
'argnames': '' if not a.implicit_jscontext else 'cx, '})
|
||||
|
||||
if not a.readonly:
|
||||
fd.write(" %s = 0;\n" % attributeAsNative(a, False))
|
||||
fd.write("\n")
|
||||
|
||||
defname = iface.name.upper()
|
||||
if iface.name[0:2] == 'ns':
|
||||
defname = 'NS_' + defname[2:]
|
||||
|
||||
names = uuid_decoder.match(iface.attributes.uuid).groupdict()
|
||||
m3str = names['m3'] + names['m4']
|
||||
names['m3joined'] = ", ".join(["0x%s" % m3str[i:i+2] for i in xrange(0, 16, 2)])
|
||||
|
||||
if iface.name[2] == 'I':
|
||||
implclass = iface.name[:2] + iface.name[3:]
|
||||
else:
|
||||
implclass = '_MYCLASS_'
|
||||
|
||||
names.update({'defname': defname,
|
||||
'macroname': iface.name.upper(),
|
||||
'name': iface.name,
|
||||
'iid': iface.attributes.uuid,
|
||||
'implclass': implclass})
|
||||
|
||||
fd.write(iface_header % names)
|
||||
|
||||
printComments(fd, iface.doccomments, '')
|
||||
|
||||
fd.write("class ")
|
||||
foundcdata = False
|
||||
for m in iface.members:
|
||||
if isinstance(m, xpidl.CDATA):
|
||||
foundcdata = True
|
||||
|
||||
if not foundcdata:
|
||||
fd.write("NS_NO_VTABLE ")
|
||||
|
||||
if iface.attributes.deprecated:
|
||||
fd.write("MOZ_DEPRECATED ")
|
||||
fd.write(iface.name)
|
||||
if iface.base:
|
||||
fd.write(" : public %s" % iface.base)
|
||||
fd.write(iface_prolog % names)
|
||||
|
||||
for key, group in itertools.groupby(iface.members, key=type):
|
||||
if key == xpidl.ConstMember:
|
||||
write_const_decls(group) # iterator of all the consts
|
||||
else:
|
||||
for member in group:
|
||||
if key == xpidl.Attribute:
|
||||
write_attr_decl(member)
|
||||
elif key == xpidl.Method:
|
||||
write_method_decl(member)
|
||||
elif key == xpidl.CDATA:
|
||||
fd.write(" %s" % member.data)
|
||||
else:
|
||||
raise Exception("Unexpected interface member: %s" % member)
|
||||
|
||||
fd.write(iface_epilog % names)
|
||||
|
||||
def writeDeclaration(fd, iface, virtual):
|
||||
declType = "NS_IMETHOD" if virtual else "NS_METHOD"
|
||||
suffix = " override" if virtual else ""
|
||||
for member in iface.members:
|
||||
if isinstance(member, xpidl.Attribute):
|
||||
if member.infallible:
|
||||
fd.write("\\\n using %s::%s; " % (iface.name, attributeNativeName(member, True)))
|
||||
fd.write("\\\n %s%s; " % (attributeAsNative(member, True, declType), suffix))
|
||||
if not member.readonly:
|
||||
fd.write("\\\n %s%s; " % (attributeAsNative(member, False, declType), suffix))
|
||||
elif isinstance(member, xpidl.Method):
|
||||
fd.write("\\\n %s%s; " % (methodAsNative(member, declType), suffix))
|
||||
if len(iface.members) == 0:
|
||||
fd.write('\\\n /* no methods! */')
|
||||
elif not member.kind in ('attribute', 'method'):
|
||||
fd.write('\\')
|
||||
|
||||
writeDeclaration(fd, iface, True);
|
||||
fd.write(iface_nonvirtual % names)
|
||||
writeDeclaration(fd, iface, False);
|
||||
fd.write(iface_forward % names)
|
||||
|
||||
def emitTemplate(forward_infallible, tmpl, tmpl_notxpcom=None):
|
||||
if tmpl_notxpcom is None:
|
||||
tmpl_notxpcom = tmpl
|
||||
for member in iface.members:
|
||||
if isinstance(member, xpidl.Attribute):
|
||||
if forward_infallible and member.infallible:
|
||||
fd.write("\\\n using %s::%s; " % (iface.name, attributeNativeName(member, True)))
|
||||
fd.write(tmpl % {'asNative': attributeAsNative(member, True),
|
||||
'nativeName': attributeNativeName(member, True),
|
||||
'paramList': attributeParamNames(member)})
|
||||
if not member.readonly:
|
||||
fd.write(tmpl % {'asNative': attributeAsNative(member, False),
|
||||
'nativeName': attributeNativeName(member, False),
|
||||
'paramList': attributeParamNames(member)})
|
||||
elif isinstance(member, xpidl.Method):
|
||||
if member.notxpcom:
|
||||
fd.write(tmpl_notxpcom % {'asNative': methodAsNative(member),
|
||||
'nativeName': methodNativeName(member),
|
||||
'paramList': paramlistNames(member)})
|
||||
else:
|
||||
fd.write(tmpl % {'asNative': methodAsNative(member),
|
||||
'nativeName': methodNativeName(member),
|
||||
'paramList': paramlistNames(member)})
|
||||
if len(iface.members) == 0:
|
||||
fd.write('\\\n /* no methods! */')
|
||||
elif not member.kind in ('attribute', 'method'):
|
||||
fd.write('\\')
|
||||
|
||||
emitTemplate(True,
|
||||
"\\\n %(asNative)s override { return _to %(nativeName)s(%(paramList)s); } ")
|
||||
|
||||
fd.write(iface_forward_safe % names)
|
||||
|
||||
# Don't try to safely forward notxpcom functions, because we have no
|
||||
# sensible default error return. Instead, the caller will have to
|
||||
# implement them.
|
||||
emitTemplate(False,
|
||||
"\\\n %(asNative)s override { return !_to ? NS_ERROR_NULL_POINTER : _to->%(nativeName)s(%(paramList)s); } ",
|
||||
"\\\n %(asNative)s override; ")
|
||||
|
||||
fd.write(iface_template_prolog % names)
|
||||
|
||||
for member in iface.members:
|
||||
if isinstance(member, xpidl.ConstMember) or isinstance(member, xpidl.CDATA):
|
||||
continue
|
||||
fd.write("/* %s */\n" % member.toIDL())
|
||||
if isinstance(member, xpidl.Attribute):
|
||||
fd.write(example_tmpl % {'implclass': implclass,
|
||||
'returntype': attributeReturnType(member, 'NS_IMETHODIMP'),
|
||||
'nativeName': attributeNativeName(member, True),
|
||||
'paramList': attributeParamlist(member, True)})
|
||||
if not member.readonly:
|
||||
fd.write(example_tmpl % {'implclass': implclass,
|
||||
'returntype': attributeReturnType(member, 'NS_IMETHODIMP'),
|
||||
'nativeName': attributeNativeName(member, False),
|
||||
'paramList': attributeParamlist(member, False)})
|
||||
elif isinstance(member, xpidl.Method):
|
||||
fd.write(example_tmpl % {'implclass': implclass,
|
||||
'returntype': methodReturnType(member, 'NS_IMETHODIMP'),
|
||||
'nativeName': methodNativeName(member),
|
||||
'paramList': paramlistAsNative(member, empty='')})
|
||||
fd.write('\n')
|
||||
|
||||
fd.write(iface_template_epilog)
|
||||
|
||||
|
||||
def main(outputfile):
|
||||
cachedir = '.'
|
||||
if not os.path.isdir(cachedir):
|
||||
os.mkdir(cachedir)
|
||||
sys.path.append(cachedir)
|
||||
|
||||
# Delete the lex/yacc files. Ply is too stupid to regenerate them
|
||||
# properly
|
||||
for fileglobs in [os.path.join(cachedir, f) for f in ["xpidllex.py*", "xpidlyacc.py*"]]:
|
||||
for filename in glob.glob(fileglobs):
|
||||
os.remove(filename)
|
||||
|
||||
# Instantiate the parser.
|
||||
p = xpidl.IDLParser(outputdir=cachedir)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(None)
|
||||
29
xpcom/idl-parser/xpidl/moz.build
Normal file
29
xpcom/idl-parser/xpidl/moz.build
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
PYTHON_UNIT_TESTS += [
|
||||
'runtests.py',
|
||||
]
|
||||
|
||||
GENERATED_FILES += [
|
||||
('xpidl.stub', 'xpidllex.py', 'xpidlyacc.py'),
|
||||
]
|
||||
|
||||
GENERATED_FILES[('xpidl.stub', 'xpidllex.py', 'xpidlyacc.py')].script = 'header.py:main'
|
||||
|
||||
SDK_FILES.bin += [
|
||||
'!xpidllex.py',
|
||||
'!xpidlyacc.py',
|
||||
'header.py',
|
||||
'typelib.py',
|
||||
'xpidl.py',
|
||||
]
|
||||
|
||||
SDK_FILES.bin.ply += [
|
||||
'/other-licenses/ply/ply/__init__.py',
|
||||
'/other-licenses/ply/ply/lex.py',
|
||||
'/other-licenses/ply/ply/yacc.py',
|
||||
]
|
||||
114
xpcom/idl-parser/xpidl/runtests.py
Normal file
114
xpcom/idl-parser/xpidl/runtests.py
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# Any copyright is dedicated to the Public Domain.
|
||||
# http://creativecommons.org/publicdomain/zero/1.0/
|
||||
#
|
||||
# Unit tests for xpidl.py
|
||||
|
||||
import mozunit
|
||||
import unittest
|
||||
import xpidl
|
||||
import header
|
||||
|
||||
|
||||
class TestParser(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.p = xpidl.IDLParser()
|
||||
|
||||
def testEmpty(self):
|
||||
i = self.p.parse("", filename='f')
|
||||
self.assertTrue(isinstance(i, xpidl.IDL))
|
||||
self.assertEqual([], i.productions)
|
||||
|
||||
def testForwardInterface(self):
|
||||
i = self.p.parse("interface foo;", filename='f')
|
||||
self.assertTrue(isinstance(i, xpidl.IDL))
|
||||
self.assertTrue(isinstance(i.productions[0], xpidl.Forward))
|
||||
self.assertEqual("foo", i.productions[0].name)
|
||||
|
||||
def testInterface(self):
|
||||
i = self.p.parse("[uuid(abc)] interface foo {};", filename='f')
|
||||
self.assertTrue(isinstance(i, xpidl.IDL))
|
||||
self.assertTrue(isinstance(i.productions[0], xpidl.Interface))
|
||||
self.assertEqual("foo", i.productions[0].name)
|
||||
|
||||
def testAttributes(self):
|
||||
i = self.p.parse("[scriptable, builtinclass, function, deprecated, uuid(abc)] interface foo {};", filename='f')
|
||||
self.assertTrue(isinstance(i, xpidl.IDL))
|
||||
self.assertTrue(isinstance(i.productions[0], xpidl.Interface))
|
||||
iface = i.productions[0]
|
||||
self.assertEqual("foo", iface.name)
|
||||
self.assertTrue(iface.attributes.scriptable)
|
||||
self.assertTrue(iface.attributes.builtinclass)
|
||||
self.assertTrue(iface.attributes.function)
|
||||
self.assertTrue(iface.attributes.deprecated)
|
||||
|
||||
i = self.p.parse("[noscript, uuid(abc)] interface foo {};", filename='f')
|
||||
self.assertTrue(isinstance(i, xpidl.IDL))
|
||||
self.assertTrue(isinstance(i.productions[0], xpidl.Interface))
|
||||
iface = i.productions[0]
|
||||
self.assertEqual("foo", iface.name)
|
||||
self.assertTrue(iface.attributes.noscript)
|
||||
|
||||
def testMethod(self):
|
||||
i = self.p.parse("""[uuid(abc)] interface foo {
|
||||
void bar();
|
||||
};""", filename='f')
|
||||
self.assertTrue(isinstance(i, xpidl.IDL))
|
||||
self.assertTrue(isinstance(i.productions[0], xpidl.Interface))
|
||||
iface = i.productions[0]
|
||||
m = iface.members[0]
|
||||
self.assertTrue(isinstance(m, xpidl.Method))
|
||||
self.assertEqual("bar", m.name)
|
||||
self.assertEqual("void", m.type)
|
||||
|
||||
def testMethodParams(self):
|
||||
i = self.p.parse("""[uuid(abc)] interface foo {
|
||||
long bar(in long a, in float b, [array] in long c);
|
||||
};""", filename='f')
|
||||
i.resolve([], self.p)
|
||||
self.assertTrue(isinstance(i, xpidl.IDL))
|
||||
self.assertTrue(isinstance(i.productions[0], xpidl.Interface))
|
||||
iface = i.productions[0]
|
||||
m = iface.members[0]
|
||||
self.assertTrue(isinstance(m, xpidl.Method))
|
||||
self.assertEqual("bar", m.name)
|
||||
self.assertEqual("long", m.type)
|
||||
self.assertEqual(3, len(m.params))
|
||||
self.assertEqual("long", m.params[0].type)
|
||||
self.assertEqual("in", m.params[0].paramtype)
|
||||
self.assertEqual("float", m.params[1].type)
|
||||
self.assertEqual("in", m.params[1].paramtype)
|
||||
self.assertEqual("long", m.params[2].type)
|
||||
self.assertEqual("in", m.params[2].paramtype)
|
||||
self.assertTrue(isinstance(m.params[2].realtype, xpidl.Array))
|
||||
self.assertEqual("long", m.params[2].realtype.type.name)
|
||||
|
||||
def testAttribute(self):
|
||||
i = self.p.parse("""[uuid(abc)] interface foo {
|
||||
attribute long bar;
|
||||
};""", filename='f')
|
||||
self.assertTrue(isinstance(i, xpidl.IDL))
|
||||
self.assertTrue(isinstance(i.productions[0], xpidl.Interface))
|
||||
iface = i.productions[0]
|
||||
a = iface.members[0]
|
||||
self.assertTrue(isinstance(a, xpidl.Attribute))
|
||||
self.assertEqual("bar", a.name)
|
||||
self.assertEqual("long", a.type)
|
||||
|
||||
def testOverloadedVirtual(self):
|
||||
i = self.p.parse("""[uuid(abc)] interface foo {
|
||||
attribute long bar;
|
||||
void getBar();
|
||||
};""", filename='f')
|
||||
self.assertTrue(isinstance(i, xpidl.IDL))
|
||||
class FdMock:
|
||||
def write(self, s):
|
||||
pass
|
||||
try:
|
||||
header.print_header(i, FdMock(), filename='f')
|
||||
except Exception as e:
|
||||
self.assertEqual(e.args[0], "Unexpected overloaded virtual method GetBar in interface foo")
|
||||
|
||||
if __name__ == '__main__':
|
||||
mozunit.main()
|
||||
307
xpcom/idl-parser/xpidl/typelib.py
Normal file
307
xpcom/idl-parser/xpidl/typelib.py
Normal file
|
|
@ -0,0 +1,307 @@
|
|||
#!/usr/bin/env python
|
||||
# typelib.py - Generate XPCOM typelib files from IDL.
|
||||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
"""Generate an XPIDL typelib for the IDL files specified on the command line"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import xpidl
|
||||
import xpt
|
||||
|
||||
# A map of xpidl.py types to xpt.py types
|
||||
TypeMap = {
|
||||
# nsresult is not strictly an xpidl.py type, but it's useful here
|
||||
'nsresult': xpt.Type.Tags.uint32,
|
||||
# builtins
|
||||
'boolean': xpt.Type.Tags.boolean,
|
||||
'void': xpt.Type.Tags.void,
|
||||
'int16_t': xpt.Type.Tags.int16,
|
||||
'int32_t': xpt.Type.Tags.int32,
|
||||
'int64_t': xpt.Type.Tags.int64,
|
||||
'uint8_t': xpt.Type.Tags.uint8,
|
||||
'uint16_t': xpt.Type.Tags.uint16,
|
||||
'uint32_t': xpt.Type.Tags.uint32,
|
||||
'uint64_t': xpt.Type.Tags.uint64,
|
||||
'octet': xpt.Type.Tags.uint8,
|
||||
'short': xpt.Type.Tags.int16,
|
||||
'long': xpt.Type.Tags.int32,
|
||||
'long long': xpt.Type.Tags.int64,
|
||||
'unsigned short': xpt.Type.Tags.uint16,
|
||||
'unsigned long': xpt.Type.Tags.uint32,
|
||||
'unsigned long long': xpt.Type.Tags.uint64,
|
||||
'float': xpt.Type.Tags.float,
|
||||
'double': xpt.Type.Tags.double,
|
||||
'char': xpt.Type.Tags.char,
|
||||
'string': xpt.Type.Tags.char_ptr,
|
||||
'wchar': xpt.Type.Tags.wchar_t,
|
||||
'wstring': xpt.Type.Tags.wchar_t_ptr,
|
||||
# special types
|
||||
'nsid': xpt.Type.Tags.nsIID,
|
||||
'domstring': xpt.Type.Tags.DOMString,
|
||||
'astring': xpt.Type.Tags.AString,
|
||||
'utf8string': xpt.Type.Tags.UTF8String,
|
||||
'cstring': xpt.Type.Tags.CString,
|
||||
'jsval': xpt.Type.Tags.jsval
|
||||
}
|
||||
|
||||
|
||||
# XXXkhuey dipper types should go away (bug 677784)
|
||||
def isDipperType(type):
|
||||
return type == xpt.Type.Tags.DOMString or type == xpt.Type.Tags.AString or type == xpt.Type.Tags.CString or type == xpt.Type.Tags.UTF8String
|
||||
|
||||
|
||||
def build_interface(iface, ifaces):
|
||||
def get_type(type, calltype, iid_is=None, size_is=None):
|
||||
""" Return the appropriate xpt.Type object for this param """
|
||||
|
||||
while isinstance(type, xpidl.Typedef):
|
||||
type = type.realtype
|
||||
|
||||
if isinstance(type, xpidl.Builtin):
|
||||
if type.name == 'string' and size_is is not None:
|
||||
return xpt.StringWithSizeType(size_is, size_is)
|
||||
elif type.name == 'wstring' and size_is is not None:
|
||||
return xpt.WideStringWithSizeType(size_is, size_is)
|
||||
else:
|
||||
tag = TypeMap[type.name]
|
||||
isPtr = (tag == xpt.Type.Tags.char_ptr or tag == xpt.Type.Tags.wchar_t_ptr)
|
||||
return xpt.SimpleType(tag,
|
||||
pointer=isPtr,
|
||||
reference=False)
|
||||
|
||||
if isinstance(type, xpidl.Array):
|
||||
# NB: For an Array<T> we pass down the iid_is to get the type of T.
|
||||
# This allows Arrays of InterfaceIs types to work.
|
||||
return xpt.ArrayType(get_type(type.type, calltype, iid_is), size_is,
|
||||
#XXXkhuey length_is duplicates size_is (bug 677788),
|
||||
size_is)
|
||||
|
||||
if isinstance(type, xpidl.Interface) or isinstance(type, xpidl.Forward):
|
||||
xptiface = None
|
||||
for i in ifaces:
|
||||
if i.name == type.name:
|
||||
xptiface = i
|
||||
|
||||
if not xptiface:
|
||||
xptiface = xpt.Interface(name=type.name)
|
||||
ifaces.append(xptiface)
|
||||
|
||||
return xpt.InterfaceType(xptiface)
|
||||
|
||||
if isinstance(type, xpidl.Native):
|
||||
if type.specialtype:
|
||||
# XXXkhuey jsval is marked differently in the typelib and in the headers :-(
|
||||
isPtr = (type.isPtr(calltype) or type.isRef(calltype)) and not type.specialtype == 'jsval'
|
||||
isRef = type.isRef(calltype) and not type.specialtype == 'jsval'
|
||||
return xpt.SimpleType(TypeMap[type.specialtype],
|
||||
pointer=isPtr,
|
||||
reference=isRef)
|
||||
elif iid_is is not None:
|
||||
return xpt.InterfaceIsType(iid_is)
|
||||
else:
|
||||
# void ptr
|
||||
return xpt.SimpleType(TypeMap['void'],
|
||||
pointer=True,
|
||||
reference=False)
|
||||
|
||||
raise Exception("Unknown type!")
|
||||
|
||||
def get_nsresult():
|
||||
return xpt.SimpleType(TypeMap['nsresult'])
|
||||
|
||||
def build_nsresult_param():
|
||||
return xpt.Param(get_nsresult())
|
||||
|
||||
def get_result_type(m):
|
||||
if not m.notxpcom:
|
||||
return get_nsresult()
|
||||
|
||||
return get_type(m.realtype, '')
|
||||
|
||||
def build_result_param(m):
|
||||
return xpt.Param(get_result_type(m))
|
||||
|
||||
def build_retval_param(m):
|
||||
type = get_type(m.realtype, 'out')
|
||||
if isDipperType(type.tag):
|
||||
# NB: The retval bit needs to be set here, contrary to what the
|
||||
# xpt spec says.
|
||||
return xpt.Param(type, in_=True, retval=True, dipper=True)
|
||||
return xpt.Param(type, in_=False, out=True, retval=True)
|
||||
|
||||
def build_attr_param(a, getter=False, setter=False):
|
||||
if not (getter or setter):
|
||||
raise Exception("Attribute param must be for a getter or a setter!")
|
||||
|
||||
type = get_type(a.realtype, getter and 'out' or 'in')
|
||||
if setter:
|
||||
return xpt.Param(type)
|
||||
else:
|
||||
if isDipperType(type.tag):
|
||||
# NB: The retval bit needs to be set here, contrary to what the
|
||||
# xpt spec says.
|
||||
return xpt.Param(type, in_=True, retval=True, dipper=True)
|
||||
return xpt.Param(type, in_=False, out=True, retval=True)
|
||||
|
||||
if iface.namemap is None:
|
||||
raise Exception("Interface was not resolved.")
|
||||
|
||||
consts = []
|
||||
methods = []
|
||||
|
||||
def build_const(c):
|
||||
consts.append(xpt.Constant(c.name, get_type(c.basetype, ''), c.getValue()))
|
||||
|
||||
def build_method(m):
|
||||
params = []
|
||||
|
||||
def build_param(p):
|
||||
def findattr(p, attr):
|
||||
if hasattr(p, attr) and getattr(p, attr):
|
||||
for i, param in enumerate(m.params):
|
||||
if param.name == getattr(p, attr):
|
||||
return i
|
||||
return None
|
||||
|
||||
iid_is = findattr(p, 'iid_is')
|
||||
size_is = findattr(p, 'size_is')
|
||||
|
||||
in_ = p.paramtype.count("in")
|
||||
out = p.paramtype.count("out")
|
||||
dipper = False
|
||||
type = get_type(p.realtype, p.paramtype, iid_is=iid_is, size_is=size_is)
|
||||
if out and isDipperType(type.tag):
|
||||
out = False
|
||||
dipper = True
|
||||
|
||||
return xpt.Param(type, in_, out, p.retval, p.shared, dipper, p.optional)
|
||||
|
||||
for p in m.params:
|
||||
params.append(build_param(p))
|
||||
|
||||
if not m.notxpcom and m.realtype.name != 'void':
|
||||
params.append(build_retval_param(m))
|
||||
|
||||
methods.append(xpt.Method(m.name, build_result_param(m), params,
|
||||
getter=False, setter=False, notxpcom=m.notxpcom,
|
||||
constructor=False, hidden=m.noscript,
|
||||
optargc=m.optional_argc,
|
||||
implicit_jscontext=m.implicit_jscontext))
|
||||
|
||||
def build_attr(a):
|
||||
# Write the getter
|
||||
methods.append(xpt.Method(a.name, build_nsresult_param(),
|
||||
[build_attr_param(a, getter=True)],
|
||||
getter=True, setter=False,
|
||||
constructor=False, hidden=a.noscript,
|
||||
optargc=False,
|
||||
implicit_jscontext=a.implicit_jscontext))
|
||||
|
||||
# And maybe the setter
|
||||
if not a.readonly:
|
||||
methods.append(xpt.Method(a.name, build_nsresult_param(),
|
||||
[build_attr_param(a, setter=True)],
|
||||
getter=False, setter=True,
|
||||
constructor=False, hidden=a.noscript,
|
||||
optargc=False,
|
||||
implicit_jscontext=a.implicit_jscontext))
|
||||
|
||||
for member in iface.members:
|
||||
if isinstance(member, xpidl.ConstMember):
|
||||
build_const(member)
|
||||
elif isinstance(member, xpidl.Attribute):
|
||||
build_attr(member)
|
||||
elif isinstance(member, xpidl.Method):
|
||||
build_method(member)
|
||||
elif isinstance(member, xpidl.CDATA):
|
||||
pass
|
||||
else:
|
||||
raise Exception("Unexpected interface member: %s" % member)
|
||||
|
||||
parent = None
|
||||
if iface.base:
|
||||
for i in ifaces:
|
||||
if i.name == iface.base:
|
||||
parent = i
|
||||
if not parent:
|
||||
parent = xpt.Interface(name=iface.base)
|
||||
ifaces.append(parent)
|
||||
|
||||
return xpt.Interface(iface.name, iface.attributes.uuid, methods=methods,
|
||||
constants=consts, resolved=True, parent=parent,
|
||||
scriptable=iface.attributes.scriptable,
|
||||
function=iface.attributes.function,
|
||||
builtinclass=iface.attributes.builtinclass,
|
||||
main_process_scriptable_only=iface.attributes.main_process_scriptable_only)
|
||||
|
||||
|
||||
def write_typelib(idl, fd, filename):
|
||||
""" Generate the typelib. """
|
||||
|
||||
# We only care about interfaces that are scriptable.
|
||||
ifaces = []
|
||||
for p in idl.productions:
|
||||
if p.kind == 'interface' and p.attributes.scriptable:
|
||||
ifaces.append(build_interface(p, ifaces))
|
||||
|
||||
typelib = xpt.Typelib(interfaces=ifaces)
|
||||
typelib.writefd(fd)
|
||||
|
||||
if __name__ == '__main__':
|
||||
from optparse import OptionParser
|
||||
o = OptionParser()
|
||||
o.add_option('-I', action='append', dest='incdirs', default=['.'],
|
||||
help="Directory to search for imported files")
|
||||
o.add_option('--cachedir', dest='cachedir', default=None,
|
||||
help="Directory in which to cache lex/parse tables.")
|
||||
o.add_option('-o', dest='outfile', default=None,
|
||||
help="Output file")
|
||||
o.add_option('-d', dest='depfile', default=None,
|
||||
help="Generate a make dependency file")
|
||||
o.add_option('--regen', action='store_true', dest='regen', default=False,
|
||||
help="Regenerate IDL Parser cache")
|
||||
options, args = o.parse_args()
|
||||
file = args[0] if args else None
|
||||
|
||||
if options.cachedir is not None:
|
||||
if not os.path.isdir(options.cachedir):
|
||||
os.mkdir(options.cachedir)
|
||||
sys.path.append(options.cachedir)
|
||||
|
||||
if options.regen:
|
||||
if options.cachedir is None:
|
||||
print >>sys.stderr, "--regen requires --cachedir"
|
||||
sys.exit(1)
|
||||
|
||||
p = xpidl.IDLParser(outputdir=options.cachedir, regen=True)
|
||||
sys.exit(0)
|
||||
|
||||
if options.depfile is not None and options.outfile is None:
|
||||
print >>sys.stderr, "-d requires -o"
|
||||
sys.exit(1)
|
||||
|
||||
if options.outfile is not None:
|
||||
outfd = open(options.outfile, 'wb')
|
||||
closeoutfd = True
|
||||
else:
|
||||
raise "typelib generation requires an output file"
|
||||
|
||||
p = xpidl.IDLParser(outputdir=options.cachedir)
|
||||
idl = p.parse(open(file).read(), filename=file)
|
||||
idl.resolve(options.incdirs, p)
|
||||
write_typelib(idl, outfd, file)
|
||||
|
||||
if closeoutfd:
|
||||
outfd.close()
|
||||
|
||||
if options.depfile is not None:
|
||||
depfd = open(options.depfile, 'w')
|
||||
deps = [dep.replace('\\', '/') for dep in idl.deps]
|
||||
|
||||
print >>depfd, "%s: %s" % (options.outfile, " ".join(deps))
|
||||
for dep in deps:
|
||||
print >>depfd, "%s:" % dep
|
||||
1465
xpcom/idl-parser/xpidl/xpidl.py
Normal file
1465
xpcom/idl-parser/xpidl/xpidl.py
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue