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