Bug 1772588 [wpt PR 34302] - [wpt] Add test for block-in-inline offsetParent., a...
[gecko.git] / ipc / ipdl / ipdl.py
blob07e043343ee6b8b2ce44d11f4856da9682076985
1 # This Source Code Form is subject to the terms of the Mozilla Public
2 # License, v. 2.0. If a copy of the MPL was not distributed with this
3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 from __future__ import print_function
6 from io import StringIO
7 import optparse
8 import os
9 import sys
10 from configparser import RawConfigParser
12 import ipdl
15 def log(minv, fmt, *args):
16 if _verbosity >= minv:
17 print(fmt % args)
20 # process command line
23 op = optparse.OptionParser(usage="ipdl.py [options] IPDLfiles...")
24 op.add_option(
25 "-I",
26 "--include",
27 dest="includedirs",
28 default=[],
29 action="append",
30 help="Additional directory to search for included protocol specifications",
32 op.add_option(
33 "-s",
34 "--sync-msg-list",
35 dest="syncMsgList",
36 default="sync-messages.ini",
37 help="Config file listing allowed sync messages",
39 op.add_option(
40 "-m",
41 "--msg-metadata",
42 dest="msgMetadata",
43 default="message-metadata.ini",
44 help="Predicted message sizes for reducing serialization malloc overhead.",
46 op.add_option(
47 "-v",
48 "--verbose",
49 dest="verbosity",
50 default=1,
51 action="count",
52 help="Verbose logging (specify -vv or -vvv for very verbose logging)",
54 op.add_option(
55 "-q",
56 "--quiet",
57 dest="verbosity",
58 action="store_const",
59 const=0,
60 help="Suppress logging output",
62 op.add_option(
63 "-d",
64 "--outheaders-dir",
65 dest="headersdir",
66 default=".",
67 help="""Directory into which C++ headers will be generated.
68 A protocol Foo in the namespace bar will cause the headers
69 dir/bar/Foo.h, dir/bar/FooParent.h, and dir/bar/FooParent.h
70 to be generated""",
72 op.add_option(
73 "-o",
74 "--outcpp-dir",
75 dest="cppdir",
76 default=".",
77 help="""Directory into which C++ sources will be generated
78 A protocol Foo in the namespace bar will cause the sources
79 cppdir/FooParent.cpp, cppdir/FooChild.cpp
80 to be generated""",
83 options, files = op.parse_args()
84 _verbosity = options.verbosity
85 syncMsgList = options.syncMsgList
86 msgMetadata = options.msgMetadata
87 headersdir = options.headersdir
88 cppdir = options.cppdir
89 includedirs = [os.path.abspath(incdir) for incdir in options.includedirs]
91 if not len(files):
92 op.error("No IPDL files specified")
94 ipcmessagestartpath = os.path.join(headersdir, "IPCMessageStart.h")
95 ipc_msgtype_name_path = os.path.join(cppdir, "IPCMessageTypeName.cpp")
97 log(2, 'Generated C++ headers will be generated relative to "%s"', headersdir)
98 log(2, 'Generated C++ sources will be generated in "%s"', cppdir)
100 allmessages = {}
101 allmessageprognames = []
102 allprotocols = []
105 def normalizedFilename(f):
106 if f == "-":
107 return "<stdin>"
108 return f
111 log(2, "Reading sync message list")
112 parser = RawConfigParser()
113 parser.read_file(open(options.syncMsgList))
114 syncMsgList = parser.sections()
116 for section in syncMsgList:
117 if not parser.get(section, "description"):
118 print("Error: Sync message %s lacks a description" % section, file=sys.stderr)
119 sys.exit(1)
121 # Read message metadata. Right now we only have 'segment_capacity'
122 # for the standard segment size used for serialization.
123 log(2, "Reading message metadata...")
124 msgMetadataConfig = RawConfigParser()
125 msgMetadataConfig.read_file(open(options.msgMetadata))
127 segmentCapacityDict = {}
128 for msgName in msgMetadataConfig.sections():
129 if msgMetadataConfig.has_option(msgName, "segment_capacity"):
130 capacity = msgMetadataConfig.get(msgName, "segment_capacity")
131 segmentCapacityDict[msgName] = capacity
133 # First pass: parse and type-check all protocols
134 for f in files:
135 log(2, os.path.basename(f))
136 filename = normalizedFilename(f)
137 if f == "-":
138 fd = sys.stdin
139 else:
140 fd = open(f)
142 specstring = fd.read()
143 fd.close()
145 ast = ipdl.parse(specstring, filename, includedirs=includedirs)
146 if ast is None:
147 print("Specification could not be parsed.", file=sys.stderr)
148 sys.exit(1)
150 log(2, "checking types")
151 if not ipdl.typecheck(ast):
152 print("Specification is not well typed.", file=sys.stderr)
153 sys.exit(1)
155 if not ipdl.checkSyncMessage(ast, syncMsgList):
156 print(
157 "Error: New sync IPC messages must be reviewed by an IPC peer and recorded in %s"
158 % options.syncMsgList,
159 file=sys.stderr,
160 ) # NOQA: E501
161 sys.exit(1)
163 if not ipdl.checkFixedSyncMessages(parser):
164 # Errors have alraedy been printed to stderr, just exit
165 sys.exit(1)
167 # Second pass: generate code
168 for f in files:
169 # Read from parser cache
170 filename = normalizedFilename(f)
171 ast = ipdl.parse(None, filename, includedirs=includedirs)
172 ipdl.gencxx(filename, ast, headersdir, cppdir, segmentCapacityDict)
174 if ast.protocol:
175 allmessages[ast.protocol.name] = ipdl.genmsgenum(ast)
176 allprotocols.append(ast.protocol.name)
177 # e.g. PContent::RequestMemoryReport (not prefixed or suffixed.)
178 for md in ast.protocol.messageDecls:
179 allmessageprognames.append("%s::%s" % (md.namespace, md.decl.progname))
181 allprotocols.sort()
183 # Check if we have undefined message names in segmentCapacityDict.
184 # This is a fool-proof of the 'message-metadata.ini' file.
185 undefinedMessages = set(segmentCapacityDict.keys()) - set(allmessageprognames)
186 if len(undefinedMessages) > 0:
187 print("Error: Undefined message names in message-metadata.ini:", file=sys.stderr)
188 print(undefinedMessages, file=sys.stderr)
189 sys.exit(1)
191 ipcmsgstart = StringIO()
193 print(
195 // CODE GENERATED by ipdl.py. Do not edit.
197 #ifndef IPCMessageStart_h
198 #define IPCMessageStart_h
200 enum IPCMessageStart {
201 """,
202 file=ipcmsgstart,
205 for name in allprotocols:
206 print(" %sMsgStart," % name, file=ipcmsgstart)
208 print(
210 LastMsgIndex
213 static_assert(LastMsgIndex <= 65536, "need to update IPC_MESSAGE_MACRO");
215 #endif // ifndef IPCMessageStart_h
216 """,
217 file=ipcmsgstart,
220 ipc_msgtype_name = StringIO()
221 print(
223 // CODE GENERATED by ipdl.py. Do not edit.
224 #include <cstdint>
226 #include "mozilla/ipc/ProtocolUtils.h"
227 #include "IPCMessageStart.h"
229 using std::uint32_t;
231 namespace {
233 enum IPCMessages {
234 """,
235 file=ipc_msgtype_name,
238 for protocol in sorted(allmessages.keys()):
239 for (msg, num) in allmessages[protocol].idnums:
240 if num:
241 print(" %s = %s," % (msg, num), file=ipc_msgtype_name)
242 elif not msg.endswith("End"):
243 print(" %s__%s," % (protocol, msg), file=ipc_msgtype_name)
245 print(
249 } // anonymous namespace
251 namespace IPC {
253 const char* StringFromIPCMessageType(uint32_t aMessageType)
255 switch (aMessageType) {
256 """,
257 file=ipc_msgtype_name,
260 for protocol in sorted(allmessages.keys()):
261 for (msg, num) in allmessages[protocol].idnums:
262 if num or msg.endswith("End"):
263 continue
264 print(
266 case %s__%s:
267 return "%s::%s";"""
268 % (protocol, msg, protocol, msg),
269 file=ipc_msgtype_name,
272 print(
274 case DATA_PIPE_CLOSED_MESSAGE_TYPE:
275 return "DATA_PIPE_CLOSED_MESSAGE";
276 case DATA_PIPE_BYTES_CONSUMED_MESSAGE_TYPE:
277 return "DATA_PIPE_BYTES_CONSUMED_MESSAGE";
278 case ACCEPT_INVITE_MESSAGE_TYPE:
279 return "ACCEPT_INVITE_MESSAGE";
280 case REQUEST_INTRODUCTION_MESSAGE_TYPE:
281 return "REQUEST_INTRODUCTION_MESSAGE";
282 case INTRODUCE_MESSAGE_TYPE:
283 return "INTRODUCE_MESSAGE";
284 case BROADCAST_MESSAGE_TYPE:
285 return "BROADCAST_MESSAGE";
286 case EVENT_MESSAGE_TYPE:
287 return "EVENT_MESSAGE";
288 case IMPENDING_SHUTDOWN_MESSAGE_TYPE:
289 return "IMPENDING_SHUTDOWN";
290 case BUILD_IDS_MATCH_MESSAGE_TYPE:
291 return "BUILD_IDS_MATCH_MESSAGE";
292 case BUILD_ID_MESSAGE_TYPE:
293 return "BUILD_ID_MESSAGE";
294 case CHANNEL_OPENED_MESSAGE_TYPE:
295 return "CHANNEL_OPENED_MESSAGE";
296 case SHMEM_DESTROYED_MESSAGE_TYPE:
297 return "SHMEM_DESTROYED_MESSAGE";
298 case SHMEM_CREATED_MESSAGE_TYPE:
299 return "SHMEM_CREATED_MESSAGE";
300 case GOODBYE_MESSAGE_TYPE:
301 return "GOODBYE_MESSAGE";
302 case CANCEL_MESSAGE_TYPE:
303 return "CANCEL_MESSAGE";
304 default:
305 return "<unknown IPC msg name>";
309 } // namespace IPC
311 namespace mozilla {
312 namespace ipc {
314 const char* ProtocolIdToName(IPCMessageStart aId) {
315 switch (aId) {
316 """,
317 file=ipc_msgtype_name,
320 for name in allprotocols:
321 print(" case %sMsgStart:" % name, file=ipc_msgtype_name)
322 print(' return "%s";' % name, file=ipc_msgtype_name)
324 print(
326 default:
327 return "<unknown protocol id>";
331 } // namespace ipc
332 } // namespace mozilla
333 """,
334 file=ipc_msgtype_name,
337 ipdl.writeifmodified(ipcmsgstart.getvalue(), ipcmessagestartpath)
338 ipdl.writeifmodified(ipc_msgtype_name.getvalue(), ipc_msgtype_name_path)