Home | History | Annotate | Download | only in gen
      1 
      2 # (C) Copyright IBM Corporation 2004, 2005
      3 # All Rights Reserved.
      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 # on the rights to use, copy, modify, merge, publish, distribute, sub
      9 # license, and/or sell copies of the Software, and to permit persons to whom
     10 # the 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 NON-INFRINGEMENT.  IN NO EVENT SHALL
     19 # IBM AND/OR ITS SUPPLIERS 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 # Authors:
     25 #    Ian Romanick <idr (at] us.ibm.com>
     26 
     27 import argparse
     28 import sys, string
     29 
     30 import gl_XML, glX_XML
     31 import license
     32 
     33 
     34 class glx_enum_function(object):
     35     def __init__(self, func_name, enum_dict):
     36         self.name = func_name
     37         self.mode = 1
     38         self.sig = None
     39 
     40         # "enums" is a set of lists.  The element in the set is the
     41         # value of the enum.  The list is the list of names for that
     42         # value.  For example, [0x8126] = {"POINT_SIZE_MIN",
     43         # "POINT_SIZE_MIN_ARB", "POINT_SIZE_MIN_EXT",
     44         # "POINT_SIZE_MIN_SGIS"}.
     45 
     46         self.enums = {}
     47 
     48         # "count" is indexed by count values.  Each element of count
     49         # is a list of index to "enums" that have that number of
     50         # associated data elements.  For example, [4] = 
     51         # {GL_AMBIENT, GL_DIFFUSE, GL_SPECULAR, GL_EMISSION,
     52         # GL_AMBIENT_AND_DIFFUSE} (the enum names are used here,
     53         # but the actual hexadecimal values would be in the array).
     54 
     55         self.count = {}
     56 
     57 
     58         # Fill self.count and self.enums using the dictionary of enums
     59         # that was passed in.  The generic Get functions (e.g.,
     60         # GetBooleanv and friends) are handled specially here.  In
     61         # the data the generic Get functions are referred to as "Get".
     62 
     63         if func_name in ["GetIntegerv", "GetBooleanv", "GetFloatv", "GetDoublev"]:
     64             match_name = "Get"
     65         else:
     66             match_name = func_name
     67 
     68         mode_set = 0
     69         for enum_name in enum_dict:
     70             e = enum_dict[ enum_name ]
     71 
     72             if e.functions.has_key( match_name ):
     73                 [count, mode] = e.functions[ match_name ]
     74 
     75                 if mode_set and mode != self.mode:
     76                     raise RuntimeError("Not all enums for %s have the same mode." % (func_name))
     77 
     78                 self.mode = mode
     79 
     80                 if self.enums.has_key( e.value ):
     81                     if e.name not in self.enums[ e.value ]:
     82                         self.enums[ e.value ].append( e )
     83                 else:
     84                     if not self.count.has_key( count ):
     85                         self.count[ count ] = []
     86 
     87                     self.enums[ e.value ] = [ e ]
     88                     self.count[ count ].append( e.value )
     89 
     90 
     91         return
     92 
     93 
     94     def signature( self ):
     95         if self.sig == None:
     96             self.sig = ""
     97             for i in self.count:
     98                 if i == None:
     99                     raise RuntimeError("i is None.  WTF?")
    100 
    101                 self.count[i].sort()
    102                 for e in self.count[i]:
    103                     self.sig += "%04x,%d," % (e, i)
    104 
    105         return self.sig
    106 
    107 
    108     def is_set( self ):
    109         return self.mode
    110 
    111 
    112     def PrintUsingTable(self):
    113         """Emit the body of the __gl*_size function using a pair
    114         of look-up tables and a mask.  The mask is calculated such
    115         that (e & mask) is unique for all the valid values of e for
    116         this function.  The result of (e & mask) is used as an index
    117         into the first look-up table.  If it matches e, then the
    118         same entry of the second table is returned.  Otherwise zero
    119         is returned.
    120 
    121         It seems like this should cause better code to be generated.
    122         However, on x86 at least, the resulting .o file is about 20%
    123         larger then the switch-statment version.  I am leaving this
    124         code in because the results may be different on other
    125         platforms (e.g., PowerPC or x86-64)."""
    126 
    127         return 0
    128         count = 0
    129         for a in self.enums:
    130             count += 1
    131 
    132         if self.count.has_key(-1):
    133             return 0
    134 
    135         # Determine if there is some mask M, such that M = (2^N) - 1,
    136         # that will generate unique values for all of the enums.
    137 
    138         mask = 0
    139         for i in [1, 2, 3, 4, 5, 6, 7, 8]:
    140             mask = (1 << i) - 1
    141 
    142             fail = 0;
    143             for a in self.enums:
    144                 for b in self.enums:
    145                     if a != b:
    146                         if (a & mask) == (b & mask):
    147                             fail = 1;
    148 
    149             if not fail:
    150                 break;
    151             else:
    152                 mask = 0
    153 
    154         if (mask != 0) and (mask < (2 * count)):
    155             masked_enums = {}
    156             masked_count = {}
    157 
    158             for i in range(0, mask + 1):
    159                 masked_enums[i] = "0";
    160                 masked_count[i] = 0;
    161 
    162             for c in self.count:
    163                 for e in self.count[c]:
    164                     i = e & mask
    165                     enum_obj = self.enums[e][0]
    166                     masked_enums[i] = '0x%04x /* %s */' % (e, enum_obj.name )
    167                     masked_count[i] = c
    168 
    169 
    170             print '    static const GLushort a[%u] = {' % (mask + 1)
    171             for e in masked_enums:
    172                 print '        %s, ' % (masked_enums[e])
    173             print '    };'
    174 
    175             print '    static const GLubyte b[%u] = {' % (mask + 1)
    176             for c in masked_count:
    177                 print '        %u, ' % (masked_count[c])
    178             print '    };'
    179 
    180             print '    const unsigned idx = (e & 0x%02xU);' % (mask)
    181             print ''
    182             print '    return (e == a[idx]) ? (GLint) b[idx] : 0;'
    183             return 1;
    184         else:
    185             return 0;
    186 
    187 
    188     def PrintUsingSwitch(self, name):
    189         """Emit the body of the __gl*_size function using a 
    190         switch-statement."""
    191 
    192         print '    switch( e ) {'
    193 
    194         for c in self.count:
    195             for e in self.count[c]:
    196                 first = 1
    197 
    198                 # There may be multiple enums with the same
    199                 # value.  This happens has extensions are
    200                 # promoted from vendor-specific or EXT to
    201                 # ARB and to the core.  Emit the first one as
    202                 # a case label, and emit the others as
    203                 # commented-out case labels.
    204 
    205                 list = {}
    206                 for enum_obj in self.enums[e]:
    207                     list[ enum_obj.priority() ] = enum_obj.name
    208 
    209                 keys = list.keys()
    210                 keys.sort()
    211                 for k in keys:
    212                     j = list[k]
    213                     if first:
    214                         print '        case GL_%s:' % (j)
    215                         first = 0
    216                     else:
    217                         print '/*      case GL_%s:*/' % (j)
    218 
    219             if c == -1:
    220                 print '            return __gl%s_variable_size( e );' % (name)
    221             else:
    222                 print '            return %u;' % (c)
    223 
    224         print '        default: return 0;'
    225         print '    }'
    226 
    227 
    228     def Print(self, name):
    229         print '_X_INTERNAL PURE FASTCALL GLint'
    230         print '__gl%s_size( GLenum e )' % (name)
    231         print '{'
    232 
    233         if not self.PrintUsingTable():
    234             self.PrintUsingSwitch(name)
    235 
    236         print '}'
    237         print ''
    238 
    239 
    240 class glx_server_enum_function(glx_enum_function):
    241     def __init__(self, func, enum_dict):
    242         glx_enum_function.__init__(self, func.name, enum_dict)
    243 
    244         self.function = func
    245         return
    246 
    247 
    248     def signature( self ):
    249         if self.sig == None:
    250             sig = glx_enum_function.signature(self)
    251 
    252             p = self.function.variable_length_parameter()
    253             if p:
    254                 sig += "%u" % (p.size())
    255 
    256             self.sig = sig
    257 
    258         return self.sig;
    259 
    260 
    261     def Print(self, name, printer):
    262         f = self.function
    263         printer.common_func_print_just_header( f )
    264 
    265         fixup = []
    266 
    267         foo = {}
    268         for param_name in f.count_parameter_list:
    269             o = f.offset_of( param_name )
    270             foo[o] = param_name
    271 
    272         for param_name in f.counter_list:
    273             o = f.offset_of( param_name )
    274             foo[o] = param_name
    275 
    276         keys = foo.keys()
    277         keys.sort()
    278         for o in keys:
    279             p = f.parameters_by_name[ foo[o] ]
    280 
    281             printer.common_emit_one_arg(p, "pc", 0)
    282             fixup.append( p.name )
    283 
    284 
    285         print '    GLsizei compsize;'
    286         print ''
    287 
    288         printer.common_emit_fixups(fixup)
    289 
    290         print ''
    291         print '    compsize = __gl%s_size(%s);' % (f.name, string.join(f.count_parameter_list, ","))
    292         p = f.variable_length_parameter()
    293         print '    return safe_pad(%s);' % (p.size_string())
    294 
    295         print '}'
    296         print ''
    297 
    298 
    299 class PrintGlxSizeStubs_common(gl_XML.gl_print_base):
    300     do_get = (1 << 0)
    301     do_set = (1 << 1)
    302 
    303     def __init__(self, which_functions):
    304         gl_XML.gl_print_base.__init__(self)
    305 
    306         self.name = "glX_proto_size.py (from Mesa)"
    307         self.license = license.bsd_license_template % ( "(C) Copyright IBM Corporation 2004", "IBM")
    308 
    309         self.emit_set = ((which_functions & PrintGlxSizeStubs_common.do_set) != 0)
    310         self.emit_get = ((which_functions & PrintGlxSizeStubs_common.do_get) != 0)
    311         return
    312 
    313 
    314 class PrintGlxSizeStubs_c(PrintGlxSizeStubs_common):
    315     def printRealHeader(self):
    316         print ''
    317         print '#include <X11/Xfuncproto.h>'
    318         print '#include <GL/gl.h>'
    319         if self.emit_get:
    320             print '#include "indirect_size_get.h"'
    321             print '#include "glxserver.h"'
    322             print '#include "indirect_util.h"'
    323 
    324         print '#include "indirect_size.h"'
    325 
    326         print ''
    327         self.printPure()
    328         print ''
    329         self.printFastcall()
    330         print ''
    331         print ''
    332         print '#ifdef HAVE_FUNC_ATTRIBUTE_ALIAS'
    333         print '#  define ALIAS2(from,to) \\'
    334         print '    _X_INTERNAL PURE FASTCALL GLint __gl ## from ## _size( GLenum e ) \\'
    335         print '        __attribute__ ((alias( # to )));'
    336         print '#  define ALIAS(from,to) ALIAS2( from, __gl ## to ## _size )'
    337         print '#else'
    338         print '#  define ALIAS(from,to) \\'
    339         print '    _X_INTERNAL PURE FASTCALL GLint __gl ## from ## _size( GLenum e ) \\'
    340         print '    { return __gl ## to ## _size( e ); }'
    341         print '#endif'
    342         print ''
    343         print ''
    344 
    345 
    346     def printBody(self, api):
    347         enum_sigs = {}
    348         aliases = []
    349 
    350         for func in api.functionIterateGlx():
    351             ef = glx_enum_function( func.name, api.enums_by_name )
    352             if len(ef.enums) == 0:
    353                 continue
    354 
    355             if (ef.is_set() and self.emit_set) or (not ef.is_set() and self.emit_get):
    356                 sig = ef.signature()
    357                 if enum_sigs.has_key( sig ):
    358                     aliases.append( [func.name, enum_sigs[ sig ]] )
    359                 else:
    360                     enum_sigs[ sig ] = func.name
    361                     ef.Print( func.name )
    362 
    363 
    364         for [alias_name, real_name] in aliases:
    365             print 'ALIAS( %s, %s )' % (alias_name, real_name)
    366 
    367 
    368 
    369 class PrintGlxSizeStubs_h(PrintGlxSizeStubs_common):
    370     def printRealHeader(self):
    371         print """/**
    372  * \\file
    373  * Prototypes for functions used to determine the number of data elements in
    374  * various GLX protocol messages.
    375  *
    376  * \\author Ian Romanick <idr (at] us.ibm.com>
    377  */
    378 """
    379         print '#include <X11/Xfuncproto.h>'
    380         print ''
    381         self.printPure();
    382         print ''
    383         self.printFastcall();
    384         print ''
    385 
    386 
    387     def printBody(self, api):
    388         for func in api.functionIterateGlx():
    389             ef = glx_enum_function( func.name, api.enums_by_name )
    390             if len(ef.enums) == 0:
    391                 continue
    392 
    393             if (ef.is_set() and self.emit_set) or (not ef.is_set() and self.emit_get):
    394                 print 'extern _X_INTERNAL PURE FASTCALL GLint __gl%s_size(GLenum);' % (func.name)
    395 
    396 
    397 class PrintGlxReqSize_common(gl_XML.gl_print_base):
    398     """Common base class for PrintGlxSizeReq_h and PrintGlxSizeReq_h.
    399 
    400     The main purpose of this common base class is to provide the infrastructure
    401     for the derrived classes to iterate over the same set of functions.
    402     """
    403 
    404     def __init__(self):
    405         gl_XML.gl_print_base.__init__(self)
    406 
    407         self.name = "glX_proto_size.py (from Mesa)"
    408         self.license = license.bsd_license_template % ( "(C) Copyright IBM Corporation 2005", "IBM")
    409 
    410 
    411 class PrintGlxReqSize_h(PrintGlxReqSize_common):
    412     def __init__(self):
    413         PrintGlxReqSize_common.__init__(self)
    414         self.header_tag = "_INDIRECT_REQSIZE_H_"
    415 
    416 
    417     def printRealHeader(self):
    418         print '#include <X11/Xfuncproto.h>'
    419         print ''
    420         self.printPure()
    421         print ''
    422 
    423 
    424     def printBody(self, api):
    425         for func in api.functionIterateGlx():
    426             if not func.ignore and func.has_variable_size_request():
    427                 print 'extern PURE _X_HIDDEN int __glX%sReqSize(const GLbyte *pc, Bool swap, int reqlen);' % (func.name)
    428 
    429 
    430 class PrintGlxReqSize_c(PrintGlxReqSize_common):
    431     """Create the server-side 'request size' functions.
    432 
    433     Create the server-side functions that are used to determine what the
    434     size of a varible length command should be.  The server then uses
    435     this value to determine if the incoming command packed it malformed.
    436     """
    437 
    438     def __init__(self):
    439         PrintGlxReqSize_common.__init__(self)
    440         self.counter_sigs = {}
    441 
    442 
    443     def printRealHeader(self):
    444         print ''
    445         print '#include <GL/gl.h>'
    446         print '#include "glxserver.h"'
    447         print '#include "glxbyteorder.h"'
    448         print '#include "indirect_size.h"'
    449         print '#include "indirect_reqsize.h"'
    450         print ''
    451         print '#ifdef HAVE_FUNC_ATTRIBUTE_ALIAS'
    452         print '#  define ALIAS2(from,to) \\'
    453         print '    GLint __glX ## from ## ReqSize( const GLbyte * pc, Bool swap, int reqlen ) \\'
    454         print '        __attribute__ ((alias( # to )));'
    455         print '#  define ALIAS(from,to) ALIAS2( from, __glX ## to ## ReqSize )'
    456         print '#else'
    457         print '#  define ALIAS(from,to) \\'
    458         print '    GLint __glX ## from ## ReqSize( const GLbyte * pc, Bool swap, int reqlen ) \\'
    459         print '    { return __glX ## to ## ReqSize( pc, swap, reqlen ); }'
    460         print '#endif'
    461         print ''
    462         print ''
    463 
    464 
    465     def printBody(self, api):
    466         aliases = []
    467         enum_functions = {}
    468         enum_sigs = {}
    469 
    470         for func in api.functionIterateGlx():
    471             if not func.has_variable_size_request(): continue
    472 
    473             ef = glx_server_enum_function( func, api.enums_by_name )
    474             if len(ef.enums) == 0: continue
    475 
    476             sig = ef.signature()
    477 
    478             if not enum_functions.has_key(func.name):
    479                 enum_functions[ func.name ] = sig
    480 
    481             if not enum_sigs.has_key( sig ):
    482                 enum_sigs[ sig ] = ef
    483 
    484 
    485 
    486         for func in api.functionIterateGlx():
    487             # Even though server-handcode fuctions are on "the
    488             # list", and prototypes are generated for them, there
    489             # isn't enough information to generate a size
    490             # function.  If there was enough information, they
    491             # probably wouldn't need to be handcoded in the first
    492             # place!
    493 
    494             if func.server_handcode: continue
    495             if not func.has_variable_size_request(): continue
    496 
    497             if enum_functions.has_key(func.name):
    498                 sig = enum_functions[func.name]
    499                 ef = enum_sigs[ sig ]
    500 
    501                 if ef.name != func.name:
    502                     aliases.append( [func.name, ef.name] )
    503                 else:
    504                     ef.Print( func.name, self )
    505 
    506             elif func.images:
    507                 self.printPixelFunction(func)
    508             elif func.has_variable_size_request():
    509                 a = self.printCountedFunction(func)
    510                 if a: aliases.append(a)
    511 
    512 
    513         for [alias_name, real_name] in aliases:
    514             print 'ALIAS( %s, %s )' % (alias_name, real_name)
    515 
    516         return
    517 
    518 
    519     def common_emit_fixups(self, fixup):
    520         """Utility function to emit conditional byte-swaps."""
    521 
    522         if fixup:
    523             print '    if (swap) {'
    524             for name in fixup:
    525                 print '        %s = bswap_32(%s);' % (name, name)
    526             print '    }'
    527 
    528         return
    529 
    530 
    531     def common_emit_one_arg(self, p, pc, adjust):
    532         offset = p.offset
    533         dst = p.string()
    534         src = '(%s *)' % (p.type_string())
    535         print '%-18s = *%11s(%s + %u);' % (dst, src, pc, offset + adjust);
    536         return
    537 
    538 
    539     def common_func_print_just_header(self, f):
    540         print 'int'
    541         print '__glX%sReqSize( const GLbyte * pc, Bool swap, int reqlen )' % (f.name)
    542         print '{'
    543 
    544 
    545     def printPixelFunction(self, f):
    546         self.common_func_print_just_header(f)
    547 
    548         f.offset_of( f.parameters[0].name )
    549         [dim, w, h, d, junk] = f.get_images()[0].get_dimensions()
    550 
    551         print '    GLint row_length   = *  (GLint *)(pc +  4);'
    552 
    553         if dim < 3:
    554             fixup = ['row_length', 'skip_rows', 'alignment']
    555             print '    GLint image_height = 0;'
    556             print '    GLint skip_images  = 0;'
    557             print '    GLint skip_rows    = *  (GLint *)(pc +  8);'
    558             print '    GLint alignment    = *  (GLint *)(pc + 16);'
    559         else:
    560             fixup = ['row_length', 'image_height', 'skip_rows', 'skip_images', 'alignment']
    561             print '    GLint image_height = *  (GLint *)(pc +  8);'
    562             print '    GLint skip_rows    = *  (GLint *)(pc + 16);'
    563             print '    GLint skip_images  = *  (GLint *)(pc + 20);'
    564             print '    GLint alignment    = *  (GLint *)(pc + 32);'
    565 
    566         img = f.images[0]
    567         for p in f.parameterIterateGlxSend():
    568             if p.name in [w, h, d, img.img_format, img.img_type, img.img_target]:
    569                 self.common_emit_one_arg(p, "pc", 0)
    570                 fixup.append( p.name )
    571 
    572         print ''
    573 
    574         self.common_emit_fixups(fixup)
    575 
    576         if img.img_null_flag:
    577             print ''
    578             print '	   if (*(CARD32 *) (pc + %s))' % (img.offset - 4)
    579             print '	       return 0;'
    580 
    581         print ''
    582         print '    return __glXImageSize(%s, %s, %s, %s, %s, %s,' % (img.img_format, img.img_type, img.img_target, w, h, d )
    583         print '                          image_height, row_length, skip_images,'
    584         print '                          skip_rows, alignment);'
    585         print '}'
    586         print ''
    587         return
    588 
    589 
    590     def printCountedFunction(self, f):
    591 
    592         sig = ""
    593         offset = 0
    594         fixup = []
    595         params = []
    596         size = ''
    597         param_offsets = {}
    598 
    599         # Calculate the offset of each counter parameter and the
    600         # size string for the variable length parameter(s).  While
    601         # that is being done, calculate a unique signature for this
    602         # function.
    603 
    604         for p in f.parameterIterateGlxSend():
    605             if p.is_counter:
    606                 fixup.append( p.name )
    607                 params.append( p )
    608             elif p.counter:
    609                 s = p.size()
    610                 if s == 0: s = 1
    611 
    612                 sig += "(%u,%u)" % (f.offset_of(p.counter), s)
    613 		if size == '':
    614 		    size = p.size_string()
    615 		else:
    616 		    size = "safe_add(%s, %s)" % (size, p.size_string())
    617 
    618         # If the calculated signature matches a function that has
    619         # already be emitted, don't emit this function.  Instead, add
    620         # it to the list of function aliases.
    621 
    622         if self.counter_sigs.has_key(sig):
    623             n = self.counter_sigs[sig];
    624             alias = [f.name, n]
    625         else:
    626             alias = None
    627             self.counter_sigs[sig] = f.name
    628 
    629             self.common_func_print_just_header(f)
    630 
    631             for p in params:
    632                 self.common_emit_one_arg(p, "pc", 0)
    633 
    634 
    635             print ''
    636             self.common_emit_fixups(fixup)
    637             print ''
    638 
    639             print '    return safe_pad(%s);' % (size)
    640             print '}'
    641             print ''
    642 
    643         return alias
    644 
    645 
    646 def _parser():
    647     """Parse arguments and return a namespace."""
    648     parser = argparse.ArgumentParser()
    649     parser.set_defaults(which_functions=(PrintGlxSizeStubs_common.do_get |
    650                                          PrintGlxSizeStubs_common.do_set))
    651     parser.add_argument('-f',
    652                         dest='filename',
    653                         default='gl_API.xml',
    654                         help='an XML file describing an OpenGL API.')
    655     parser.add_argument('-m',
    656                         dest='mode',
    657                         choices=['size_c', 'size_h', 'reqsize_c', 'reqsize_h'],
    658                         help='Which file to generate')
    659     getset = parser.add_mutually_exclusive_group()
    660     getset.add_argument('--only-get',
    661                         dest='which_functions',
    662                         action='store_const',
    663                         const=PrintGlxSizeStubs_common.do_get,
    664                         help='only emit "get-type" functions')
    665     getset.add_argument('--only-set',
    666                         dest='which_functions',
    667                         action='store_const',
    668                         const=PrintGlxSizeStubs_common.do_set,
    669                         help='only emit "set-type" functions')
    670     parser.add_argument('--header-tag',
    671                         dest='header_tag',
    672                         action='store',
    673                         default=None,
    674                         help='set header tag value')
    675     return parser.parse_args()
    676 
    677 
    678 def main():
    679     """Main function."""
    680     args = _parser()
    681 
    682     if args.mode == "size_c":
    683         printer = PrintGlxSizeStubs_c(args.which_functions)
    684     elif args.mode == "size_h":
    685         printer = PrintGlxSizeStubs_h(args.which_functions)
    686         if args.header_tag is not None:
    687             printer.header_tag = args.header_tag
    688     elif args.mode == "reqsize_c":
    689         printer = PrintGlxReqSize_c()
    690     elif args.mode == "reqsize_h":
    691         printer = PrintGlxReqSize_h()
    692 
    693     api = gl_XML.parse_GL_API(args.filename, glX_XML.glx_item_factory())
    694 
    695     printer.Print(api)
    696 
    697 
    698 if __name__ == '__main__':
    699     main()
    700