1#!/usr/bin/env python 2# 3# Copyright 2013-2020 The Khronos Group Inc. 4# SPDX-License-Identifier: Apache-2.0 5 6import sys, time, pdb, string, cProfile 7from reg import * 8 9# debug - start header generation in debugger 10# dump - dump registry after loading 11# profile - enable Python profiling 12# protect - whether to use #ifndef protections 13# registry <filename> - use specified XML registry instead of gl.xml 14# target - string name of target header, or all targets if None 15# timeit - time length of registry loading & header generation 16# validate - validate return & parameter group tags against <group> 17debug = False 18dump = False 19profile = False 20protect = True 21target = None 22timeit = False 23validate= False 24# Default input / log files 25errFilename = None 26diagFilename = 'diag.txt' 27regFilename = 'gl.xml' 28 29if __name__ == '__main__': 30 i = 1 31 while (i < len(sys.argv)): 32 arg = sys.argv[i] 33 i = i + 1 34 if (arg == '-debug'): 35 write('Enabling debug (-debug)', file=sys.stderr) 36 debug = True 37 elif (arg == '-dump'): 38 write('Enabling dump (-dump)', file=sys.stderr) 39 dump = True 40 elif (arg == '-noprotect'): 41 write('Disabling inclusion protection in output headers', file=sys.stderr) 42 protect = False 43 elif (arg == '-profile'): 44 write('Enabling profiling (-profile)', file=sys.stderr) 45 profile = True 46 elif (arg == '-registry'): 47 regFilename = sys.argv[i] 48 i = i+1 49 write('Using registry ', regFilename, file=sys.stderr) 50 elif (arg == '-time'): 51 write('Enabling timing (-time)', file=sys.stderr) 52 timeit = True 53 elif (arg == '-validate'): 54 write('Enabling group validation (-validate)', file=sys.stderr) 55 validate = True 56 elif (arg[0:1] == '-'): 57 write('Unrecognized argument:', arg, file=sys.stderr) 58 exit(1) 59 else: 60 target = arg 61 write('Using target', target, file=sys.stderr) 62 63# Simple timer functions 64startTime = None 65def startTimer(): 66 global startTime 67 startTime = time.process_time() 68def endTimer(msg): 69 global startTime 70 endTime = time.process_time() 71 if (timeit): 72 write(msg, endTime - startTime) 73 startTime = None 74 75# Load & parse registry 76reg = Registry() 77 78startTimer() 79tree = etree.parse(regFilename) 80endTimer('Time to make ElementTree =') 81 82startTimer() 83reg.loadElementTree(tree) 84endTimer('Time to parse ElementTree =') 85 86if (validate): 87 reg.validateGroups() 88 89if (dump): 90 write('***************************************') 91 write('Performing Registry dump to regdump.txt') 92 write('***************************************') 93 reg.dumpReg(filehandle = open('regdump.txt','w')) 94 95# Turn a list of strings into a regexp string matching exactly those strings 96def makeREstring(list): 97 return '^(' + '|'.join(list) + ')$' 98 99# These are "mandatory" OpenGL ES 1 extensions, to 100# be included in the core GLES/gl.h header. 101es1CoreList = [ 102 'GL_OES_read_format', 103 'GL_OES_compressed_paletted_texture', 104 'GL_OES_point_size_array', 105 'GL_OES_point_sprite' 106] 107 108# These are extensions to be included in the libglvnd GL/gl.h header. 109glVndList = [ 110 'GL_ARB_imaging', 111 'GL_ARB_multitexture' 112] 113 114# Descriptive names for various regexp patterns used to select 115# versions and extensions 116 117allVersions = allExtensions = '.*' 118noVersions = noExtensions = None 119gl13Pat = '1\.[0-3]' 120gl12andLaterPat = '1\.[2-9]|[234]\.[0-9]' 121gles2onlyPat = '2\.[0-9]' 122gles2through30Pat = '2\.[0-9]|3\.0' 123gles2through31Pat = '2\.[0-9]|3\.[01]' 124gles2through32Pat = '2\.[0-9]|3\.[012]' 125es1CorePat = makeREstring(es1CoreList) 126glVndPat = makeREstring(glVndList) 127 128# Extensions in old glcorearb.h but not yet tagged accordingly in gl.xml 129glCoreARBPat = None 130glx13andLaterPat = '1\.[3-9]' 131 132# Copyright text prefixing all headers (list of strings). 133prefixStrings = [ 134 '/*', 135 '** Copyright 2013-2020 The Khronos Group Inc.', 136 '** SPDX-' + 'License-Identifier: MIT', 137 '**', 138 '** This header is generated from the Khronos OpenGL / OpenGL ES XML', 139 '** API Registry. The current version of the Registry, generator scripts', 140 '** used to make the header, and the header can be found at', 141 '** https://github.com/KhronosGroup/OpenGL-Registry', 142 '*/', 143 '' 144] 145 146# glext.h / glcorearb.h define calling conventions inline (no GL *platform.h) 147glExtPlatformStrings = [ 148 '#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)', 149 '#ifndef WIN32_LEAN_AND_MEAN', 150 '#define WIN32_LEAN_AND_MEAN 1', 151 '#endif', 152 '#include <windows.h>', 153 '#endif', 154 '', 155 '#ifndef APIENTRY', 156 '#define APIENTRY', 157 '#endif', 158 '#ifndef APIENTRYP', 159 '#define APIENTRYP APIENTRY *', 160 '#endif', 161 '#ifndef GLAPI', 162 '#define GLAPI extern', 163 '#endif', 164 '' 165] 166 167glCorearbPlatformStrings = glExtPlatformStrings + [ 168 '/* glcorearb.h is for use with OpenGL core profile implementations.', 169 '** It should should be placed in the same directory as gl.h and', 170 '** included as <GL/glcorearb.h>.', 171 '**', 172 '** glcorearb.h includes only APIs in the latest OpenGL core profile', 173 '** implementation together with APIs in newer ARB extensions which ', 174 '** can be supported by the core profile. It does not, and never will', 175 '** include functionality removed from the core profile, such as', 176 '** fixed-function vertex and fragment processing.', 177 '**', 178 '** Do not #include both <GL/glcorearb.h> and either of <GL/gl.h> or', 179 '** <GL/glext.h> in the same source file.', 180 '*/', 181 '' 182] 183 184# wglext.h needs Windows include 185wglPlatformStrings = [ 186 '#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)', 187 '#define WIN32_LEAN_AND_MEAN 1', 188 '#include <windows.h>', 189 '#endif', 190 '', 191] 192 193# Different APIs use different *platform.h files to define calling 194# conventions 195glPlatformStrings = [ '#include <GL/glplatform.h>', '' ] 196gles1PlatformStrings = [ '#include <GLES/glplatform.h>', '' ] 197gles2PlatformStrings = [ '#include <GLES2/gl2platform.h>', '' ] 198gles3PlatformStrings = [ '#include <GLES3/gl3platform.h>', '' ] 199glsc2PlatformStrings = [ '#include <GLSC2/gl2platform.h>', '' ] 200eglPlatformStrings = [ '#include <EGL/eglplatform.h>', '' ] 201 202# GLES headers have a small addition to calling convention headers for function pointer typedefs 203apiEntryPrefixStrings = [ 204 '#ifndef GL_APIENTRYP', 205 '#define GL_APIENTRYP GL_APIENTRY*', 206 '#endif', 207 '' 208] 209 210# Insert generation date in a comment for headers not having *GLEXT_VERSION macros 211genDateCommentString = [ 212 format("/* Generated on date %s */" % time.strftime("%Y%m%d")), 213 '' 214] 215 216# GL_GLEXT_VERSION is defined only in glext.h 217glextVersionStrings = [ 218 format("#define GL_GLEXT_VERSION %s" % time.strftime("%Y%m%d")), 219 '' 220] 221# WGL_WGLEXT_VERSION is defined only in wglext.h 222wglextVersionStrings = [ 223 format("#define WGL_WGLEXT_VERSION %s" % time.strftime("%Y%m%d")), 224 '' 225] 226# GLX_GLXEXT_VERSION is defined only in glxext.h 227glxextVersionStrings = [ 228 format("#define GLX_GLXEXT_VERSION %s" % time.strftime("%Y%m%d")), 229 '' 230] 231# EGL_EGLEXT_VERSION is defined only in eglext.h 232eglextVersionStrings = [ 233 format("#define EGL_EGLEXT_VERSION %s" % time.strftime("%Y%m%d")), 234 '' 235] 236 237# Defaults for generating re-inclusion protection wrappers (or not) 238protectFile = protect 239protectFeature = protect 240protectProto = protect 241 242buildList = [ 243 # GL API 1.2+ + extensions - GL/glext.h 244 CGeneratorOptions( 245 filename = 'drafts/GL/glext.h', 246 apiname = 'gl', 247 profile = 'compatibility', 248 versions = allVersions, 249 emitversions = gl12andLaterPat, 250 defaultExtensions = 'gl', # Default extensions for GL 251 addExtensions = None, 252 removeExtensions = None, 253 prefixText = prefixStrings + glExtPlatformStrings + glextVersionStrings, 254 genFuncPointers = True, 255 protectFile = protectFile, 256 protectFeature = protectFeature, 257 protectProto = protectProto, 258 protectProtoStr = 'GL_GLEXT_PROTOTYPES', 259 apicall = 'GLAPI ', 260 apientry = 'APIENTRY ', 261 apientryp = 'APIENTRYP '), 262 # GL compatibility profile through GL 1.3 (for libglvnd) - GL/gl.h 263 CGeneratorOptions( 264 filename = 'drafts/GL/gl.h', 265 apiname = 'gl', 266 profile = 'compatibility', 267 versions = allVersions, 268 emitversions = gl13Pat, 269 defaultExtensions = None, # No extensions for gl.h 270 addExtensions = glVndPat, 271 removeExtensions = None, 272 prefixText = prefixStrings + glPlatformStrings, 273 genFuncPointers = True, 274 protectFile = protectFile, 275 protectFeature = protectFeature, 276 protectProto = False, # gl.h always includes prototypes 277 protectProtoStr = 'GL_GLEXT_PROTOTYPES', 278 apicall = 'GLAPI ', 279 apientry = 'APIENTRY ', 280 apientryp = 'APIENTRYP '), 281 # GL core profile + extensions - GL/glcorearb.h 282 CGeneratorOptions( 283 filename = 'drafts/GL/glcorearb.h', 284 apiname = 'gl', 285 profile = 'core', 286 versions = allVersions, 287 emitversions = allVersions, 288 defaultExtensions = 'glcore', # Default extensions for GL core profile (only) 289 addExtensions = glCoreARBPat, 290 removeExtensions = None, 291 prefixText = prefixStrings + glCorearbPlatformStrings, 292 genFuncPointers = True, 293 protectFile = protectFile, 294 protectFeature = protectFeature, 295 protectProto = protectProto, 296 protectProtoStr = 'GL_GLEXT_PROTOTYPES', 297 apicall = 'GLAPI ', 298 apientry = 'APIENTRY ', 299 apientryp = 'APIENTRYP '), 300 # GLES 1.x API + mandatory extensions - GLES/gl.h (no function pointers) 301 CGeneratorOptions( 302 filename = 'GLES/gl.h', 303 apiname = 'gles1', 304 profile = 'common', 305 versions = allVersions, 306 emitversions = allVersions, 307 defaultExtensions = None, # No default extensions 308 addExtensions = es1CorePat, # Add mandatory ES1 extensions in GLES1/gl.h 309 removeExtensions = None, 310 prefixText = prefixStrings + gles1PlatformStrings + genDateCommentString, 311 genFuncPointers = False, 312 protectFile = protectFile, 313 protectFeature = protectFeature, 314 protectProto = False, # Core ES API functions are in the static link libraries 315 protectProtoStr = 'GL_GLEXT_PROTOTYPES', 316 apicall = 'GL_API ', 317 apientry = 'GL_APIENTRY ', 318 apientryp = 'GL_APIENTRYP '), 319 # GLES 1.x extensions - GLES/glext.h 320 CGeneratorOptions( 321 filename = 'GLES/glext.h', 322 apiname = 'gles1', 323 profile = 'common', 324 versions = allVersions, 325 emitversions = noVersions, 326 defaultExtensions = 'gles1', # Default extensions for GLES 1 327 addExtensions = None, 328 removeExtensions = es1CorePat, # Remove mandatory ES1 extensions in GLES1/glext.h 329 prefixText = prefixStrings + apiEntryPrefixStrings + genDateCommentString, 330 genFuncPointers = True, 331 protectFile = protectFile, 332 protectFeature = protectFeature, 333 protectProto = protectProto, 334 protectProtoStr = 'GL_GLEXT_PROTOTYPES', 335 apicall = 'GL_API ', 336 apientry = 'GL_APIENTRY ', 337 apientryp = 'GL_APIENTRYP '), 338 # GLES 2.0 API - GLES2/gl2.h (now with function pointers) 339 CGeneratorOptions( 340 filename = 'GLES2/gl2.h', 341 apiname = 'gles2', 342 profile = 'common', 343 versions = gles2onlyPat, 344 emitversions = allVersions, 345 defaultExtensions = None, # No default extensions 346 addExtensions = None, 347 removeExtensions = None, 348 prefixText = prefixStrings + gles2PlatformStrings + apiEntryPrefixStrings + genDateCommentString, 349 genFuncPointers = True, 350 protectFile = protectFile, 351 protectFeature = protectFeature, 352 protectProto = protectProto, # Core ES API functions are in the static link libraries 353 protectProtoStr = 'GL_GLEXT_PROTOTYPES', 354 apicall = 'GL_APICALL ', 355 apientry = 'GL_APIENTRY ', 356 apientryp = 'GL_APIENTRYP '), 357 # GLES 3.1 / 3.0 / 2.0 extensions - GLES2/gl2ext.h 358 CGeneratorOptions( 359 filename = 'GLES2/gl2ext.h', 360 apiname = 'gles2', 361 profile = 'common', 362 versions = gles2onlyPat, 363 emitversions = None, 364 defaultExtensions = 'gles2', # Default extensions for GLES 2 365 addExtensions = None, 366 removeExtensions = None, 367 prefixText = prefixStrings + apiEntryPrefixStrings + genDateCommentString, 368 genFuncPointers = True, 369 protectFile = protectFile, 370 protectFeature = protectFeature, 371 protectProto = protectProto, 372 protectProtoStr = 'GL_GLEXT_PROTOTYPES', 373 apicall = 'GL_APICALL ', 374 apientry = 'GL_APIENTRY ', 375 apientryp = 'GL_APIENTRYP '), 376 # GLES 3.2 API - GLES3/gl32.h (now with function pointers) 377 CGeneratorOptions( 378 filename = 'GLES3/gl32.h', 379 apiname = 'gles2', 380 profile = 'common', 381 versions = gles2through32Pat, 382 emitversions = allVersions, 383 defaultExtensions = None, # No default extensions 384 addExtensions = None, 385 removeExtensions = None, 386 prefixText = prefixStrings + gles3PlatformStrings + apiEntryPrefixStrings + genDateCommentString, 387 genFuncPointers = True, 388 protectFile = protectFile, 389 protectFeature = protectFeature, 390 protectProto = protectProto, # Core ES API functions are in the static link libraries 391 protectProtoStr = 'GL_GLEXT_PROTOTYPES', 392 apicall = 'GL_APICALL ', 393 apientry = 'GL_APIENTRY ', 394 apientryp = 'GL_APIENTRYP '), 395 # GLES 3.1 API - GLES3/gl31.h (now with function pointers) 396 CGeneratorOptions( 397 filename = 'GLES3/gl31.h', 398 apiname = 'gles2', 399 profile = 'common', 400 versions = gles2through31Pat, 401 emitversions = allVersions, 402 defaultExtensions = None, # No default extensions 403 addExtensions = None, 404 removeExtensions = None, 405 prefixText = prefixStrings + gles3PlatformStrings + apiEntryPrefixStrings + genDateCommentString, 406 genFuncPointers = True, 407 protectFile = protectFile, 408 protectFeature = protectFeature, 409 protectProto = protectProto, # Core ES API functions are in the static link libraries 410 protectProtoStr = 'GL_GLEXT_PROTOTYPES', 411 apicall = 'GL_APICALL ', 412 apientry = 'GL_APIENTRY ', 413 apientryp = 'GL_APIENTRYP '), 414 # GLES 3.0 API - GLES3/gl3.h (now with function pointers) 415 CGeneratorOptions( 416 filename = 'GLES3/gl3.h', 417 apiname = 'gles2', 418 profile = 'common', 419 versions = gles2through30Pat, 420 emitversions = allVersions, 421 defaultExtensions = None, # No default extensions 422 addExtensions = None, 423 removeExtensions = None, 424 prefixText = prefixStrings + gles3PlatformStrings + apiEntryPrefixStrings + genDateCommentString, 425 genFuncPointers = True, 426 protectFile = protectFile, 427 protectFeature = protectFeature, 428 protectProto = protectProto, # Core ES API functions are in the static link libraries 429 protectProtoStr = 'GL_GLEXT_PROTOTYPES', 430 apicall = 'GL_APICALL ', 431 apientry = 'GL_APIENTRY ', 432 apientryp = 'GL_APIENTRYP '), 433 # GLSC 2.0 API - GLSC2/glsc2.h 434 CGeneratorOptions( 435 filename = 'GLSC2/glsc2.h', 436 apiname = 'glsc2', 437 profile = 'common', 438 versions = gles2onlyPat, 439 emitversions = allVersions, 440 defaultExtensions = None, # No default extensions 441 addExtensions = None, 442 removeExtensions = None, 443 prefixText = prefixStrings + glsc2PlatformStrings + apiEntryPrefixStrings + genDateCommentString, 444 genFuncPointers = False, 445 protectFile = protectFile, 446 protectFeature = protectFeature, 447 protectProto = False, 448 protectProtoStr = 'GL_GLEXT_PROTOTYPES', 449 apicall = 'GL_APICALL ', 450 apientry = 'GL_APIENTRY ', 451 apientryp = 'GL_APIENTRYP '), 452 # GLSC 2.0 extensions - GLSC2/gl2ext.h 453 CGeneratorOptions( 454 filename = 'GLSC2/glsc2ext.h', 455 apiname = 'glsc2', 456 profile = 'common', 457 versions = gles2onlyPat, 458 emitversions = None, 459 defaultExtensions = 'glsc2', # Default extensions for GLSC 2 460 addExtensions = None, 461 removeExtensions = None, 462 prefixText = prefixStrings + apiEntryPrefixStrings + genDateCommentString, 463 genFuncPointers = False, 464 protectFile = protectFile, 465 protectFeature = protectFeature, 466 protectProto = False, 467 protectProtoStr = 'GL_GLEXT_PROTOTYPES', 468 apicall = 'GL_APICALL ', 469 apientry = 'GL_APIENTRY ', 470 apientryp = 'GL_APIENTRYP '), 471 # EGL API - EGL/egl.h (no function pointers, yet @@@) 472 CGeneratorOptions( 473 filename = 'EGL/egl.h', 474 apiname = 'egl', 475 profile = None, 476 versions = allVersions, 477 emitversions = allVersions, 478 defaultExtensions = None, # No default extensions 479 addExtensions = None, 480 removeExtensions = None, 481 prefixText = prefixStrings + eglPlatformStrings + genDateCommentString, 482 genFuncPointers = False, 483 protectFile = protectFile, 484 protectFeature = protectFeature, 485 protectProto = False, 486 protectProtoStr = 'EGL_EGLEXT_PROTOTYPES', 487 apicall = 'EGLAPI ', 488 apientry = 'EGLAPIENTRY ', 489 apientryp = 'EGLAPIENTRYP '), 490 # EGL extensions - EGL/eglext.h (no function pointers, yet @@@) 491 CGeneratorOptions( 492 filename = 'EGL/eglext.h', 493 apiname = 'egl', 494 profile = None, 495 versions = allVersions, 496 emitversions = None, 497 defaultExtensions = 'egl', # Default extensions for EGL 498 addExtensions = None, 499 removeExtensions = None, 500 prefixText = prefixStrings + eglPlatformStrings + eglextVersionStrings, 501 genFuncPointers = True, 502 protectFile = protectFile, 503 protectFeature = protectFeature, 504 protectProto = protectProto, 505 protectProtoStr = 'EGL_EGLEXT_PROTOTYPES', 506 apicall = 'EGLAPI ', 507 apientry = 'EGLAPIENTRY ', 508 apientryp = 'EGLAPIENTRYP '), 509 # GLX 1.* API - GL/glx.h 510 CGeneratorOptions( 511 filename = 'GL/glx.h', 512 apiname = 'glx', 513 profile = None, 514 versions = allVersions, 515 emitversions = allVersions, 516 defaultExtensions = None, # No default extensions 517 addExtensions = None, 518 removeExtensions = None, 519 # add glXPlatformStrings? 520 prefixText = prefixStrings + genDateCommentString, 521 genFuncPointers = True, 522 protectFile = protectFile, 523 protectFeature = protectFeature, 524 protectProto = protectProto, 525 protectProtoStr = 'GLX_GLXEXT_PROTOTYPES', 526 apicall = '', 527 apientry = '', 528 apientryp = ' *'), 529 # GLX 1.3+ API + extensions - GL/glxext.h (no function pointers, yet @@@) 530 CGeneratorOptions( 531 filename = 'GL/glxext.h', 532 apiname = 'glx', 533 profile = None, 534 versions = allVersions, 535 emitversions = glx13andLaterPat, 536 defaultExtensions = 'glx', # Default extensions for GLX 537 addExtensions = None, 538 removeExtensions = None, 539 # add glXPlatformStrings? 540 prefixText = prefixStrings + glxextVersionStrings, 541 genFuncPointers = True, 542 protectFile = protectFile, 543 protectFeature = protectFeature, 544 protectProto = protectProto, 545 protectProtoStr = 'GLX_GLXEXT_PROTOTYPES', 546 apicall = '', 547 apientry = '', 548 apientryp = ' *'), 549 # WGL API + extensions - GL/wgl.h (no function pointers, yet @@@) 550 CGeneratorOptions( 551 filename = 'GL/wgl.h', 552 apiname = 'wgl', 553 profile = None, 554 versions = allVersions, 555 emitversions = allVersions, 556 defaultExtensions = 'wgl', # Default extensions for WGL 557 addExtensions = None, 558 removeExtensions = None, 559 prefixText = prefixStrings + wglPlatformStrings + genDateCommentString, 560 genFuncPointers = True, 561 protectFile = protectFile, 562 protectFeature = protectFeature, 563 protectProto = protectProto, 564 protectProtoStr = 'WGL_WGLEXT_PROTOTYPES', 565 apicall = '', 566 apientry = 'WINAPI ', 567 apientryp = 'WINAPI * '), 568 # WGL extensions - GL/wglext.h (no function pointers, yet @@@) 569 CGeneratorOptions( 570 filename = 'GL/wglext.h', 571 apiname = 'wgl', 572 profile = None, 573 versions = allVersions, 574 emitversions = None, 575 defaultExtensions = 'wgl', # Default extensions for WGL 576 addExtensions = None, 577 removeExtensions = None, 578 prefixText = prefixStrings + wglPlatformStrings + wglextVersionStrings, 579 genFuncPointers = True, 580 protectFile = protectFile, 581 protectFeature = protectFeature, 582 protectProto = protectProto, 583 protectProtoStr = 'WGL_WGLEXT_PROTOTYPES', 584 apicall = '', 585 apientry = 'WINAPI ', 586 apientryp = 'WINAPI * '), 587 # End of list 588 None 589] 590 591# create error/warning & diagnostic files 592if (errFilename): 593 errWarn = open(errFilename,'w') 594else: 595 errWarn = sys.stderr 596diag = open(diagFilename, 'w') 597 598def genHeaders(): 599 # Loop over targets, building each 600 generated = 0 601 for genOpts in buildList: 602 if (genOpts == None): 603 break 604 if (target and target != genOpts.filename): 605 # write('*** Skipping', genOpts.filename) 606 continue 607 write('*** Building', genOpts.filename) 608 generated = generated + 1 609 startTimer() 610 gen = COutputGenerator(errFile=errWarn, 611 warnFile=errWarn, 612 diagFile=diag) 613 reg.setGenerator(gen) 614 reg.apiGen(genOpts) 615 write('** Generated', genOpts.filename) 616 endTimer('Time to generate ' + genOpts.filename + ' =') 617 if (target and generated == 0): 618 write('Failed to generate target:', target) 619 620if (debug): 621 pdb.run('genHeaders()') 622elif (profile): 623 import cProfile, pstats 624 cProfile.run('genHeaders()', 'profile.txt') 625 p = pstats.Stats('profile.txt') 626 p.strip_dirs().sort_stats('time').print_stats(50) 627else: 628 genHeaders() 629