1COPYRIGHT=u""" 2/* Copyright © 2015-2021 Intel Corporation 3 * Copyright © 2021 Collabora, Ltd. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice (including the next 13 * paragraph) shall be included in all copies or substantial portions of the 14 * Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 * IN THE SOFTWARE. 23 */ 24""" 25 26import argparse 27import os 28import re 29from collections import namedtuple 30import xml.etree.ElementTree as et 31 32from mako.template import Template 33 34# Mesa-local imports must be declared in meson variable 35# '{file_without_suffix}_depend_files'. 36from vk_entrypoints import EntrypointParam, get_entrypoints_from_xml 37from vk_extensions import filter_api, get_all_required 38 39# These have hand-typed implementations in vk_cmd_enqueue.c 40MANUAL_COMMANDS = [ 41 # This script doesn't know how to copy arrays in structs in arrays 42 'CmdPushDescriptorSetKHR', 43 44 # The size of the elements is specified in a stride param 45 'CmdDrawMultiEXT', 46 'CmdDrawMultiIndexedEXT', 47 48 # The VkPipelineLayout object could be released before the command is 49 # executed 50 'CmdBindDescriptorSets', 51] 52 53NO_ENQUEUE_COMMANDS = [ 54 # pData's size cannot be calculated from the xml 55 'CmdPushConstants2KHR', 56 'CmdPushDescriptorSet2KHR', 57 'CmdPushDescriptorSetWithTemplate2KHR', 58 'CmdPushDescriptorSetWithTemplateKHR', 59 60 # These don't return void 61 'CmdSetPerformanceMarkerINTEL', 62 'CmdSetPerformanceStreamMarkerINTEL', 63 'CmdSetPerformanceOverrideINTEL', 64] 65 66TEMPLATE_H = Template(COPYRIGHT + """\ 67/* This file generated from ${filename}, don't edit directly. */ 68 69#pragma once 70 71#include "util/list.h" 72 73#define VK_PROTOTYPES 74#include <vulkan/vulkan_core.h> 75#ifdef VK_ENABLE_BETA_EXTENSIONS 76#include <vulkan/vulkan_beta.h> 77#endif 78 79#ifdef __cplusplus 80extern "C" { 81#endif 82 83struct vk_device_dispatch_table; 84 85struct vk_cmd_queue { 86 const VkAllocationCallbacks *alloc; 87 struct list_head cmds; 88}; 89 90enum vk_cmd_type { 91% for c in commands: 92% if c.guard is not None: 93#ifdef ${c.guard} 94% endif 95 ${to_enum_name(c.name)}, 96% if c.guard is not None: 97#endif // ${c.guard} 98% endif 99% endfor 100}; 101 102extern const char *vk_cmd_queue_type_names[]; 103extern size_t vk_cmd_queue_type_sizes[]; 104 105% for c in commands: 106% if len(c.params) <= 1: # Avoid "error C2016: C requires that a struct or union have at least one member" 107<% continue %> 108% endif 109% if c.guard is not None: 110#ifdef ${c.guard} 111% endif 112struct ${to_struct_name(c.name)} { 113% for p in c.params[1:]: 114 ${to_field_decl(p.decl)}; 115% endfor 116}; 117% if c.guard is not None: 118#endif // ${c.guard} 119% endif 120% endfor 121 122struct vk_cmd_queue_entry; 123 124/* this ordering must match vk_cmd_queue_entry */ 125struct vk_cmd_queue_entry_base { 126 struct list_head cmd_link; 127 enum vk_cmd_type type; 128 void *driver_data; 129 void (*driver_free_cb)(struct vk_cmd_queue *queue, 130 struct vk_cmd_queue_entry *cmd); 131}; 132 133/* this ordering must match vk_cmd_queue_entry_base */ 134struct vk_cmd_queue_entry { 135 struct list_head cmd_link; 136 enum vk_cmd_type type; 137 void *driver_data; 138 void (*driver_free_cb)(struct vk_cmd_queue *queue, 139 struct vk_cmd_queue_entry *cmd); 140 union { 141% for c in commands: 142% if len(c.params) <= 1: 143<% continue %> 144% endif 145% if c.guard is not None: 146#ifdef ${c.guard} 147% endif 148 struct ${to_struct_name(c.name)} ${to_struct_field_name(c.name)}; 149% if c.guard is not None: 150#endif // ${c.guard} 151% endif 152% endfor 153 } u; 154}; 155 156% for c in commands: 157% if c.name in manual_commands or c.name in no_enqueue_commands: 158<% continue %> 159% endif 160% if c.guard is not None: 161#ifdef ${c.guard} 162% endif 163 VkResult vk_enqueue_${to_underscore(c.name)}(struct vk_cmd_queue *queue 164% for p in c.params[1:]: 165 , ${p.decl} 166% endfor 167 ); 168% if c.guard is not None: 169#endif // ${c.guard} 170% endif 171 172% endfor 173 174void vk_free_queue(struct vk_cmd_queue *queue); 175 176static inline void 177vk_cmd_queue_init(struct vk_cmd_queue *queue, VkAllocationCallbacks *alloc) 178{ 179 queue->alloc = alloc; 180 list_inithead(&queue->cmds); 181} 182 183static inline void 184vk_cmd_queue_reset(struct vk_cmd_queue *queue) 185{ 186 vk_free_queue(queue); 187 list_inithead(&queue->cmds); 188} 189 190static inline void 191vk_cmd_queue_finish(struct vk_cmd_queue *queue) 192{ 193 vk_free_queue(queue); 194 list_inithead(&queue->cmds); 195} 196 197void vk_cmd_queue_execute(struct vk_cmd_queue *queue, 198 VkCommandBuffer commandBuffer, 199 const struct vk_device_dispatch_table *disp); 200 201#ifdef __cplusplus 202} 203#endif 204""") 205 206TEMPLATE_C = Template(COPYRIGHT + """ 207/* This file generated from ${filename}, don't edit directly. */ 208 209#include "${header}" 210 211#define VK_PROTOTYPES 212#include <vulkan/vulkan_core.h> 213#ifdef VK_ENABLE_BETA_EXTENSIONS 214#include <vulkan/vulkan_beta.h> 215#endif 216 217#include "vk_alloc.h" 218#include "vk_cmd_enqueue_entrypoints.h" 219#include "vk_command_buffer.h" 220#include "vk_dispatch_table.h" 221#include "vk_device.h" 222 223const char *vk_cmd_queue_type_names[] = { 224% for c in commands: 225% if c.guard is not None: 226#ifdef ${c.guard} 227% endif 228 "${to_enum_name(c.name)}", 229% if c.guard is not None: 230#endif // ${c.guard} 231% endif 232% endfor 233}; 234 235size_t vk_cmd_queue_type_sizes[] = { 236% for c in commands: 237% if c.guard is not None: 238#ifdef ${c.guard} 239% endif 240% if len(c.params) > 1: 241 sizeof(struct ${to_struct_name(c.name)}) + 242% endif 243 sizeof(struct vk_cmd_queue_entry_base), 244% if c.guard is not None: 245#endif // ${c.guard} 246% endif 247% endfor 248}; 249 250% for c in commands: 251% if c.guard is not None: 252#ifdef ${c.guard} 253% endif 254static void 255vk_free_${to_underscore(c.name)}(struct vk_cmd_queue *queue, 256${' ' * len('vk_free_' + to_underscore(c.name) + '(')}\\ 257struct vk_cmd_queue_entry *cmd) 258{ 259 if (cmd->driver_free_cb) 260 cmd->driver_free_cb(queue, cmd); 261 else 262 vk_free(queue->alloc, cmd->driver_data); 263% for p in c.params[1:]: 264% if p.len: 265 vk_free(queue->alloc, (${remove_suffix(p.decl.replace("const", ""), p.name)})cmd->u.${to_struct_field_name(c.name)}.${to_field_name(p.name)}); 266% elif '*' in p.decl: 267 ${get_struct_free(c, p, types)} 268% endif 269% endfor 270 vk_free(queue->alloc, cmd); 271} 272 273% if c.name not in manual_commands and c.name not in no_enqueue_commands: 274VkResult vk_enqueue_${to_underscore(c.name)}(struct vk_cmd_queue *queue 275% for p in c.params[1:]: 276, ${p.decl} 277% endfor 278) 279{ 280 struct vk_cmd_queue_entry *cmd = vk_zalloc(queue->alloc, vk_cmd_queue_type_sizes[${to_enum_name(c.name)}], 8, 281 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 282 if (!cmd) return VK_ERROR_OUT_OF_HOST_MEMORY; 283 284 cmd->type = ${to_enum_name(c.name)}; 285 \ 286 <% need_error_handling = False %> 287% for p in c.params[1:]: 288% if p.len: 289 if (${p.name}) { 290 ${get_array_copy(c, p)} 291 }\ 292 <% need_error_handling = True %> 293% elif '[' in p.decl: 294 memcpy(cmd->u.${to_struct_field_name(c.name)}.${to_field_name(p.name)}, ${p.name}, 295 sizeof(*${p.name}) * ${get_array_len(p)}); 296% elif p.type == "void": 297 cmd->u.${to_struct_field_name(c.name)}.${to_field_name(p.name)} = (${remove_suffix(p.decl.replace("const", ""), p.name)}) ${p.name}; 298% elif '*' in p.decl: 299 ${get_struct_copy("cmd->u.%s.%s" % (to_struct_field_name(c.name), to_field_name(p.name)), p.name, p.type, 'sizeof(%s)' % p.type, types)}\ 300 <% need_error_handling = True %> 301% else: 302 cmd->u.${to_struct_field_name(c.name)}.${to_field_name(p.name)} = ${p.name}; 303% endif 304% endfor 305 306 list_addtail(&cmd->cmd_link, &queue->cmds); 307 return VK_SUCCESS; 308 309% if need_error_handling: 310err: 311 if (cmd) 312 vk_free_${to_underscore(c.name)}(queue, cmd); 313 return VK_ERROR_OUT_OF_HOST_MEMORY; 314% endif 315} 316% endif 317% if c.guard is not None: 318#endif // ${c.guard} 319% endif 320 321% endfor 322 323void 324vk_free_queue(struct vk_cmd_queue *queue) 325{ 326 struct vk_cmd_queue_entry *tmp, *cmd; 327 LIST_FOR_EACH_ENTRY_SAFE(cmd, tmp, &queue->cmds, cmd_link) { 328 switch(cmd->type) { 329% for c in commands: 330% if c.guard is not None: 331#ifdef ${c.guard} 332% endif 333 case ${to_enum_name(c.name)}: 334 vk_free_${to_underscore(c.name)}(queue, cmd); 335 break; 336% if c.guard is not None: 337#endif // ${c.guard} 338% endif 339% endfor 340 } 341 } 342} 343 344void 345vk_cmd_queue_execute(struct vk_cmd_queue *queue, 346 VkCommandBuffer commandBuffer, 347 const struct vk_device_dispatch_table *disp) 348{ 349 list_for_each_entry(struct vk_cmd_queue_entry, cmd, &queue->cmds, cmd_link) { 350 switch (cmd->type) { 351% for c in commands: 352% if c.guard is not None: 353#ifdef ${c.guard} 354% endif 355 case ${to_enum_name(c.name)}: 356 disp->${c.name}(commandBuffer 357% for p in c.params[1:]: 358 , cmd->u.${to_struct_field_name(c.name)}.${to_field_name(p.name)}\\ 359% endfor 360 ); 361 break; 362% if c.guard is not None: 363#endif // ${c.guard} 364% endif 365% endfor 366 default: unreachable("Unsupported command"); 367 } 368 } 369} 370 371% for c in commands: 372% if c.name in no_enqueue_commands: 373/* TODO: Generate vk_cmd_enqueue_${c.name}() */ 374<% continue %> 375% endif 376 377% if c.guard is not None: 378#ifdef ${c.guard} 379% endif 380<% assert c.return_type == 'void' %> 381 382% if c.name in manual_commands: 383/* vk_cmd_enqueue_${c.name}() is hand-typed in vk_cmd_enqueue.c */ 384% else: 385VKAPI_ATTR void VKAPI_CALL 386vk_cmd_enqueue_${c.name}(${c.decl_params()}) 387{ 388 VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, commandBuffer); 389 390 if (vk_command_buffer_has_error(cmd_buffer)) 391 return; 392% if len(c.params) == 1: 393 VkResult result = vk_enqueue_${to_underscore(c.name)}(&cmd_buffer->cmd_queue); 394% else: 395 VkResult result = vk_enqueue_${to_underscore(c.name)}(&cmd_buffer->cmd_queue, 396 ${c.call_params(1)}); 397% endif 398 if (unlikely(result != VK_SUCCESS)) 399 vk_command_buffer_set_error(cmd_buffer, result); 400} 401% endif 402 403VKAPI_ATTR void VKAPI_CALL 404vk_cmd_enqueue_unless_primary_${c.name}(${c.decl_params()}) 405{ 406 VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, commandBuffer); 407 408 if (cmd_buffer->level == VK_COMMAND_BUFFER_LEVEL_PRIMARY) { 409 const struct vk_device_dispatch_table *disp = 410 cmd_buffer->base.device->command_dispatch_table; 411 412 disp->${c.name}(${c.call_params()}); 413 } else { 414 vk_cmd_enqueue_${c.name}(${c.call_params()}); 415 } 416} 417% if c.guard is not None: 418#endif // ${c.guard} 419% endif 420% endfor 421""") 422 423def remove_prefix(text, prefix): 424 if text.startswith(prefix): 425 return text[len(prefix):] 426 return text 427 428def remove_suffix(text, suffix): 429 if text.endswith(suffix): 430 return text[:-len(suffix)] 431 return text 432 433def to_underscore(name): 434 return remove_prefix(re.sub('([A-Z]+)', r'_\1', name).lower(), '_') 435 436def to_struct_field_name(name): 437 return to_underscore(name).replace('cmd_', '') 438 439def to_field_name(name): 440 return remove_prefix(to_underscore(name).replace('cmd_', ''), 'p_') 441 442def to_field_decl(decl): 443 if 'const*' in decl: 444 decl = decl.replace('const*', '*') 445 else: 446 decl = decl.replace('const ', '') 447 [decl, name] = decl.rsplit(' ', 1) 448 return decl + ' ' + to_field_name(name) 449 450def to_enum_name(name): 451 return "VK_%s" % to_underscore(name).upper() 452 453def to_struct_name(name): 454 return "vk_%s" % to_underscore(name) 455 456def get_array_len(param): 457 return param.decl[param.decl.find("[") + 1:param.decl.find("]")] 458 459def get_array_copy(command, param): 460 field_name = "cmd->u.%s.%s" % (to_struct_field_name(command.name), to_field_name(param.name)) 461 if param.type == "void": 462 field_size = "1" 463 else: 464 field_size = "sizeof(*%s)" % field_name 465 allocation = "%s = vk_zalloc(queue->alloc, %s * (%s), 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);\n if (%s == NULL) goto err;\n" % (field_name, field_size, param.len, field_name) 466 copy = "memcpy((void*)%s, %s, %s * (%s));" % (field_name, param.name, field_size, param.len) 467 return "%s\n %s" % (allocation, copy) 468 469def get_array_member_copy(struct, src_name, member): 470 field_name = "%s->%s" % (struct, member.name) 471 if member.len == "struct-ptr": 472 field_size = "sizeof(*%s)" % (field_name) 473 else: 474 field_size = "sizeof(*%s) * %s->%s" % (field_name, struct, member.len) 475 allocation = "%s = vk_zalloc(queue->alloc, %s, 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);\n if (%s == NULL) goto err;\n" % (field_name, field_size, field_name) 476 copy = "memcpy((void*)%s, %s->%s, %s);" % (field_name, src_name, member.name, field_size) 477 return "if (%s->%s) {\n %s\n %s\n}\n" % (src_name, member.name, allocation, copy) 478 479def get_pnext_member_copy(struct, src_type, member, types, level): 480 if not types[src_type].extended_by: 481 return "" 482 field_name = "%s->%s" % (struct, member.name) 483 pnext_decl = "const VkBaseInStructure *pnext = %s;" % field_name 484 case_stmts = "" 485 for type in types[src_type].extended_by: 486 guard_pre_stmt = "" 487 guard_post_stmt = "" 488 if type.guard is not None: 489 guard_pre_stmt = "#ifdef %s" % type.guard 490 guard_post_stmt = "#endif" 491 case_stmts += """ 492%s 493 case %s: 494 %s 495 break; 496%s 497 """ % (guard_pre_stmt, type.enum, get_struct_copy(field_name, "pnext", type.name, "sizeof(%s)" % type.name, types, level), guard_post_stmt) 498 return """ 499 %s 500 if (pnext) { 501 switch ((int32_t)pnext->sType) { 502 %s 503 } 504 } 505 """ % (pnext_decl, case_stmts) 506 507def get_struct_copy(dst, src_name, src_type, size, types, level=0): 508 global tmp_dst_idx 509 global tmp_src_idx 510 511 allocation = "%s = vk_zalloc(queue->alloc, %s, 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);\n if (%s == NULL) goto err;\n" % (dst, size, dst) 512 copy = "memcpy((void*)%s, %s, %s);" % (dst, src_name, size) 513 514 level += 1 515 tmp_dst = "%s *tmp_dst%d = (void *) %s; (void) tmp_dst%d;" % (src_type, level, dst, level) 516 tmp_src = "%s *tmp_src%d = (void *) %s; (void) tmp_src%d;" % (src_type, level, src_name, level) 517 518 member_copies = "" 519 if src_type in types: 520 for member in types[src_type].members: 521 if member.len and member.len != 'null-terminated': 522 member_copies += get_array_member_copy("tmp_dst%d" % level, "tmp_src%d" % level, member) 523 elif member.name == 'pNext': 524 member_copies += get_pnext_member_copy("tmp_dst%d" % level, src_type, member, types, level) 525 526 null_assignment = "%s = NULL;" % dst 527 if_stmt = "if (%s) {" % src_name 528 indent = " " * level 529 return "%s\n %s\n %s\n %s\n %s\n %s\n%s} else {\n %s\n%s}" % (if_stmt, allocation, copy, tmp_dst, tmp_src, member_copies, indent, null_assignment, indent) 530 531def get_struct_free(command, param, types): 532 field_name = "cmd->u.%s.%s" % (to_struct_field_name(command.name), to_field_name(param.name)) 533 const_cast = remove_suffix(param.decl.replace("const", ""), param.name) 534 struct_free = "vk_free(queue->alloc, (%s)%s);" % (const_cast, field_name) 535 member_frees = "" 536 if (param.type in types): 537 for member in types[param.type].members: 538 if member.len and member.len != 'null-terminated': 539 member_name = "cmd->u.%s.%s->%s" % (to_struct_field_name(command.name), to_field_name(param.name), member.name) 540 const_cast = remove_suffix(member.decl.replace("const", ""), member.name) 541 member_frees += "vk_free(queue->alloc, (%s)%s);\n" % (const_cast, member_name) 542 return "%s %s\n" % (member_frees, struct_free) 543 544EntrypointType = namedtuple('EntrypointType', 'name enum members extended_by guard') 545 546def get_types_defines(doc): 547 """Maps types to extension defines.""" 548 types_to_defines = {} 549 550 platform_define = {} 551 for platform in doc.findall('./platforms/platform'): 552 name = platform.attrib['name'] 553 define = platform.attrib['protect'] 554 platform_define[name] = define 555 556 for extension in doc.findall('./extensions/extension[@platform]'): 557 platform = extension.attrib['platform'] 558 define = platform_define[platform] 559 560 for types in extension.findall('./require/type'): 561 fullname = types.attrib['name'] 562 types_to_defines[fullname] = define 563 564 return types_to_defines 565 566def get_types(doc, beta, api, types_to_defines): 567 """Extract the types from the registry.""" 568 types = {} 569 570 required = get_all_required(doc, 'type', api, beta) 571 572 for _type in doc.findall('./types/type'): 573 if _type.attrib.get('category') != 'struct': 574 continue 575 if not filter_api(_type, api): 576 continue 577 if _type.attrib['name'] not in required: 578 continue 579 580 members = [] 581 type_enum = None 582 for p in _type.findall('./member'): 583 if not filter_api(p, api): 584 continue 585 586 mem_type = p.find('./type').text 587 mem_name = p.find('./name').text 588 mem_decl = ''.join(p.itertext()) 589 mem_len = p.attrib.get('altlen', p.attrib.get('len', None)) 590 if mem_len is None and '*' in mem_decl and mem_name != 'pNext': 591 mem_len = "struct-ptr" 592 593 member = EntrypointParam(type=mem_type, 594 name=mem_name, 595 decl=mem_decl, 596 len=mem_len) 597 members.append(member) 598 599 if mem_name == 'sType': 600 type_enum = p.attrib.get('values') 601 types[_type.attrib['name']] = EntrypointType(name=_type.attrib['name'], enum=type_enum, members=members, extended_by=[], guard=types_to_defines.get(_type.attrib['name'])) 602 603 for _type in doc.findall('./types/type'): 604 if _type.attrib.get('category') != 'struct': 605 continue 606 if not filter_api(_type, api): 607 continue 608 if _type.attrib['name'] not in required: 609 continue 610 if _type.attrib.get('structextends') is None: 611 continue 612 for extended in _type.attrib.get('structextends').split(','): 613 if extended not in required: 614 continue 615 types[extended].extended_by.append(types[_type.attrib['name']]) 616 617 return types 618 619def get_types_from_xml(xml_files, beta, api='vulkan'): 620 types = {} 621 622 for filename in xml_files: 623 doc = et.parse(filename) 624 types.update(get_types(doc, beta, api, get_types_defines(doc))) 625 626 return types 627 628def main(): 629 parser = argparse.ArgumentParser() 630 parser.add_argument('--out-c', required=True, help='Output C file.') 631 parser.add_argument('--out-h', required=True, help='Output H file.') 632 parser.add_argument('--beta', required=True, help='Enable beta extensions.') 633 parser.add_argument('--xml', 634 help='Vulkan API XML file.', 635 required=True, action='append', dest='xml_files') 636 args = parser.parse_args() 637 638 commands = [] 639 for e in get_entrypoints_from_xml(args.xml_files, args.beta): 640 if e.name.startswith('Cmd') and \ 641 not e.alias: 642 commands.append(e) 643 644 types = get_types_from_xml(args.xml_files, args.beta) 645 646 assert os.path.dirname(args.out_c) == os.path.dirname(args.out_h) 647 648 environment = { 649 'header': os.path.basename(args.out_h), 650 'commands': commands, 651 'filename': os.path.basename(__file__), 652 'to_underscore': to_underscore, 653 'get_array_len': get_array_len, 654 'to_struct_field_name': to_struct_field_name, 655 'to_field_name': to_field_name, 656 'to_field_decl': to_field_decl, 657 'to_enum_name': to_enum_name, 658 'to_struct_name': to_struct_name, 659 'get_array_copy': get_array_copy, 660 'get_struct_copy': get_struct_copy, 661 'get_struct_free': get_struct_free, 662 'types': types, 663 'manual_commands': MANUAL_COMMANDS, 664 'no_enqueue_commands': NO_ENQUEUE_COMMANDS, 665 'remove_suffix': remove_suffix, 666 } 667 668 try: 669 with open(args.out_h, 'w', encoding='utf-8') as f: 670 guard = os.path.basename(args.out_h).replace('.', '_').upper() 671 f.write(TEMPLATE_H.render(guard=guard, **environment)) 672 with open(args.out_c, 'w', encoding='utf-8') as f: 673 f.write(TEMPLATE_C.render(**environment)) 674 except Exception: 675 # In the event there's an error, this imports some helpers from mako 676 # to print a useful stack trace and prints it, then exits with 677 # status 1, if python is run with debug; otherwise it just raises 678 # the exception 679 import sys 680 from mako import exceptions 681 print(exceptions.text_error_template().render(), file=sys.stderr) 682 sys.exit(1) 683 684if __name__ == '__main__': 685 main() 686