--- a/ipc/Makefile.in
+++ b/ipc/Makefile.in
@@ -36,12 +36,16 @@
DEPTH = ..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
-DIRS += testshell
+# NB: chromium/ and glue/ are in tier_xpcom
+
+# tier_gecko:
+DIRS += ipdl testshell
+
TOOL_DIRS = app
include $(topsrcdir)/config/rules.mk
--- a/ipc/glue/IPCMessageUtils.h
+++ b/ipc/glue/IPCMessageUtils.h
@@ -40,20 +40,16 @@
#define __IPC_GLUE_IPCMESSAGEUTILS_H__
#include "chrome/common/ipc_message_utils.h"
#include "prtypes.h"
#include "nsStringGlue.h"
#include "nsTArray.h"
-#include "IPCMessageStart.h"
-
-COMPILE_ASSERT(LastMsgIndex <= 64, need_to_update_IPC_MESSAGE_MACRO);
-
namespace IPC {
template <>
struct ParamTraits<nsACString>
{
typedef nsACString paramType;
static void Write(Message* aMsg, const paramType& aParam)
--- a/ipc/ipdl/Makefile.in
+++ b/ipc/ipdl/Makefile.in
@@ -39,37 +39,68 @@ topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
GARBAGE_DIRS += _ipdlheaders
GARBAGE += ipdl_lextab.py ipdl_yacctab.py
-include $(topsrcdir)/config/rules.mk
+MODULE = ipdlgen
+LIBRARY_NAME = mozipdlgen_s
+FORCE_STATIC_LIB = 1
+LIBXUL_LIBRARY = 1
+EXPORT_LIBRARY = 1
+##-----------------------------------------------------------------------------
+## When you add IPDL files to a source directory, list the directory here.
+##
IPDLDIRS = \
dom/plugins \
dom/ipc \
netwerk/ipc \
netwerk/protocol/http/src \
ipc/ipdl/test/cxx \
ipc/testshell \
$(NULL)
+##-----------------------------------------------------------------------------
+
+ifdef MOZ_IPDL_TESTS
+DIRS += test
+endif
vpath %.ipdl $(topsrcdir)
define ADD_IPDLDIR
include $(topsrcdir)/$(IPDLDIR)/ipdl.mk
ALL_IPDLSRCS += $$(IPDLSRCS:%=$(IPDLDIR)/%)
+PROTOCOLS += $$(IPDLSRCS)
endef
ALL_IPDLSRCS :=
+PROTOCOLS :=
$(foreach IPDLDIR,$(IPDLDIRS),$(eval $(ADD_IPDLDIR)))
+
+CPPSRCS = \
+ $(PROTOCOLS:%.ipdl=%Parent.cpp) \
+ $(PROTOCOLS:%.ipdl=%Child.cpp) \
+ $(NULL)
+
+LOCAL_INCLUDES += -I$(DEPTH)/ipc/ipdl/_ipdlheaders
+
+
+include $(topsrcdir)/config/config.mk
+include $(topsrcdir)/ipc/chromium/chromium-config.mk
+include $(topsrcdir)/config/rules.mk
+
+
+# NB: the IPDL compiler manages .ipdl-->.h/.cpp dependencies itself,
+# which is why we don't have explicit .h/.cpp targets here
export:: $(ALL_IPDLSRCS)
- $(PYTHON) $(topsrcdir)/config/pythonpath.py \
- -I$(topsrcdir)/other-licenses/ply \
- $(srcdir)/ipdl.py \
- -d _ipdlheaders \
- $(IPDLDIRS:%=-I$(topsrcdir)/%) \
+ $(PYTHON) $(topsrcdir)/config/pythonpath.py \
+ -I$(topsrcdir)/other-licenses/ply \
+ $(srcdir)/ipdl.py \
+ --outheaders-dir=_ipdlheaders \
+ --outcpp-dir=. \
+ $(IPDLDIRS:%=-I$(topsrcdir)/%) \
$^
--- a/ipc/ipdl/ipdl.py
+++ b/ipc/ipdl/ipdl.py
@@ -37,35 +37,46 @@ import ipdl
def log(minv, fmt, *args):
if _verbosity >= minv:
print >>sys.stderr, fmt % args
# process command line
op = optparse.OptionParser(usage='ipdl.py [options] IPDLfiles...')
-op.add_option('-d', '--output-dir', dest='outputdir', default='.',
- help='Directory in which to put generated headers')
op.add_option('-I', '--include', dest='includedirs', default=[ ],
action='append',
help='Additional directory to search for included protocol specifications')
op.add_option('-v', '--verbose', dest='verbosity', default=1, action='count',
help='Verbose logging (specify -vv or -vvv for very verbose logging)')
op.add_option('-q', '--quiet', dest='verbosity', action='store_const', const=0,
help="Suppress logging output")
+op.add_option('-d', '--outheaders-dir', dest='headersdir', default='.',
+ help="""Director into which C++ headers will be generated.
+A protocol Foo in the namespace bar will cause the headers
+ dir/bar/Foo.h, dir/bar/FooParent.h, and dir/bar/FooParent.h
+to be generated""")
+op.add_option('-o', '--outcpp-dir', dest='cppdir', default='.',
+ help="""Director into which C++ sources will be generated
+A protocol Foo in the namespace bar will cause the sources
+ cppdir/FooParent.cpp, cppdir/FooChild.cpp
+to be generated""")
+
options, files = op.parse_args()
_verbosity = options.verbosity
-codedir = options.outputdir
+headersdir = options.headersdir
+cppdir = options.cppdir
includedirs = [ os.path.abspath(incdir) for incdir in options.includedirs ]
if not len(files):
op.error("No IPDL files specified")
-log(1, 'Generated headers will be placed in "%s"', codedir)
+log(1, 'Generated C++ headers will be generated relative to "%s"', headersdir)
+log(1, 'Generated C++ sources will be generated relative to "%s"', cppdir)
allprotocols = []
for f in files:
log(1, 'Parsing specification %s', f)
if f == '-':
fd = sys.stdin
filename = '<stdin>'
@@ -87,30 +98,37 @@ for f in files:
if not ipdl.typecheck(ast):
print >>sys.stderr, 'Specification is not well typed.'
sys.exit(1)
if _verbosity > 2:
log(3, ' pretty printed code:')
ipdl.genipdl(ast, codedir)
- ipdl.gencxx(ast, codedir)
+ ipdl.gencxx(filename, ast, headersdir, cppdir)
allprotocols.sort()
ipcmsgstart = StringIO()
print >>ipcmsgstart, """
// CODE GENERATED by ipdl.py. Do not edit.
+#ifndef IPCMessageStart_h
+#define IPCMessageStart_h
+
enum IPCMessageStart {
"""
for name in allprotocols:
print >>ipcmsgstart, " %s," % name
print >>ipcmsgstart, """
LastMsgIndex
};
+
+COMPILE_ASSERT(LastMsgIndex <= 64, need_to_update_IPC_MESSAGE_MACRO);
+
+#endif // ifndef IPCMessageStart_h
"""
ipdl.writeifmodified(ipcmsgstart.getvalue(),
- os.path.join(codedir, 'IPCMessageStart.h'))
+ os.path.join(headersdir, 'IPCMessageStart.h'))
--- a/ipc/ipdl/ipdl/__init__.py
+++ b/ipc/ipdl/ipdl/__init__.py
@@ -37,39 +37,53 @@ from cStringIO import StringIO
from ipdl.cgen import IPDLCodeGen
from ipdl.lower import LowerToCxx
from ipdl.parser import Parser
from ipdl.type import TypeCheck
from ipdl.cxx.cgen import CxxCodeGen
+
def parse(specstring, filename='/stdin', includedirs=[ ], errout=sys.stderr):
'''Return an IPDL AST if parsing was successful. Print errors to |errout|
if it is not.'''
return Parser().parse(specstring, os.path.abspath(filename), includedirs, errout)
+
def typecheck(ast, errout=sys.stderr):
'''Return True iff |ast| is well typed. Print errors to |errout| if
it is not.'''
return TypeCheck().check(ast, errout)
-def gencxx(ast, outdir):
- for hdr in LowerToCxx().lower(ast):
- file = os.path.join(
- outdir,
- *([ns.name for ns in ast.protocol.namespaces] + [hdr.name]))
+
+def gencxx(ipdlfilename, ast, outheadersdir, outcppdir):
+ headers, cpps = LowerToCxx().lower(ast)
+ def resolveHeader(hdr):
+ return [
+ hdr,
+ os.path.join(
+ outheadersdir,
+ *([ns.name for ns in ast.protocol.namespaces] + [hdr.name]))
+ ]
+ def resolveCpp(cpp):
+ return [ cpp, os.path.join(outcppdir, cpp.name) ]
+
+ for ast, filename in ([ resolveHeader(hdr) for hdr in headers ]
+ + [ resolveCpp(cpp) for cpp in cpps ]):
tempfile = StringIO()
- CxxCodeGen(tempfile).cgen(hdr)
- writeifmodified(tempfile.getvalue(), file)
+ CxxCodeGen(tempfile).cgen(ast)
+ writeifmodified(tempfile.getvalue(), filename)
+
def genipdl(ast, outdir):
return IPDLCodeGen().cgen(ast)
+
def writeifmodified(contents, file):
dir = os.path.dirname(file)
os.path.exists(dir) or os.makedirs(dir)
oldcontents = None
if os.path.exists(file):
fd = open(file, 'rb')
oldcontents = fd.read()
--- a/ipc/ipdl/ipdl/builtin.py
+++ b/ipc/ipdl/ipdl/builtin.py
@@ -62,13 +62,14 @@ Types = (
'nsCString',
)
Includes = (
'base/basictypes.h',
'prtime.h',
'nscore.h',
+ 'IPCMessageStart.h',
'IPC/IPCMessageUtils.h',
'nsStringGlue.h',
'nsTArray.h',
'mozilla/ipc/ProtocolUtils.h',
)
--- a/ipc/ipdl/ipdl/cxx/ast.py
+++ b/ipc/ipdl/ipdl/cxx/ast.py
@@ -72,16 +72,21 @@ class Visitor:
tdef.fromtype.accept(self)
def visitForwardDecl(self, fd):
pass
def visitDecl(self, decl):
decl.type.accept(self)
+ def visitParam(self, param):
+ self.visitDecl(param)
+ if param.default is not None:
+ param.default.accept(self)
+
def visitClass(self, cls):
for inherit in cls.inherits:
inherit.accept(self)
self.visitBlock(cls)
def visitInherit(self, inh):
pass
@@ -393,16 +398,24 @@ class Decl(Node):
assert isinstance(name, str)
Node.__init__(self)
self.type = type
self.name = name
def __deepcopy__(self, memo):
return Decl(copy.deepcopy(self.type, memo), self.name)
+class Param(Decl):
+ def __init__(self, type, name, default=None):
+ Decl.__init__(self, type, name)
+ self.default = default
+ def __deepcopy__(self, memo):
+ return Param(copy.deepcopy(self.type, memo), self.name,
+ copy.deepcopy(self.default, memo))
+
##------------------------------
# class stuff
class Class(Block):
def __init__(self, name, inherits=[ ],
interface=0, abstract=0, final=0,
specializes=None, struct=0):
assert not (interface and abstract)
assert not (abstract and final)
@@ -481,16 +494,21 @@ class ConstructorDefn(MethodDefn):
def __init__(self, decl, memberinits=[ ]):
MethodDefn.__init__(self, decl)
self.memberinits = memberinits
class DestructorDecl(MethodDecl):
def __init__(self, name, virtual=0):
MethodDecl.__init__(self, name, params=[ ], ret=None,
virtual=virtual)
+
+ def __deepcopy__(self, memo):
+ return DestructorDecl(self.name, self.virtual)
+
+
class DestructorDefn(MethodDefn):
def __init__(self, decl): MethodDefn.__init__(self, decl)
##------------------------------
# expressions
class ExprVar(Node):
def __init__(self, name):
assert isinstance(name, str)
--- a/ipc/ipdl/ipdl/cxx/cgen.py
+++ b/ipc/ipdl/ipdl/cxx/cgen.py
@@ -131,16 +131,22 @@ class CxxCodeGen(CodePrinter, Visitor):
if d.name:
self.write(' '+ d.name)
if isinstance(d.type, TypeArray):
self.write('[')
d.type.nmemb.accept(self)
self.write(']')
+ def visitParam(self, p):
+ self.visitDecl(p)
+ if p.default is not None:
+ self.write(' = ')
+ p.default.accept(self)
+
def visitClass(self, c):
if c.specializes is not None:
self.printdentln('template<>')
if c.struct:
self.printdent('struct')
else:
self.printdent('class')
@@ -253,17 +259,22 @@ class CxxCodeGen(CodePrinter, Visitor):
self.dedent()
self.printdentln('}')
def visitDestructorDecl(self, dd):
if dd.virtual:
self.write('virtual ')
- self.write('~'+ dd.name +'()')
+
+ # hack alert
+ parts = dd.name.split('::')
+ parts[-1] = '~'+ parts[-1]
+
+ self.write('::'.join(parts) +'()')
def visitDestructorDefn(self, dd):
self.printdent()
dd.decl.accept(self)
self.println()
self.printdentln('{')
self.indent()
--- a/ipc/ipdl/ipdl/lower.py
+++ b/ipc/ipdl/ipdl/lower.py
@@ -43,47 +43,54 @@ from ipdl.type import TypeVisitor
# this code will remain off until the chromium base lib is replaced
EMIT_LOGGING_CODE = ('win32' == sys.platform)
##-----------------------------------------------------------------------------
## "Public" interface to lowering
##
class LowerToCxx:
def lower(self, tu):
- '''returns a list of File representing the lowered form of |tu|'''
+ '''returns |[ header: File ], [ cpp : File ]| representing the
+lowered form of |tu|'''
# annotate the AST with IPDL/C++ IR-type stuff used later
tu.accept(_DecorateWithCxxStuff())
pname = tu.protocol.name
pheader = File(pname +'.h')
_GenerateProtocolHeader().lower(tu, pheader)
- parentheader = File(pname +'Parent.h')
- _GenerateProtocolParentHeader().lower(tu, pname+'Parent', parentheader)
-
- childheader = File(pname +'Child.h')
- _GenerateProtocolChildHeader().lower(tu, pname+'Child', childheader)
-
- return pheader, parentheader, childheader
+ parentheader, parentcpp = File(pname +'Parent.h'), File(pname +'Parent.cpp')
+ _GenerateProtocolParentCode().lower(
+ tu, pname+'Parent', parentheader, parentcpp)
+
+ childheader, childcpp = File(pname +'Child.h'), File(pname +'Child.cpp')
+ _GenerateProtocolChildCode().lower(
+ tu, pname+'Child', childheader, childcpp)
+
+ return [ pheader, parentheader, childheader ], [ parentcpp, childcpp ]
##-----------------------------------------------------------------------------
## Helper code
##
_NULL_ACTOR_ID = ExprLiteral.ZERO
_FREED_ACTOR_ID = ExprLiteral.ONE
class _struct: pass
-def _protocolHeaderBaseFilename(p):
+def _protocolHeaderName(p, side=''):
+ if side: side = side.title()
+ base = p.name + side
+
+
pfx = '/'.join([ ns.name for ns in p.namespaces ])
- if pfx: return pfx +'/'+ p.name
- else: return p.name
+ if pfx: return pfx +'/'+ base
+ else: return base
def _includeGuardMacroName(headerfile):
return re.sub(r'[./]', '_', headerfile.name)
def _includeGuardStart(headerfile):
guard = _includeGuardMacroName(headerfile)
return [ CppDirective('ifndef', guard),
CppDirective('define', guard) ]
@@ -351,17 +358,19 @@ def _killProcess(pid):
args=[ pid,
# XXX this is meaningless on POSIX
ExprVar('base::PROCESS_END_KILLED_BY_USER'),
ExprLiteral.FALSE ])
# Results that IPDL-generated code returns back to *Channel code.
# Users never see these
class _Result:
- Type = Type('Result')
+ @staticmethod
+ def Type():
+ return Type('Result')
Processed = ExprVar('MsgProcessed')
NotKnown = ExprVar('MsgNotKnown')
NotAllowed = ExprVar('MsgNotAllowed')
PayloadError = ExprVar('MsgPayloadError')
RouteError = ExprVar('MsgRouteError')
ValuError = ExprVar('MsgValueError') # [sic]
@@ -2265,121 +2274,192 @@ class _FindFriends(ipdl.ast.Visitor):
for param in md.inParams:
for actor in ipdl.type.iteractortypes(param.type):
yield actor
for ret in md.outParams:
for actor in ipdl.type.iteractortypes(ret.type):
yield actor
-class _GenerateProtocolActorHeader(ipdl.ast.Visitor):
+class _GenerateProtocolActorCode(ipdl.ast.Visitor):
def __init__(self, myside):
self.side = myside # "parent" or "child"
self.prettyside = myside.title()
self.clsname = None
self.protocol = None
- self.file = None
+ self.hdrfile = None
+ self.cppfile = None
self.ns = None
self.cls = None
self.includedActorTypedefs = [ ]
-
- def lower(self, tu, clsname, cxxHeaderFile):
+ self.protocolCxxIncludes = [ ]
+
+ def lower(self, tu, clsname, cxxHeaderFile, cxxFile):
self.clsname = clsname
- self.file = cxxHeaderFile
+ self.hdrfile = cxxHeaderFile
+ self.cppfile = cxxFile
tu.accept(self)
+ def standardTypedefs(self):
+ return [
+ Typedef(Type('IPC::Message'), 'Message'),
+ Typedef(Type(self.protocol.channelName()), 'Channel'),
+ Typedef(Type(self.protocol.fqListenerName()), 'ChannelListener'),
+ Typedef(Type('base::ProcessHandle'), 'ProcessHandle')
+ ]
+
+
def visitTranslationUnit(self, tu):
- f = self.file
-
- f.addthing(Whitespace('''//
+ self.protocol = tu.protocol
+
+ hf = self.hdrfile
+ cf = self.cppfile
+
+ disclaimer = Whitespace('''//
// Automatically generated by ipdlc.
// Edit at your own risk
//
-'''))
- f.addthings(_includeGuardStart(f))
- f.addthings([
- Whitespace.NL,
- CppDirective(
- 'include',
- '"'+ _protocolHeaderBaseFilename(tu.protocol) +'.h"') ])
-
- self.protocol = tu.protocol
+''')
+ # make the C++ header
+ hf.addthings(
+ [ disclaimer ]
+ + _includeGuardStart(hf)
+ +[
+ Whitespace.NL,
+ CppDirective(
+ 'include',
+ '"'+ _protocolHeaderName(tu.protocol) +'.h"')
+ ])
for pinc in tu.protocolIncludes:
pinc.accept(self)
+ # this generates the actor's full impl in self.cls
tu.protocol.accept(self)
- f.addthing(Whitespace.NL)
- f.addthings(_includeGuardEnd(f))
+ clsdecl, clsdefn = _ClassDeclDefn().split(self.cls)
+
+ # XXX damn C++ ... return types in the method defn aren't in
+ # class scope
+ for stmt in clsdefn.stmts:
+ if isinstance(stmt, MethodDefn):
+ if stmt.decl.ret and stmt.decl.ret.name == 'Result':
+ stmt.decl.ret.name = clsdecl.name +'::'+ stmt.decl.ret.name
+
+ def makeNamespace(p, file):
+ if 0 == len(p.namespaces):
+ return file
+ ns = Namespace(p.namespaces[-1].name)
+ outerns = _putInNamespaces(ns, p.namespaces[:-1])
+ file.addthing(outerns)
+ return ns
+
+ hdrns = makeNamespace(self.protocol, self.hdrfile)
+ hdrns.addstmts([
+ Whitespace.NL,
+ Whitespace.NL,
+ clsdecl,
+ Whitespace.NL,
+ Whitespace.NL
+ ])
+
+ self.hdrfile.addthings(
+ ([
+ Whitespace.NL,
+ CppDirective('if', '0') ])
+ + _GenerateSkeletonImpl(
+ _actorName(self.protocol.name, self.side)[1:],
+ self.protocol.namespaces).fromclass(self.cls)
+ +([
+ CppDirective('endif', '// if 0'),
+ Whitespace.NL ])
+ + _includeGuardEnd(hf))
+
+ # make the .cpp file
+ cf.addthings((
+ [ disclaimer,
+ Whitespace.NL,
+ CppDirective(
+ 'include',
+ '"'+ _protocolHeaderName(self.protocol, self.side) +'.h"'),
+ Whitespace.NL
+ ]
+ + self.protocolCxxIncludes
+ + [ Whitespace.NL ]
+ + self.standardTypedefs()
+ + self.includedActorTypedefs
+ + tu.protocol.decl.cxxtypedefs
+ + [ Whitespace.NL ]))
+
+ cppns = makeNamespace(self.protocol, cf)
+ cppns.addstmts([
+ Whitespace.NL,
+ Whitespace.NL,
+ clsdefn,
+ Whitespace.NL,
+ Whitespace.NL
+ ])
def visitProtocolInclude(self, pi):
ip = pi.tu.protocol
- if self.protocol.decl.type.isManagerOf(ip.decl.type):
- self.file.addthing(
- CppDirective(
- 'include',
- '"%s%s.h"'% (_protocolHeaderBaseFilename(ip),
- self.prettyside)))
+ self.hdrfile.addthings([
+ _makeForwardDecl(ip.decl.type, self.side),
+ Whitespace.NL
+ ])
+ self.protocolCxxIncludes.append(
+ CppDirective(
+ 'include',
+ '"%s.h"'% (_protocolHeaderName(ip, self.side))))
if ip.decl.fullname is not None:
self.includedActorTypedefs.append(Typedef(
Type(_actorName(ip.decl.fullname, self.prettyside)),
_actorName(ip.decl.shortname, self.prettyside)))
def visitProtocol(self, p):
- self.file.addthings([
+ self.hdrfile.addthings([
CppDirective('ifdef', 'DEBUG'),
CppDirective('include', '"prenv.h"'),
CppDirective('endif', '// DEBUG')
])
self.protocol = p
# FIXME: all actors impl Iface for now
if p.decl.type.isManager() or 1:
- self.file.addthing(CppDirective('include', '"base/id_map.h"'))
-
- self.file.addthings([
+ self.hdrfile.addthing(CppDirective('include', '"base/id_map.h"'))
+
+ self.hdrfile.addthings([
CppDirective('include', '"'+ p.channelHeaderFile() +'"'),
Whitespace.NL ])
inherits = [ Inherit(Type(p.fqListenerName())) ]
if p.decl.type.isManager():
inherits.append(Inherit(p.managerCxxType()))
self.cls = Class(self.clsname, inherits=inherits, abstract=True)
friends = _FindFriends().findFriends(p.decl.type)
if p.decl.type.isManaged():
friends.add(p.decl.type.manager)
for friend in friends:
- self.file.addthings([
+ self.hdrfile.addthings([
Whitespace.NL,
_makeForwardDecl(friend, self.prettyside),
Whitespace.NL
])
self.cls.addstmts([
FriendClassDecl(_actorName(friend.fullname(),
self.prettyside)),
Whitespace.NL ])
- # construct the namespace into which we'll stick all our decls
- if 0 == len(p.namespaces):
- self.ns = self.file
- else:
- self.ns = Namespace(p.namespaces[-1].name)
- outerns = _putInNamespaces(self.ns, p.namespaces[:-1])
- self.file.addthing(outerns)
- self.ns.addstmts([ Whitespace.NL, Whitespace.NL ])
-
self.cls.addstmt(Label.PROTECTED)
for typedef in p.cxxTypedefs():
self.cls.addstmt(typedef)
for typedef in self.includedActorTypedefs:
self.cls.addstmt(typedef)
self.cls.addstmt(Whitespace.NL)
# interface methods that the concrete subclass has to impl
@@ -2415,24 +2495,21 @@ class _GenerateProtocolActorHeader(ipdl.
defaultRecv.addstmt(StmtReturn(ExprLiteral.TRUE))
self.cls.addstmt(defaultRecv)
else:
recvDecl.pure = 1
self.cls.addstmt(StmtDecl(recvDecl))
self.cls.addstmt(Whitespace.NL)
- self.cls.addstmts([
- Label.PRIVATE,
- Typedef(Type('IPC::Message'), 'Message'),
- Typedef(Type(p.channelName()), 'Channel'),
- Typedef(Type(p.fqListenerName()), 'ChannelListener'),
- Typedef(Type('base::ProcessHandle'), 'ProcessHandle'),
- Whitespace.NL,
- ])
+ self.cls.addstmts((
+ [ Label.PRIVATE ]
+ + self.standardTypedefs()
+ + [ Whitespace.NL ]
+ ))
self.cls.addstmt(Label.PUBLIC)
# Actor()
ctor = ConstructorDefn(ConstructorDecl(self.clsname))
if p.decl.type.isToplevel():
ctor.memberinits = [
ExprMemberInit(p.channelVar(), [
ExprCall(ExprVar('ALLOW_THIS_IN_INITIALIZER_LIST'),
@@ -2462,18 +2539,19 @@ class _GenerateProtocolActorHeader(ipdl.
aThreadVar = ExprVar('aThread')
processvar = ExprVar('aOtherProcess')
openmeth = MethodDefn(
MethodDecl(
'Open',
params=[ Decl(Type('Channel::Transport', ptr=True),
aTransportVar.name),
Decl(Type('ProcessHandle'), processvar.name),
- Decl(Type('MessageLoop', ptr=True),
- aThreadVar.name +' = 0') ],
+ Param(Type('MessageLoop', ptr=True),
+ aThreadVar.name,
+ default=ExprLiteral.NULL) ],
ret=Type.BOOL))
openmeth.addstmts([
StmtExpr(ExprAssn(p.otherProcessVar(), processvar)),
StmtReturn(ExprCall(ExprSelect(p.channelVar(), '.', 'Open'),
[ aTransportVar, aThreadVar ]))
])
self.cls.addstmts([
@@ -2525,17 +2603,17 @@ class _GenerateProtocolActorHeader(ipdl.
def makeHandlerMethod(name, switch, hasReply, dispatches=0):
params = [ Decl(Type('Message', const=1, ref=1), msgvar.name) ]
if hasReply:
params.append(Decl(Type('Message', ref=1, ptr=1),
replyvar.name))
method = MethodDefn(MethodDecl(name, virtual=True,
- params=params, ret=_Result.Type))
+ params=params, ret=_Result.Type()))
if dispatches:
routevar = ExprVar('__route')
routedecl = StmtDecl(
Decl(_actorIdType(), routevar.name),
init=ExprCall(ExprSelect(msgvar, '.', 'routing_id')))
routeif = StmtIf(ExprBinary(
ExprVar('MSG_ROUTING_CONTROL'), '!=', routevar))
@@ -2644,27 +2722,16 @@ class _GenerateProtocolActorHeader(ipdl.
])
if p.usesShmem():
self.cls.addstmts([
StmtDecl(Decl(Type('IDMap', T=_rawShmemType()),
p.shmemMapVar().name)),
StmtDecl(Decl(_shmemIdType(), p.lastShmemIdVar().name))
])
- self.ns.addstmts([ self.cls, Whitespace.NL, Whitespace.NL ])
-
- # generate skeleton implementation of abstract actor class
- self.file.addthing(CppDirective('if', '0'))
-
- genskeleton = _GenerateSkeletonImpl()
- genskeleton.fromclass(self.cls)
- self.file.addthings(genskeleton.stuff)
-
- self.file.addthing(CppDirective('endif', '// if 0'))
-
def implementManagerIface(self):
p = self.protocol
routedvar = ExprVar('aRouted')
idvar = ExprVar('aId')
listenertype = Type('ChannelListener', ptr=1)
register = MethodDefn(MethodDecl(
@@ -3433,61 +3500,94 @@ class _GenerateProtocolActorHeader(ipdl.
actorname = _actorName(self.protocol.name, self.side)
return _ifLogging([
StmtExpr(ExprCall(
ExprSelect(msgptr, '->', 'Log'),
args=[ ExprLiteral.String('['+ actorname +'] '+ pfx),
ExprVar('stderr') ])) ])
-class _GenerateProtocolParentHeader(_GenerateProtocolActorHeader):
+class _GenerateProtocolParentCode(_GenerateProtocolActorCode):
def __init__(self):
- _GenerateProtocolActorHeader.__init__(self, 'parent')
+ _GenerateProtocolActorCode.__init__(self, 'parent')
def sendsMessage(self, md):
return not md.decl.type.isIn()
def receivesMessage(self, md):
return md.decl.type.isInout() or md.decl.type.isIn()
-class _GenerateProtocolChildHeader(_GenerateProtocolActorHeader):
+class _GenerateProtocolChildCode(_GenerateProtocolActorCode):
def __init__(self):
- _GenerateProtocolActorHeader.__init__(self, 'child')
+ _GenerateProtocolActorCode.__init__(self, 'child')
def sendsMessage(self, md):
return not md.decl.type.isOut()
def receivesMessage(self, md):
return md.decl.type.isInout() or md.decl.type.isOut()
##-----------------------------------------------------------------------------
-## Bonus (inessential) passes
+## Utility passes
##
+class _ClassDeclDefn:
+ def split(self, cls):
+ """Warning: destructively splits |cls|!"""
+ defns = Block()
+
+ for i, stmt in enumerate(cls.stmts):
+ if isinstance(stmt, MethodDefn):
+ decl, defn = self.splitMethodDefn(stmt, cls.name)
+ cls.stmts[i] = StmtDecl(decl)
+ defns.addstmts([ defn, Whitespace.NL ])
+
+ return cls, defns
+
+ def splitMethodDefn(self, md, clsname):
+ saveddecl = deepcopy(md.decl)
+ md.decl.name = (clsname +'::'+ md.decl.name)
+ md.decl.virtual = 0
+ md.decl.static = 0
+ for param in md.decl.params:
+ if isinstance(param, Param):
+ param.default = None
+ return saveddecl, md
+
+
+# XXX this is tantalizingly similar to _SplitDeclDefn, but just
+# different enough that I don't see the need to define
+# _GenerateSkeleton in terms of that
class _GenerateSkeletonImpl(Visitor):
- def __init__(self, name='ActorImpl'):
+ def __init__(self, name, namespaces):
self.name = name
- self.stuff = [ ]
self.cls = None
- self.methodimpls = [ ]
+ self.namespaces = namespaces
+ self.methodimpls = Block()
def fromclass(self, cls):
cls.accept(self)
- self.stuff.append(Whitespace('''
+
+ nsclass = _putInNamespaces(self.cls, self.namespaces)
+ nsmethodimpls = _putInNamespaces(self.methodimpls, self.namespaces)
+
+ return [
+ Whitespace('''
//-----------------------------------------------------------------------------
// Skeleton implementation of abstract actor class
-'''))
- self.stuff.append(Whitespace('// Header file contents\n'))
- self.stuff.append(self.cls)
-
- self.stuff.append(Whitespace.NL)
- self.stuff.append(Whitespace('\n// C++ file contents\n'))
- self.stuff.extend(self.methodimpls)
+'''),
+ Whitespace('// Header file contents\n'),
+ nsclass,
+ Whitespace.NL,
+ Whitespace('\n// C++ file contents\n'),
+ nsmethodimpls
+ ]
+
def visitClass(self, cls):
self.cls = Class(self.name, inherits=[ Inherit(Type(cls.name)) ])
Visitor.visitClass(self, cls)
def visitMethodDecl(self, md):
if not md.pure:
return
@@ -3516,13 +3616,12 @@ class _GenerateSkeletonImpl(Visitor):
StmtDecl(DestructorDecl(self.name, virtual=1)))
# FIXME/cjones: hack!
dtor = DestructorDefn(ConstructorDecl(self.implname('~' +self.name)))
dtor.addstmt(StmtExpr(ExprCall(ExprVar( 'MOZ_COUNT_DTOR'),
[ ExprVar(self.name) ])))
self.addmethodimpl(dtor)
def addmethodimpl(self, impl):
- self.methodimpls.append(impl)
- self.methodimpls.append(Whitespace.NL)
+ self.methodimpls.addstmts([ impl, Whitespace.NL ])
def implname(self, method):
return self.name +'::'+ method
new file mode 100644
--- /dev/null
+++ b/ipc/ipdl/test/cxx/IPDLUnitTestTypes.h
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
+/* ***** 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 Mozilla IPC.
+ *
+ * The Initial Developer of the Original Code is
+ * The Mozilla Foundation
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Chris Jones <jones.chris.g@gmail.com>.
+ *
+ * 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 ***** */
+
+#ifndef mozilla__ipdltest_IPDLUnitTestTypes_h
+#define mozilla__ipdltest_IPDLUnitTestTypes_h
+
+
+namespace mozilla {
+namespace _ipdltest {
+
+struct DirtyRect
+{
+ int x; int y; int w; int h;
+};
+
+}
+}
+
+namespace IPC {
+template<>
+struct ParamTraits<mozilla::_ipdltest::DirtyRect>
+{
+ typedef mozilla::_ipdltest::DirtyRect paramType;
+ static void Write(Message* aMsg, const paramType& aParam) {
+ WriteParam(aMsg, aParam.x);
+ WriteParam(aMsg, aParam.y);
+ WriteParam(aMsg, aParam.w);
+ WriteParam(aMsg, aParam.h);
+ }
+ static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+ {
+ return (ReadParam(aMsg, aIter, &aResult->x) &&
+ ReadParam(aMsg, aIter, &aResult->y) &&
+ ReadParam(aMsg, aIter, &aResult->w) &&
+ ReadParam(aMsg, aIter, &aResult->h));
+ }
+};
+}
+
+
+#endif // ifndef mozilla__ipdltest_IPDLUnitTestTypes_h
--- a/ipc/ipdl/test/cxx/Makefile.in
+++ b/ipc/ipdl/test/cxx/Makefile.in
@@ -44,16 +44,17 @@ include $(DEPTH)/config/autoconf.mk
TOOL_DIRS += app
MODULE = ipdlunittest
EXPORTS_NAMESPACES = mozilla/_ipdltest
EXPORTS_mozilla/_ipdltest = \
IPDLUnitTests.h \
IPDLUnitTestThreadChild.h \
+ IPDLUnitTestTypes.h \
$(NULL)
LIBRARY_NAME = $(MODULE)_s
LIBXUL_LIBRARY = 1
FORCE_STATIC_LIB = 1
EXPORT_LIBRARY = 1
# Please keep these organized in the order "easy"-to-"hard"
@@ -73,17 +74,16 @@ GENTESTER := $(srcdir)/genIPDLUnitTests.
CPPSRCS = \
IPDLUnitTests.cpp \
IPDLUnitTestSubprocess.cpp \
IPDLUnitTestThreadChild.cpp \
$(IPDLTESTSRCS) \
$(NULL)
-
include $(topsrcdir)/config/config.mk
include $(topsrcdir)/ipc/chromium/chromium-config.mk
include $(topsrcdir)/config/rules.mk
RUNIPDLTEST := $(RUN_TEST_PROGRAM) $(DEPTH)/dist/bin/ipdlunittest$(BIN_SUFFIX)
--- a/toolkit/library/libxul-config.mk
+++ b/toolkit/library/libxul-config.mk
@@ -91,16 +91,17 @@ LOCAL_INCLUDES += -I$(topsrcdir)/widget/
endif
# dependent libraries
ifdef MOZ_IPC
STATIC_LIBS += \
domipc_s \
domplugins_s \
mozipc_s \
+ mozipdlgen_s \
chromium_s \
ipcshell_s \
gfxipc_s \
$(NULL)
ifdef MOZ_IPDL_TESTS
STATIC_LIBS += ipdlunittest_s
endif
--- a/toolkit/toolkit-tiers.mk
+++ b/toolkit/toolkit-tiers.mk
@@ -169,20 +169,16 @@ tier_gecko_dirs += \
ifdef MOZ_UNIVERSALCHARDET
tier_gecko_dirs += extensions/universalchardet
endif
ifdef ACCESSIBILITY
tier_gecko_dirs += accessible
endif
-ifdef MOZ_IPDL_TESTS
-tier_gecko_dirs += ipc/ipdl/test
-endif
-
#
# tier "toolkit" - xpfe & toolkit
#
# The division of "gecko" and "toolkit" is somewhat arbitrary, and related
# to history where "gecko" wasn't forked between seamonkey/firefox but
# "toolkit" was.
#
--- a/xpcom/build.mk
+++ b/xpcom/build.mk
@@ -39,10 +39,10 @@ TIERS += xpcom
ifdef NS_TRACE_MALLOC
tier_xpcom_dirs = tools/trace-malloc/lib
endif
tier_xpcom_dirs += xpcom
ifdef MOZ_IPC
-tier_xpcom_dirs += ipc/ipdl ipc/chromium ipc/glue
+tier_xpcom_dirs += ipc/chromium ipc/glue
endif