blob: c136c49d38071d92e841661fc64d0daf77bba8e6 [file] [log] [blame]
Chia-I Wufb2559d2014-08-01 11:19:52 +08001#!/usr/bin/env python3
Chia-I Wu701f3f62014-09-02 08:32:09 +08002#
Karl Schultz8e42f402016-02-02 19:32:33 -07003# Copyright (c) 2015-2016 The Khronos Group Inc.
4# Copyright (c) 2015-2016 Valve Corporation
5# Copyright (c) 2015-2016 LunarG, Inc.
6# Copyright (c) 2015-2016 Google Inc.
Chia-I Wu701f3f62014-09-02 08:32:09 +08007#
Jon Ashburn3ebf1252016-04-19 11:30:31 -06008# Licensed under the Apache License, Version 2.0 (the "License");
9# you may not use this file except in compliance with the License.
10# You may obtain a copy of the License at
Chia-I Wu701f3f62014-09-02 08:32:09 +080011#
Jon Ashburn3ebf1252016-04-19 11:30:31 -060012# http://www.apache.org/licenses/LICENSE-2.0
Chia-I Wu701f3f62014-09-02 08:32:09 +080013#
Jon Ashburn3ebf1252016-04-19 11:30:31 -060014# Unless required by applicable law or agreed to in writing, software
15# distributed under the License is distributed on an "AS IS" BASIS,
16# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17# See the License for the specific language governing permissions and
18# limitations under the License.
Chia-I Wu701f3f62014-09-02 08:32:09 +080019#
Courtney Goeltzenleuchter05559522015-10-30 11:14:30 -060020# Author: Chia-I Wu <olv@lunarg.com>
21# Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
22# Author: Jon Ashburn <jon@lunarg.com>
Mun, Gwan-gyeong82a244a2016-02-22 20:23:59 +090023# Author: Gwan-gyeong Mun <kk.moon@samsung.com>
Chia-I Wufb2559d2014-08-01 11:19:52 +080024
25import sys
26
Courtney Goeltzenleuchterf53c3cb2015-04-14 14:55:44 -060027import vulkan
Chia-I Wufb2559d2014-08-01 11:19:52 +080028
Chia-I Wu6cdaedb2015-01-05 12:55:13 +080029def generate_get_proc_addr_check(name):
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -060030 return " if (!%s || %s[0] != 'v' || %s[1] != 'k')\n" \
31 " return NULL;" % ((name,) * 3)
Chia-I Wu6cdaedb2015-01-05 12:55:13 +080032
Chia-I Wufb2559d2014-08-01 11:19:52 +080033class Subcommand(object):
34 def __init__(self, argv):
35 self.argv = argv
Courtney Goeltzenleuchterf53c3cb2015-04-14 14:55:44 -060036 self.headers = vulkan.headers
37 self.protos = vulkan.protos
Jamie Madilldbda66b2016-05-10 07:36:20 -070038 self.outfile = None
Chia-I Wufb2559d2014-08-01 11:19:52 +080039
40 def run(self):
Jamie Madilldbda66b2016-05-10 07:36:20 -070041 if self.outfile:
42 with open(self.outfile, "w") as outfile:
43 outfile.write(self.generate())
44 else:
45 print(self.generate())
Chia-I Wufb2559d2014-08-01 11:19:52 +080046
47 def generate(self):
48 copyright = self.generate_copyright()
49 header = self.generate_header()
50 body = self.generate_body()
51 footer = self.generate_footer()
52
53 contents = []
54 if copyright:
55 contents.append(copyright)
56 if header:
57 contents.append(header)
58 if body:
59 contents.append(body)
60 if footer:
61 contents.append(footer)
62
63 return "\n\n".join(contents)
64
65 def generate_copyright(self):
66 return """/* THIS FILE IS GENERATED. DO NOT EDIT. */
67
68/*
Karl Schultz8e42f402016-02-02 19:32:33 -070069 * Copyright (c) 2015-2016 The Khronos Group Inc.
70 * Copyright (c) 2015-2016 Valve Corporation
71 * Copyright (c) 2015-2016 LunarG, Inc.
Chia-I Wufb2559d2014-08-01 11:19:52 +080072 *
Jon Ashburn3ebf1252016-04-19 11:30:31 -060073 * Licensed under the Apache License, Version 2.0 (the "License");
74 * you may not use this file except in compliance with the License.
75 * You may obtain a copy of the License at
Chia-I Wufb2559d2014-08-01 11:19:52 +080076 *
Jon Ashburn3ebf1252016-04-19 11:30:31 -060077 * http://www.apache.org/licenses/LICENSE-2.0
Chia-I Wufb2559d2014-08-01 11:19:52 +080078 *
Jon Ashburn3ebf1252016-04-19 11:30:31 -060079 * Unless required by applicable law or agreed to in writing, software
80 * distributed under the License is distributed on an "AS IS" BASIS,
81 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
82 * See the License for the specific language governing permissions and
83 * limitations under the License.
Courtney Goeltzenleuchter05559522015-10-30 11:14:30 -060084 *
85 * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
Chia-I Wufb2559d2014-08-01 11:19:52 +080086 */"""
87
88 def generate_header(self):
Chia-I Wu6bdf0192014-09-13 13:36:06 +080089 return "\n".join(["#include <" + h + ">" for h in self.headers])
Chia-I Wufb2559d2014-08-01 11:19:52 +080090
91 def generate_body(self):
92 pass
93
94 def generate_footer(self):
95 pass
96
Chia-I Wu29271d72015-01-04 10:19:50 +080097class DispatchTableOpsSubcommand(Subcommand):
Mark Youngaa1aa3a2016-07-05 16:41:50 -060098 def __init__(self, argv):
99 self.argv = argv
100 self.headers = vulkan.headers_all
101 self.protos = vulkan.protos_all
102 self.outfile = None
103
Chia-I Wu29271d72015-01-04 10:19:50 +0800104 def run(self):
Jamie Madilldbda66b2016-05-10 07:36:20 -0700105 if len(self.argv) < 1:
Chia-I Wu29271d72015-01-04 10:19:50 +0800106 print("DispatchTableOpsSubcommand: <prefix> unspecified")
107 return
108
109 self.prefix = self.argv[0]
Jamie Madilldbda66b2016-05-10 07:36:20 -0700110
111 if len(self.argv) > 2:
112 print("DispatchTableOpsSubcommand: <prefix> [outfile]")
113 return
114
115 if len(self.argv) == 2:
116 self.outfile = self.argv[1]
117
Michael Lentine695f2c22015-09-09 12:39:13 -0700118 super(DispatchTableOpsSubcommand, self).run()
Chia-I Wu29271d72015-01-04 10:19:50 +0800119
120 def generate_header(self):
David Pinedo9316d3b2015-11-06 12:54:48 -0700121 return "\n".join(["#include <vulkan/vulkan.h>",
122 "#include <vulkan/vk_layer.h>",
Jon Ashburn1dd0a5c2015-05-04 09:16:41 -0600123 "#include <string.h>"])
Chia-I Wu29271d72015-01-04 10:19:50 +0800124
Jon Ashburn8fd08252015-05-28 16:25:02 -0600125 def _generate_init_dispatch(self, type):
Chia-I Wu29271d72015-01-04 10:19:50 +0800126 stmts = []
Jon Ashburn8c5cbcf2015-05-07 10:27:37 -0600127 func = []
128 if type == "device":
Jon Ashburn8fd08252015-05-28 16:25:02 -0600129 # GPA has to be first one and uses wrapped object
Mark Youngaa1aa3a2016-07-05 16:41:50 -0600130 stmts.append(" memset(table, 0, sizeof(*table));")
131 stmts.append(" // Core device function pointers")
132 stmts.append(" table->GetDeviceProcAddr = (PFN_vkGetDeviceProcAddr) gpa(device, \"vkGetDeviceProcAddr\");")
133
134 KHR_printed = False
135 EXT_printed = False
Johannes van Waverenaabf1fd2016-07-22 16:10:11 -0500136 Win32_printed = False
Mark Youngaa1aa3a2016-07-05 16:41:50 -0600137 XLIB_printed = False
138 XCB_printed = False
139 MIR_printed = False
140 WAY_printed = False
Johannes van Waverenaabf1fd2016-07-22 16:10:11 -0500141 Android_printed = False
Jon Ashburn8c5cbcf2015-05-07 10:27:37 -0600142 for proto in self.protos:
Mark Youngaa1aa3a2016-07-05 16:41:50 -0600143 if proto.name == "CreateInstance" or proto.name == "EnumerateInstanceExtensionProperties" or \
144 proto.name == "EnumerateInstanceLayerProperties" or proto.params[0].ty == "VkInstance" or \
145 proto.params[0].ty == "VkPhysicalDevice" or proto.name == "GetDeviceProcAddr":
Jon Ashburn95a77ba2015-05-15 15:09:35 -0600146 continue
Johannes van Waverenaabf1fd2016-07-22 16:10:11 -0500147 if Win32_printed and 'Win32' not in proto.name:
148 stmts.append("#endif // VK_USE_PLATFORM_WIN32_KHR")
149 Win32_printed = False
Mark Youngaa1aa3a2016-07-05 16:41:50 -0600150 if XLIB_printed and 'Xlib' not in proto.name:
151 stmts.append("#endif // VK_USE_PLATFORM_XLIB_KHR")
152 XLIB_printed = False
153 if XCB_printed and 'Xcb' not in proto.name:
154 stmts.append("#endif // VK_USE_PLATFORM_XCB_KHR")
155 XCB_printed = False
156 if MIR_printed and 'Mir' not in proto.name:
157 stmts.append("#endif // VK_USE_PLATFORM_MIR_KHR")
158 MIR_printed = False
159 if WAY_printed and 'Wayland' not in proto.name:
160 stmts.append("#endif // VK_USE_PLATFORM_WAYLAND_KHR")
161 WAY_printed = False
Johannes van Waverenaabf1fd2016-07-22 16:10:11 -0500162 if Android_printed and 'Android' not in proto.name:
163 stmts.append("#endif // VK_USE_PLATFORM_ANDROID_KHR")
164 Android_printed = False
165 if 'KHR' in proto.name and 'Win32' in proto.name:
166 if not Win32_printed:
167 stmts.append("#ifdef VK_USE_PLATFORM_WIN32_KHR")
168 Win32_printed = True
Mark Youngaa1aa3a2016-07-05 16:41:50 -0600169 if 'KHR' in proto.name and 'Xlib' in proto.name:
170 if not XLIB_printed:
171 stmts.append("#ifdef VK_USE_PLATFORM_XLIB_KHR")
172 XLIB_printed = True
173 if 'KHR' in proto.name and 'Xcb' in proto.name:
174 if not XCB_printed:
175 stmts.append("#ifdef VK_USE_PLATFORM_XCB_KHR")
176 XCB_printed = True
177 if 'KHR' in proto.name and 'Mir' in proto.name:
178 if not MIR_printed:
179 stmts.append("#ifdef VK_USE_PLATFORM_MIR_KHR")
180 MIR_printed = True
181 if 'KHR' in proto.name and 'Wayland' in proto.name:
182 if not WAY_printed:
183 stmts.append("#ifdef VK_USE_PLATFORM_WAYLAND_KHR")
184 WAY_printed = True
Johannes van Waverenaabf1fd2016-07-22 16:10:11 -0500185 if 'KHR' in proto.name and 'Android' in proto.name:
186 if not Android_printed:
187 stmts.append("#ifdef VK_USE_PLATFORM_ANDROID_KHR")
188 Android_printed = True
189 if 'KHR' in proto.name and not KHR_printed:
190 stmts.append(" // KHR device extension function pointers")
191 KHR_printed = True
192 if 'EXT' in proto.name and not EXT_printed:
193 stmts.append(" // EXT device extension function pointers")
194 EXT_printed = True
Mark Youngaa1aa3a2016-07-05 16:41:50 -0600195 stmts.append(" table->%s = (PFN_vk%s) gpa(device, \"vk%s\");" %
Chia-I Wu29271d72015-01-04 10:19:50 +0800196 (proto.name, proto.name, proto.name))
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700197 func.append("static inline void %s_init_device_dispatch_table(VkDevice device,"
Chia-I Wu29271d72015-01-04 10:19:50 +0800198 % self.prefix)
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700199 func.append("%s VkLayerDispatchTable *table,"
200 % (" " * len(self.prefix)))
201 func.append("%s PFN_vkGetDeviceProcAddr gpa)"
Jon Ashburn8c5cbcf2015-05-07 10:27:37 -0600202 % (" " * len(self.prefix)))
203 else:
Mark Youngaa1aa3a2016-07-05 16:41:50 -0600204 stmts.append(" memset(table, 0, sizeof(*table));")
205 stmts.append(" // Core instance function pointers")
206 stmts.append(" table->GetInstanceProcAddr = (PFN_vkGetInstanceProcAddr) gpa(instance, \"vkGetInstanceProcAddr\");")
207
208 KHR_printed = False
209 EXT_printed = False
Johannes van Waverenaabf1fd2016-07-22 16:10:11 -0500210 Win32_printed = False
Mark Youngaa1aa3a2016-07-05 16:41:50 -0600211 XLIB_printed = False
212 XCB_printed = False
213 MIR_printed = False
214 WAY_printed = False
Johannes van Waverenaabf1fd2016-07-22 16:10:11 -0500215 Android_printed = False
Jon Ashburn8c5cbcf2015-05-07 10:27:37 -0600216 for proto in self.protos:
Mark Youngaa1aa3a2016-07-05 16:41:50 -0600217 if proto.params[0].ty != "VkInstance" and proto.params[0].ty != "VkPhysicalDevice" or \
218 proto.name == "CreateDevice" or proto.name == "GetInstanceProcAddr":
Jon Ashburn8c5cbcf2015-05-07 10:27:37 -0600219 continue
Johannes van Waverenaabf1fd2016-07-22 16:10:11 -0500220 if Win32_printed and 'Win32' not in proto.name:
221 stmts.append("#endif // VK_USE_PLATFORM_WIN32_KHR")
222 Win32_printed = False
Mark Youngaa1aa3a2016-07-05 16:41:50 -0600223 if XLIB_printed and 'Xlib' not in proto.name:
224 stmts.append("#endif // VK_USE_PLATFORM_XLIB_KHR")
225 XLIB_printed = False
226 if XCB_printed and 'Xcb' not in proto.name:
227 stmts.append("#endif // VK_USE_PLATFORM_XCB_KHR")
228 XCB_printed = False
229 if MIR_printed and 'Mir' not in proto.name:
230 stmts.append("#endif // VK_USE_PLATFORM_MIR_KHR")
231 MIR_printed = False
232 if WAY_printed and 'Wayland' not in proto.name:
233 stmts.append("#endif // VK_USE_PLATFORM_WAYLAND_KHR")
234 WAY_printed = False
Johannes van Waverenaabf1fd2016-07-22 16:10:11 -0500235 if Android_printed and 'Android' not in proto.name:
236 stmts.append("#endif // VK_USE_PLATFORM_ANDROID_KHR")
237 Android_printed = False
238 if 'KHR' in proto.name and 'Win32' in proto.name:
239 if not Win32_printed:
240 stmts.append("#ifdef VK_USE_PLATFORM_WIN32_KHR")
241 Win32_printed = True
Mark Youngaa1aa3a2016-07-05 16:41:50 -0600242 if 'KHR' in proto.name and 'Xlib' in proto.name:
243 if not XLIB_printed:
244 stmts.append("#ifdef VK_USE_PLATFORM_XLIB_KHR")
245 XLIB_printed = True
246 if 'KHR' in proto.name and 'Xcb' in proto.name:
247 if not XCB_printed:
248 stmts.append("#ifdef VK_USE_PLATFORM_XCB_KHR")
249 XCB_printed = True
250 if 'KHR' in proto.name and 'Mir' in proto.name:
251 if not MIR_printed:
252 stmts.append("#ifdef VK_USE_PLATFORM_MIR_KHR")
253 MIR_printed = True
254 if 'KHR' in proto.name and 'Wayland' in proto.name:
255 if not WAY_printed:
256 stmts.append("#ifdef VK_USE_PLATFORM_WAYLAND_KHR")
257 WAY_printed = True
Johannes van Waverenaabf1fd2016-07-22 16:10:11 -0500258 if 'KHR' in proto.name and 'Android' in proto.name:
259 if not Android_printed:
260 stmts.append("#ifdef VK_USE_PLATFORM_ANDROID_KHR")
261 Android_printed = True
262 if 'KHR' in proto.name and not KHR_printed:
263 stmts.append(" // KHR instance extension function pointers")
264 KHR_printed = True
265 if 'EXT' in proto.name and not EXT_printed:
266 stmts.append(" // EXT instance extension function pointers")
267 EXT_printed = True
Mark Youngaa1aa3a2016-07-05 16:41:50 -0600268 stmts.append(" table->%s = (PFN_vk%s) gpa(instance, \"vk%s\");" %
269 (proto.name, proto.name, proto.name))
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700270 func.append("static inline void %s_init_instance_dispatch_table(" % self.prefix)
271 func.append("%s VkInstance instance," % (" " * len(self.prefix)))
272 func.append("%s VkLayerInstanceDispatchTable *table," % (" " * len(self.prefix)))
273 func.append("%s PFN_vkGetInstanceProcAddr gpa)" % (" " * len(self.prefix)))
Chia-I Wu29271d72015-01-04 10:19:50 +0800274 func.append("{")
Mark Youngaa1aa3a2016-07-05 16:41:50 -0600275 func.append("%s" % "\n".join(stmts))
Chia-I Wu29271d72015-01-04 10:19:50 +0800276 func.append("}")
277
278 return "\n".join(func)
279
Chia-I Wu29271d72015-01-04 10:19:50 +0800280 def generate_body(self):
Jon Ashburn8fd08252015-05-28 16:25:02 -0600281 body = [self._generate_init_dispatch("device"),
282 self._generate_init_dispatch("instance")]
Chia-I Wu29271d72015-01-04 10:19:50 +0800283
284 return "\n\n".join(body)
285
Chia-I Wu0a6644b2015-04-11 10:56:50 +0800286class WinDefFileSubcommand(Subcommand):
287 def run(self):
288 library_exports = {
289 "all": [],
290 "icd": [
Jon Ashburnf5e97542016-01-07 09:46:26 -0700291 "vk_icdGetInstanceProcAddr",
Chia-I Wu0a6644b2015-04-11 10:56:50 +0800292 ],
293 "layer": [
Jon Ashburn2919a012015-08-13 14:15:07 -0700294 "vkGetInstanceProcAddr",
295 "vkGetDeviceProcAddr",
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -0600296 "vkEnumerateInstanceLayerProperties",
297 "vkEnumerateInstanceExtensionProperties"
Chia-I Wu0a6644b2015-04-11 10:56:50 +0800298 ],
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700299 "layer_multi": [
Jon Ashburn2919a012015-08-13 14:15:07 -0700300 "multi2GetInstanceProcAddr",
301 "multi1GetDeviceProcAddr"
302 ]
Chia-I Wu0a6644b2015-04-11 10:56:50 +0800303 }
304
Jamie Madilldbda66b2016-05-10 07:36:20 -0700305 if len(self.argv) < 2 or len(self.argv) > 3 or self.argv[1] not in library_exports:
306 print("WinDefFileSubcommand: <library-name> {%s} [outfile]" %
Chia-I Wu0a6644b2015-04-11 10:56:50 +0800307 "|".join(library_exports.keys()))
308 return
309
310 self.library = self.argv[0]
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700311 if self.library == "VkLayer_multi":
312 self.exports = library_exports["layer_multi"]
Jon Ashburn2919a012015-08-13 14:15:07 -0700313 else:
314 self.exports = library_exports[self.argv[1]]
Chia-I Wu0a6644b2015-04-11 10:56:50 +0800315
Jamie Madilldbda66b2016-05-10 07:36:20 -0700316 if len(self.argv) == 3:
317 self.outfile = self.argv[2]
318
Jamie Madillc0018852016-04-04 11:20:24 -0400319 super(WinDefFileSubcommand, self).run()
Chia-I Wu0a6644b2015-04-11 10:56:50 +0800320
321 def generate_copyright(self):
322 return """; THIS FILE IS GENERATED. DO NOT EDIT.
323
324;;;; Begin Copyright Notice ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600325; Vulkan
Chia-I Wu0a6644b2015-04-11 10:56:50 +0800326;
Karl Schultz8e42f402016-02-02 19:32:33 -0700327; Copyright (c) 2015-2016 The Khronos Group Inc.
328; Copyright (c) 2015-2016 Valve Corporation
329; Copyright (c) 2015-2016 LunarG, Inc.
Chia-I Wu0a6644b2015-04-11 10:56:50 +0800330;
Jon Ashburn3ebf1252016-04-19 11:30:31 -0600331; Licensed under the Apache License, Version 2.0 (the "License");
332; you may not use this file except in compliance with the License.
333; You may obtain a copy of the License at
Chia-I Wu0a6644b2015-04-11 10:56:50 +0800334;
Jon Ashburn3ebf1252016-04-19 11:30:31 -0600335; http://www.apache.org/licenses/LICENSE-2.0
Chia-I Wu0a6644b2015-04-11 10:56:50 +0800336;
Jon Ashburn3ebf1252016-04-19 11:30:31 -0600337; Unless required by applicable law or agreed to in writing, software
338; distributed under the License is distributed on an "AS IS" BASIS,
339; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
340; See the License for the specific language governing permissions and
341; limitations under the License.
Courtney Goeltzenleuchterbdde0b22015-12-16 14:57:27 -0700342;
343; Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
Chia-I Wu0a6644b2015-04-11 10:56:50 +0800344;;;; End Copyright Notice ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"""
345
346 def generate_header(self):
347 return "; The following is required on Windows, for exporting symbols from the DLL"
348
349 def generate_body(self):
350 body = []
351
352 body.append("LIBRARY " + self.library)
353 body.append("EXPORTS")
354
Jon Ashburn2919a012015-08-13 14:15:07 -0700355 for proto in self.exports:
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700356 if self.library != "VkLayerSwapchain" or proto != "vkEnumerateInstanceExtensionProperties" and proto != "vkEnumerateInstanceLayerProperties":
Ian Elliott0b4d6242015-09-22 10:51:24 -0600357 body.append( proto)
Chia-I Wu0a6644b2015-04-11 10:56:50 +0800358
359 return "\n".join(body)
360
Chia-I Wufb2559d2014-08-01 11:19:52 +0800361def main():
Mun, Gwan-gyeong82a244a2016-02-22 20:23:59 +0900362 wsi = {
363 "Win32",
364 "Android",
365 "Xcb",
366 "Xlib",
367 "Wayland",
Petros Bantolas2b40be72016-04-15 11:02:59 +0100368 "Mir",
Johannes van Waverenaabf1fd2016-07-22 16:10:11 -0500369 "Display",
370 "AllPlatforms"
Mun, Gwan-gyeong82a244a2016-02-22 20:23:59 +0900371 }
Chia-I Wufb2559d2014-08-01 11:19:52 +0800372 subcommands = {
Chia-I Wu29271d72015-01-04 10:19:50 +0800373 "dispatch-table-ops": DispatchTableOpsSubcommand,
Chia-I Wu0a6644b2015-04-11 10:56:50 +0800374 "win-def-file": WinDefFileSubcommand,
Chia-I Wufb2559d2014-08-01 11:19:52 +0800375 }
376
Mun, Gwan-gyeong82a244a2016-02-22 20:23:59 +0900377 if len(sys.argv) < 3 or sys.argv[1] not in wsi or sys.argv[2] not in subcommands:
378 print("Usage: %s <wsi> <subcommand> [options]" % sys.argv[0])
Chia-I Wufb2559d2014-08-01 11:19:52 +0800379 print
380 print("Available sucommands are: %s" % " ".join(subcommands))
381 exit(1)
382
Mun, Gwan-gyeong82a244a2016-02-22 20:23:59 +0900383 subcmd = subcommands[sys.argv[2]](sys.argv[3:])
Chia-I Wufb2559d2014-08-01 11:19:52 +0800384 subcmd.run()
385
386if __name__ == "__main__":
387 main()