13464ebd5Sriastradh
23464ebd5Sriastradh# (C) Copyright IBM Corporation 2004, 2005
33464ebd5Sriastradh# All Rights Reserved.
43464ebd5Sriastradh#
53464ebd5Sriastradh# Permission is hereby granted, free of charge, to any person obtaining a
63464ebd5Sriastradh# copy of this software and associated documentation files (the "Software"),
73464ebd5Sriastradh# to deal in the Software without restriction, including without limitation
83464ebd5Sriastradh# on the rights to use, copy, modify, merge, publish, distribute, sub
93464ebd5Sriastradh# license, and/or sell copies of the Software, and to permit persons to whom
103464ebd5Sriastradh# the Software is furnished to do so, subject to the following conditions:
113464ebd5Sriastradh#
123464ebd5Sriastradh# The above copyright notice and this permission notice (including the next
133464ebd5Sriastradh# paragraph) shall be included in all copies or substantial portions of the
143464ebd5Sriastradh# Software.
153464ebd5Sriastradh#
163464ebd5Sriastradh# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
173464ebd5Sriastradh# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
183464ebd5Sriastradh# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
193464ebd5Sriastradh# IBM AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
203464ebd5Sriastradh# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
213464ebd5Sriastradh# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
223464ebd5Sriastradh# IN THE SOFTWARE.
233464ebd5Sriastradh#
243464ebd5Sriastradh# Authors:
253464ebd5Sriastradh#    Ian Romanick <idr@us.ibm.com>
263464ebd5Sriastradh
2701e04c3fSmrgfrom collections import OrderedDict
28af69d88dSmrgfrom decimal import Decimal
29af69d88dSmrgimport xml.etree.ElementTree as ET
3001e04c3fSmrgimport re, sys
31af69d88dSmrgimport os.path
323464ebd5Sriastradhimport typeexpr
3301e04c3fSmrgimport static_data
343464ebd5Sriastradh
353464ebd5Sriastradh
363464ebd5Sriastradhdef parse_GL_API( file_name, factory = None ):
373464ebd5Sriastradh
38af69d88dSmrg    if not factory:
39af69d88dSmrg        factory = gl_item_factory()
403464ebd5Sriastradh
41af69d88dSmrg    api = factory.create_api()
42af69d88dSmrg    api.parse_file( file_name )
433464ebd5Sriastradh
44af69d88dSmrg    # After the XML has been processed, we need to go back and assign
45af69d88dSmrg    # dispatch offsets to the functions that request that their offsets
46af69d88dSmrg    # be assigned by the scripts.  Typically this means all functions
47af69d88dSmrg    # that are not part of the ABI.
483464ebd5Sriastradh
49af69d88dSmrg    for func in api.functionIterateByCategory():
509f464c52Smaya        if func.assign_offset and func.offset < 0:
51af69d88dSmrg            func.offset = api.next_offset;
52af69d88dSmrg            api.next_offset += 1
533464ebd5Sriastradh
54af69d88dSmrg    return api
553464ebd5Sriastradh
563464ebd5Sriastradh
57af69d88dSmrgdef is_attr_true( element, name, default = "false" ):
58af69d88dSmrg    """Read a name value from an element's attributes.
593464ebd5Sriastradh
60af69d88dSmrg    The value read from the attribute list must be either 'true' or
61af69d88dSmrg    'false'.  If the value is 'false', zero will be returned.  If the
62af69d88dSmrg    value is 'true', non-zero will be returned.  An exception will be
63af69d88dSmrg    raised for any other value."""
643464ebd5Sriastradh
65af69d88dSmrg    value = element.get( name, default )
66af69d88dSmrg    if value == "true":
67af69d88dSmrg        return 1
68af69d88dSmrg    elif value == "false":
69af69d88dSmrg        return 0
70af69d88dSmrg    else:
71af69d88dSmrg        raise RuntimeError('Invalid value "%s" for boolean "%s".' % (value, name))
723464ebd5Sriastradh
733464ebd5Sriastradh
74af69d88dSmrgclass gl_print_base(object):
75af69d88dSmrg    """Base class of all API pretty-printers.
763464ebd5Sriastradh
77af69d88dSmrg    In the model-view-controller pattern, this is the view.  Any derived
78af69d88dSmrg    class will want to over-ride the printBody, printRealHader, and
79af69d88dSmrg    printRealFooter methods.  Some derived classes may want to over-ride
80af69d88dSmrg    printHeader and printFooter, or even Print (though this is unlikely).
81af69d88dSmrg    """
823464ebd5Sriastradh
83af69d88dSmrg    def __init__(self):
84af69d88dSmrg        # Name of the script that is generating the output file.
85af69d88dSmrg        # Every derived class should set this to the name of its
86af69d88dSmrg        # source file.
873464ebd5Sriastradh
88af69d88dSmrg        self.name = "a"
893464ebd5Sriastradh
903464ebd5Sriastradh
91af69d88dSmrg        # License on the *generated* source file.  This may differ
92af69d88dSmrg        # from the license on the script that is generating the file.
93af69d88dSmrg        # Every derived class should set this to some reasonable
94af69d88dSmrg        # value.
95af69d88dSmrg        #
96af69d88dSmrg        # See license.py for an example of a reasonable value.
973464ebd5Sriastradh
98af69d88dSmrg        self.license = "The license for this file is unspecified."
993464ebd5Sriastradh
1003464ebd5Sriastradh
101af69d88dSmrg        # The header_tag is the name of the C preprocessor define
102af69d88dSmrg        # used to prevent multiple inclusion.  Typically only
103af69d88dSmrg        # generated C header files need this to be set.  Setting it
104af69d88dSmrg        # causes code to be generated automatically in printHeader
105af69d88dSmrg        # and printFooter.
1063464ebd5Sriastradh
107af69d88dSmrg        self.header_tag = None
1083464ebd5Sriastradh
1093464ebd5Sriastradh
110af69d88dSmrg        # List of file-private defines that must be undefined at the
111af69d88dSmrg        # end of the file.  This can be used in header files to define
112af69d88dSmrg        # names for use in the file, then undefine them at the end of
113af69d88dSmrg        # the header file.
1143464ebd5Sriastradh
115af69d88dSmrg        self.undef_list = []
116af69d88dSmrg        return
1173464ebd5Sriastradh
1183464ebd5Sriastradh
119af69d88dSmrg    def Print(self, api):
120af69d88dSmrg        self.printHeader()
121af69d88dSmrg        self.printBody(api)
122af69d88dSmrg        self.printFooter()
123af69d88dSmrg        return
1243464ebd5Sriastradh
1253464ebd5Sriastradh
126af69d88dSmrg    def printHeader(self):
127af69d88dSmrg        """Print the header associated with all files and call the printRealHeader method."""
1283464ebd5Sriastradh
12901e04c3fSmrg        print('/* DO NOT EDIT - This file generated automatically by %s script */' \
13001e04c3fSmrg                % (self.name))
13101e04c3fSmrg        print('')
13201e04c3fSmrg        print('/*')
13301e04c3fSmrg        print((' * ' + self.license.replace('\n', '\n * ')).replace(' \n', '\n'))
13401e04c3fSmrg        print(' */')
13501e04c3fSmrg        print('')
136af69d88dSmrg        if self.header_tag:
13701e04c3fSmrg            print('#if !defined( %s )' % (self.header_tag))
13801e04c3fSmrg            print('#  define %s' % (self.header_tag))
13901e04c3fSmrg            print('')
140af69d88dSmrg        self.printRealHeader();
141af69d88dSmrg        return
1423464ebd5Sriastradh
1433464ebd5Sriastradh
144af69d88dSmrg    def printFooter(self):
145af69d88dSmrg        """Print the header associated with all files and call the printRealFooter method."""
1463464ebd5Sriastradh
147af69d88dSmrg        self.printRealFooter()
1483464ebd5Sriastradh
149af69d88dSmrg        if self.undef_list:
15001e04c3fSmrg            print('')
151af69d88dSmrg            for u in self.undef_list:
15201e04c3fSmrg                print("#  undef %s" % (u))
1533464ebd5Sriastradh
154af69d88dSmrg        if self.header_tag:
15501e04c3fSmrg            print('')
15601e04c3fSmrg            print('#endif /* !defined( %s ) */' % (self.header_tag))
1573464ebd5Sriastradh
1583464ebd5Sriastradh
159af69d88dSmrg    def printRealHeader(self):
160af69d88dSmrg        """Print the "real" header for the created file.
1613464ebd5Sriastradh
162af69d88dSmrg        In the base class, this function is empty.  All derived
163af69d88dSmrg        classes should over-ride this function."""
164af69d88dSmrg        return
1653464ebd5Sriastradh
1663464ebd5Sriastradh
167af69d88dSmrg    def printRealFooter(self):
168af69d88dSmrg        """Print the "real" footer for the created file.
1693464ebd5Sriastradh
170af69d88dSmrg        In the base class, this function is empty.  All derived
171af69d88dSmrg        classes should over-ride this function."""
172af69d88dSmrg        return
1733464ebd5Sriastradh
174af69d88dSmrg
175af69d88dSmrg    def printPure(self):
176af69d88dSmrg        """Conditionally define `PURE' function attribute.
177af69d88dSmrg
178af69d88dSmrg        Conditionally defines a preprocessor macro `PURE' that wraps
179af69d88dSmrg        GCC's `pure' function attribute.  The conditional code can be
180af69d88dSmrg        easilly adapted to other compilers that support a similar
181af69d88dSmrg        feature.
182af69d88dSmrg
183af69d88dSmrg        The name is also added to the file's undef_list.
184af69d88dSmrg        """
185af69d88dSmrg        self.undef_list.append("PURE")
18601e04c3fSmrg        print("""#  if defined(__GNUC__) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590))
1873464ebd5Sriastradh#    define PURE __attribute__((pure))
1883464ebd5Sriastradh#  else
1893464ebd5Sriastradh#    define PURE
19001e04c3fSmrg#  endif""")
191af69d88dSmrg        return
1923464ebd5Sriastradh
1933464ebd5Sriastradh
194af69d88dSmrg    def printFastcall(self):
195af69d88dSmrg        """Conditionally define `FASTCALL' function attribute.
1963464ebd5Sriastradh
197af69d88dSmrg        Conditionally defines a preprocessor macro `FASTCALL' that
198af69d88dSmrg        wraps GCC's `fastcall' function attribute.  The conditional
199af69d88dSmrg        code can be easilly adapted to other compilers that support a
200af69d88dSmrg        similar feature.
2013464ebd5Sriastradh
202af69d88dSmrg        The name is also added to the file's undef_list.
203af69d88dSmrg        """
2043464ebd5Sriastradh
205af69d88dSmrg        self.undef_list.append("FASTCALL")
20601e04c3fSmrg        print("""#  if defined(__i386__) && defined(__GNUC__) && !defined(__CYGWIN__) && !defined(__MINGW32__)
2073464ebd5Sriastradh#    define FASTCALL __attribute__((fastcall))
2083464ebd5Sriastradh#  else
2093464ebd5Sriastradh#    define FASTCALL
21001e04c3fSmrg#  endif""")
211af69d88dSmrg        return
2123464ebd5Sriastradh
2133464ebd5Sriastradh
214af69d88dSmrg    def printVisibility(self, S, s):
215af69d88dSmrg        """Conditionally define visibility function attribute.
2163464ebd5Sriastradh
217af69d88dSmrg        Conditionally defines a preprocessor macro name S that wraps
218af69d88dSmrg        GCC's visibility function attribute.  The visibility used is
219af69d88dSmrg        the parameter s.  The conditional code can be easilly adapted
220af69d88dSmrg        to other compilers that support a similar feature.
2213464ebd5Sriastradh
222af69d88dSmrg        The name is also added to the file's undef_list.
223af69d88dSmrg        """
2243464ebd5Sriastradh
225af69d88dSmrg        self.undef_list.append(S)
22601e04c3fSmrg        print("""#  if defined(__GNUC__) && !defined(__CYGWIN__) && !defined(__MINGW32__)
2273464ebd5Sriastradh#    define %s  __attribute__((visibility("%s")))
2283464ebd5Sriastradh#  else
2293464ebd5Sriastradh#    define %s
23001e04c3fSmrg#  endif""" % (S, s, S))
231af69d88dSmrg        return
2323464ebd5Sriastradh
2333464ebd5Sriastradh
234af69d88dSmrg    def printNoinline(self):
235af69d88dSmrg        """Conditionally define `NOINLINE' function attribute.
2363464ebd5Sriastradh
237af69d88dSmrg        Conditionally defines a preprocessor macro `NOINLINE' that
238af69d88dSmrg        wraps GCC's `noinline' function attribute.  The conditional
239af69d88dSmrg        code can be easilly adapted to other compilers that support a
240af69d88dSmrg        similar feature.
2413464ebd5Sriastradh
242af69d88dSmrg        The name is also added to the file's undef_list.
243af69d88dSmrg        """
2443464ebd5Sriastradh
245af69d88dSmrg        self.undef_list.append("NOINLINE")
24601e04c3fSmrg        print("""#  if defined(__GNUC__)
2473464ebd5Sriastradh#    define NOINLINE __attribute__((noinline))
2483464ebd5Sriastradh#  else
2493464ebd5Sriastradh#    define NOINLINE
25001e04c3fSmrg#  endif""")
251af69d88dSmrg        return
2523464ebd5Sriastradh
2533464ebd5Sriastradh
2543464ebd5Sriastradhdef real_function_name(element):
255af69d88dSmrg    name = element.get( "name" )
256af69d88dSmrg    alias = element.get( "alias" )
257af69d88dSmrg
258af69d88dSmrg    if alias:
259af69d88dSmrg        return alias
260af69d88dSmrg    else:
261af69d88dSmrg        return name
2623464ebd5Sriastradh
2633464ebd5Sriastradh
2643464ebd5Sriastradhdef real_category_name(c):
265af69d88dSmrg    if re.compile("[1-9][0-9]*[.][0-9]+").match(c):
266af69d88dSmrg        return "GL_VERSION_" + c.replace(".", "_")
267af69d88dSmrg    else:
268af69d88dSmrg        return c
2693464ebd5Sriastradh
2703464ebd5Sriastradh
2713464ebd5Sriastradhdef classify_category(name, number):
272af69d88dSmrg    """Based on the category name and number, select a numerical class for it.
2733464ebd5Sriastradh
274af69d88dSmrg    Categories are divided into four classes numbered 0 through 3.  The
275af69d88dSmrg    classes are:
2763464ebd5Sriastradh
277af69d88dSmrg            0. Core GL versions, sorted by version number.
278af69d88dSmrg            1. ARB extensions, sorted by extension number.
279af69d88dSmrg            2. Non-ARB extensions, sorted by extension number.
280af69d88dSmrg            3. Un-numbered extensions, sorted by extension name.
281af69d88dSmrg    """
2823464ebd5Sriastradh
283af69d88dSmrg    try:
284af69d88dSmrg        core_version = float(name)
28501e04c3fSmrg    except Exception:
286af69d88dSmrg        core_version = 0.0
2873464ebd5Sriastradh
288af69d88dSmrg    if core_version > 0.0:
289af69d88dSmrg        cat_type = 0
290af69d88dSmrg        key = name
291af69d88dSmrg    elif name.startswith("GL_ARB_") or name.startswith("GLX_ARB_") or name.startswith("WGL_ARB_"):
292af69d88dSmrg        cat_type = 1
293af69d88dSmrg        key = int(number)
294af69d88dSmrg    else:
295af69d88dSmrg        if number != None:
296af69d88dSmrg            cat_type = 2
297af69d88dSmrg            key = int(number)
298af69d88dSmrg        else:
299af69d88dSmrg            cat_type = 3
300af69d88dSmrg            key = name
3013464ebd5Sriastradh
3023464ebd5Sriastradh
303af69d88dSmrg    return [cat_type, key]
3043464ebd5Sriastradh
3053464ebd5Sriastradh
306af69d88dSmrgdef create_parameter_string(parameters, include_names):
307af69d88dSmrg    """Create a parameter string from a list of gl_parameters."""
3083464ebd5Sriastradh
309af69d88dSmrg    list = []
310af69d88dSmrg    for p in parameters:
311af69d88dSmrg        if p.is_padding:
312af69d88dSmrg            continue
3133464ebd5Sriastradh
314af69d88dSmrg        if include_names:
315af69d88dSmrg            list.append( p.string() )
316af69d88dSmrg        else:
317af69d88dSmrg            list.append( p.type_string() )
3183464ebd5Sriastradh
319af69d88dSmrg    if len(list) == 0: list = ["void"]
3203464ebd5Sriastradh
32101e04c3fSmrg    return ", ".join(list)
3223464ebd5Sriastradh
3233464ebd5Sriastradh
324af69d88dSmrgclass gl_item(object):
325af69d88dSmrg    def __init__(self, element, context, category):
326af69d88dSmrg        self.context = context
327af69d88dSmrg        self.name = element.get( "name" )
328af69d88dSmrg        self.category = real_category_name( category )
3293464ebd5Sriastradh
330af69d88dSmrg        return
3313464ebd5Sriastradh
3323464ebd5Sriastradh
333af69d88dSmrgclass gl_type( gl_item ):
334af69d88dSmrg    def __init__(self, element, context, category):
335af69d88dSmrg        gl_item.__init__(self, element, context, category)
336af69d88dSmrg        self.size = int( element.get( "size" ), 0 )
337af69d88dSmrg
338af69d88dSmrg        te = typeexpr.type_expression( None )
339af69d88dSmrg        tn = typeexpr.type_node()
340af69d88dSmrg        tn.size = int( element.get( "size" ), 0 )
341af69d88dSmrg        tn.integer = not is_attr_true( element, "float" )
342af69d88dSmrg        tn.unsigned = is_attr_true( element, "unsigned" )
343af69d88dSmrg        tn.pointer = is_attr_true( element, "pointer" )
344af69d88dSmrg        tn.name = "GL" + self.name
345af69d88dSmrg        te.set_base_type_node( tn )
3463464ebd5Sriastradh
347af69d88dSmrg        self.type_expr = te
348af69d88dSmrg        return
3493464ebd5Sriastradh
3503464ebd5Sriastradh
351af69d88dSmrg    def get_type_expression(self):
352af69d88dSmrg        return self.type_expr
3533464ebd5Sriastradh
3543464ebd5Sriastradh
355af69d88dSmrgclass gl_enum( gl_item ):
356af69d88dSmrg    def __init__(self, element, context, category):
357af69d88dSmrg        gl_item.__init__(self, element, context, category)
358af69d88dSmrg        self.value = int( element.get( "value" ), 0 )
359af69d88dSmrg
360af69d88dSmrg        temp = element.get( "count" )
361af69d88dSmrg        if not temp or temp == "?":
362af69d88dSmrg            self.default_count = -1
363af69d88dSmrg        else:
364af69d88dSmrg            try:
365af69d88dSmrg                c = int(temp)
36601e04c3fSmrg            except Exception:
367af69d88dSmrg                raise RuntimeError('Invalid count value "%s" for enum "%s" in function "%s" when an integer was expected.' % (temp, self.name, n))
368af69d88dSmrg
369af69d88dSmrg            self.default_count = c
3703464ebd5Sriastradh
371af69d88dSmrg        return
3723464ebd5Sriastradh
3733464ebd5Sriastradh
374af69d88dSmrg    def priority(self):
375af69d88dSmrg        """Calculate a 'priority' for this enum name.
3763464ebd5Sriastradh
377af69d88dSmrg        When an enum is looked up by number, there may be many
378af69d88dSmrg        possible names, but only one is the 'prefered' name.  The
379af69d88dSmrg        priority is used to select which name is the 'best'.
3803464ebd5Sriastradh
381af69d88dSmrg        Highest precedence is given to core GL name.  ARB extension
382af69d88dSmrg        names have the next highest, followed by EXT extension names.
383af69d88dSmrg        Vendor extension names are the lowest.
384af69d88dSmrg        """
3853464ebd5Sriastradh
386af69d88dSmrg        if self.name.endswith( "_BIT" ):
387af69d88dSmrg            bias = 1
388af69d88dSmrg        else:
389af69d88dSmrg            bias = 0
3903464ebd5Sriastradh
391af69d88dSmrg        if self.category.startswith( "GL_VERSION_" ):
392af69d88dSmrg            priority = 0
393af69d88dSmrg        elif self.category.startswith( "GL_ARB_" ):
394af69d88dSmrg            priority = 2
395af69d88dSmrg        elif self.category.startswith( "GL_EXT_" ):
396af69d88dSmrg            priority = 4
397af69d88dSmrg        else:
398af69d88dSmrg            priority = 6
3993464ebd5Sriastradh
400af69d88dSmrg        return priority + bias
4013464ebd5Sriastradh
4023464ebd5Sriastradh
4033464ebd5Sriastradh
404af69d88dSmrgclass gl_parameter(object):
405af69d88dSmrg    def __init__(self, element, context):
406af69d88dSmrg        self.name = element.get( "name" )
4073464ebd5Sriastradh
408af69d88dSmrg        ts = element.get( "type" )
409af69d88dSmrg        self.type_expr = typeexpr.type_expression( ts, context )
4103464ebd5Sriastradh
411af69d88dSmrg        temp = element.get( "variable_param" )
412af69d88dSmrg        if temp:
413af69d88dSmrg            self.count_parameter_list = temp.split( ' ' )
414af69d88dSmrg        else:
415af69d88dSmrg            self.count_parameter_list = []
4163464ebd5Sriastradh
417af69d88dSmrg        # The count tag can be either a numeric string or the name of
418af69d88dSmrg        # a variable.  If it is the name of a variable, the int(c)
419af69d88dSmrg        # statement will throw an exception, and the except block will
420af69d88dSmrg        # take over.
4213464ebd5Sriastradh
422af69d88dSmrg        c = element.get( "count" )
423af69d88dSmrg        try:
424af69d88dSmrg            count = int(c)
425af69d88dSmrg            self.count = count
426af69d88dSmrg            self.counter = None
42701e04c3fSmrg        except Exception:
428af69d88dSmrg            count = 1
429af69d88dSmrg            self.count = 0
430af69d88dSmrg            self.counter = c
4313464ebd5Sriastradh
4327ec681f3Smrg        self.marshal_count = element.get("marshal_count")
433af69d88dSmrg        self.count_scale = int(element.get( "count_scale", "1" ))
4343464ebd5Sriastradh
435af69d88dSmrg        elements = (count * self.count_scale)
436af69d88dSmrg        if elements == 1:
437af69d88dSmrg            elements = 0
4383464ebd5Sriastradh
439af69d88dSmrg        #if ts == "GLdouble":
440af69d88dSmrg        #	print '/* stack size -> %s = %u (before)*/' % (self.name, self.type_expr.get_stack_size())
441af69d88dSmrg        #	print '/* # elements = %u */' % (elements)
442af69d88dSmrg        self.type_expr.set_elements( elements )
443af69d88dSmrg        #if ts == "GLdouble":
444af69d88dSmrg        #	print '/* stack size -> %s = %u (after) */' % (self.name, self.type_expr.get_stack_size())
4453464ebd5Sriastradh
446af69d88dSmrg        self.is_client_only = is_attr_true( element, 'client_only' )
447af69d88dSmrg        self.is_counter     = is_attr_true( element, 'counter' )
448af69d88dSmrg        self.is_output      = is_attr_true( element, 'output' )
4493464ebd5Sriastradh
4503464ebd5Sriastradh
451af69d88dSmrg        # Pixel data has special parameters.
4523464ebd5Sriastradh
453af69d88dSmrg        self.width      = element.get('img_width')
454af69d88dSmrg        self.height     = element.get('img_height')
455af69d88dSmrg        self.depth      = element.get('img_depth')
456af69d88dSmrg        self.extent     = element.get('img_extent')
4573464ebd5Sriastradh
458af69d88dSmrg        self.img_xoff   = element.get('img_xoff')
459af69d88dSmrg        self.img_yoff   = element.get('img_yoff')
460af69d88dSmrg        self.img_zoff   = element.get('img_zoff')
461af69d88dSmrg        self.img_woff   = element.get('img_woff')
4623464ebd5Sriastradh
463af69d88dSmrg        self.img_format = element.get('img_format')
464af69d88dSmrg        self.img_type   = element.get('img_type')
465af69d88dSmrg        self.img_target = element.get('img_target')
4663464ebd5Sriastradh
467af69d88dSmrg        self.img_pad_dimensions = is_attr_true( element, 'img_pad_dimensions' )
468af69d88dSmrg        self.img_null_flag      = is_attr_true( element, 'img_null_flag' )
469af69d88dSmrg        self.img_send_null      = is_attr_true( element, 'img_send_null' )
4703464ebd5Sriastradh
471af69d88dSmrg        self.is_padding = is_attr_true( element, 'padding' )
472af69d88dSmrg        return
4733464ebd5Sriastradh
4743464ebd5Sriastradh
475af69d88dSmrg    def compatible(self, other):
476af69d88dSmrg        return 1
4773464ebd5Sriastradh
4783464ebd5Sriastradh
479af69d88dSmrg    def is_array(self):
480af69d88dSmrg        return self.is_pointer()
4813464ebd5Sriastradh
4823464ebd5Sriastradh
483af69d88dSmrg    def is_pointer(self):
484af69d88dSmrg        return self.type_expr.is_pointer()
4853464ebd5Sriastradh
4863464ebd5Sriastradh
487af69d88dSmrg    def is_image(self):
488af69d88dSmrg        if self.width:
489af69d88dSmrg            return 1
490af69d88dSmrg        else:
491af69d88dSmrg            return 0
4923464ebd5Sriastradh
4933464ebd5Sriastradh
494af69d88dSmrg    def is_variable_length(self):
4957ec681f3Smrg        return len(self.count_parameter_list) or self.counter or self.marshal_count
4963464ebd5Sriastradh
4973464ebd5Sriastradh
498af69d88dSmrg    def is_64_bit(self):
499af69d88dSmrg        count = self.type_expr.get_element_count()
500af69d88dSmrg        if count:
501af69d88dSmrg            if (self.size() / count) == 8:
502af69d88dSmrg                return 1
503af69d88dSmrg        else:
504af69d88dSmrg            if self.size() == 8:
505af69d88dSmrg                return 1
5063464ebd5Sriastradh
507af69d88dSmrg        return 0
5083464ebd5Sriastradh
5093464ebd5Sriastradh
510af69d88dSmrg    def string(self):
511af69d88dSmrg        return self.type_expr.original_string + " " + self.name
5123464ebd5Sriastradh
5133464ebd5Sriastradh
514af69d88dSmrg    def type_string(self):
515af69d88dSmrg        return self.type_expr.original_string
5163464ebd5Sriastradh
5173464ebd5Sriastradh
518af69d88dSmrg    def get_base_type_string(self):
519af69d88dSmrg        return self.type_expr.get_base_name()
5203464ebd5Sriastradh
5213464ebd5Sriastradh
522af69d88dSmrg    def get_dimensions(self):
523af69d88dSmrg        if not self.width:
524af69d88dSmrg            return [ 0, "0", "0", "0", "0" ]
5253464ebd5Sriastradh
526af69d88dSmrg        dim = 1
527af69d88dSmrg        w = self.width
528af69d88dSmrg        h = "1"
529af69d88dSmrg        d = "1"
530af69d88dSmrg        e = "1"
5313464ebd5Sriastradh
532af69d88dSmrg        if self.height:
533af69d88dSmrg            dim = 2
534af69d88dSmrg            h = self.height
5353464ebd5Sriastradh
536af69d88dSmrg        if self.depth:
537af69d88dSmrg            dim = 3
538af69d88dSmrg            d = self.depth
5393464ebd5Sriastradh
540af69d88dSmrg        if self.extent:
541af69d88dSmrg            dim = 4
542af69d88dSmrg            e = self.extent
5433464ebd5Sriastradh
544af69d88dSmrg        return [ dim, w, h, d, e ]
5453464ebd5Sriastradh
5463464ebd5Sriastradh
547af69d88dSmrg    def get_stack_size(self):
548af69d88dSmrg        return self.type_expr.get_stack_size()
5493464ebd5Sriastradh
5503464ebd5Sriastradh
551af69d88dSmrg    def size(self):
552af69d88dSmrg        if self.is_image():
553af69d88dSmrg            return 0
554af69d88dSmrg        else:
555af69d88dSmrg            return self.type_expr.get_element_size()
5563464ebd5Sriastradh
5573464ebd5Sriastradh
558af69d88dSmrg    def get_element_count(self):
559af69d88dSmrg        c = self.type_expr.get_element_count()
560af69d88dSmrg        if c == 0:
561af69d88dSmrg            return 1
5623464ebd5Sriastradh
563af69d88dSmrg        return c
5643464ebd5Sriastradh
5653464ebd5Sriastradh
5667ec681f3Smrg    def size_string(self, use_parens = 1, marshal = 0):
5677ec681f3Smrg        base_size_str = ""
5687ec681f3Smrg
5697ec681f3Smrg        count = self.get_element_count()
5707ec681f3Smrg        if count:
5717ec681f3Smrg            base_size_str = "%d * " % count
5727ec681f3Smrg
5737ec681f3Smrg        base_size_str += "sizeof(%s)" % ( self.get_base_type_string() )
5747ec681f3Smrg
5757ec681f3Smrg        if self.counter or self.count_parameter_list or (self.marshal_count and marshal):
576af69d88dSmrg            list = [ "compsize" ]
5773464ebd5Sriastradh
5787ec681f3Smrg            if self.marshal_count and marshal:
5797ec681f3Smrg                list = [ self.marshal_count ]
5807ec681f3Smrg            elif self.counter and self.count_parameter_list:
581af69d88dSmrg                list.append( self.counter )
582af69d88dSmrg            elif self.counter:
583af69d88dSmrg                list = [ self.counter ]
5843464ebd5Sriastradh
5857ec681f3Smrg            if self.size() > 1:
5867ec681f3Smrg                list.append( base_size_str )
5873464ebd5Sriastradh
588af69d88dSmrg            if len(list) > 1 and use_parens :
58901e04c3fSmrg                return "safe_mul(%s)" % ", ".join(list)
590af69d88dSmrg            else:
59101e04c3fSmrg                return " * ".join(list)
5923464ebd5Sriastradh
593af69d88dSmrg        elif self.is_image():
594af69d88dSmrg            return "compsize"
595af69d88dSmrg        else:
5967ec681f3Smrg            return base_size_str
5973464ebd5Sriastradh
5983464ebd5Sriastradh
599af69d88dSmrg    def format_string(self):
600af69d88dSmrg        if self.type_expr.original_string == "GLenum":
601af69d88dSmrg            return "0x%x"
602af69d88dSmrg        else:
603af69d88dSmrg            return self.type_expr.format_string()
604af69d88dSmrg
605af69d88dSmrg
606af69d88dSmrgclass gl_function( gl_item ):
607af69d88dSmrg    def __init__(self, element, context):
608af69d88dSmrg        self.context = context
609af69d88dSmrg        self.name = None
610af69d88dSmrg
611af69d88dSmrg        self.entry_points = []
612af69d88dSmrg        self.return_type = "void"
613af69d88dSmrg        self.parameters = []
614af69d88dSmrg        self.offset = -1
615af69d88dSmrg        self.initialized = 0
616af69d88dSmrg        self.images = []
617af69d88dSmrg        self.exec_flavor = 'mesa'
618af69d88dSmrg        self.desktop = True
619af69d88dSmrg        self.deprecated = None
62001e04c3fSmrg        self.has_no_error_variant = False
621af69d88dSmrg
622af69d88dSmrg        # self.api_map[api] is a decimal value indicating the earliest
623af69d88dSmrg        # version of the given API in which ANY alias for the function
624af69d88dSmrg        # exists.  The map only lists APIs which contain the function
625af69d88dSmrg        # in at least one version.  For example, for the ClipPlanex
6269f464c52Smaya        # function, self.api_map == { 'es1':
627af69d88dSmrg        # Decimal('1.1') }.
628af69d88dSmrg        self.api_map = {}
629af69d88dSmrg
63001e04c3fSmrg        self.assign_offset = False
631af69d88dSmrg
632af69d88dSmrg        self.static_entry_points = []
633af69d88dSmrg
634af69d88dSmrg        # Track the parameter string (for the function prototype)
635af69d88dSmrg        # for each entry-point.  This is done because some functions
636af69d88dSmrg        # change their prototype slightly when promoted from extension
637af69d88dSmrg        # to ARB extension to core.  glTexImage3DEXT and glTexImage3D
638af69d88dSmrg        # are good examples of this.  Scripts that need to generate
639af69d88dSmrg        # code for these differing aliases need to real prototype
640af69d88dSmrg        # for each entry-point.  Otherwise, they may generate code
641af69d88dSmrg        # that won't compile.
642af69d88dSmrg
643af69d88dSmrg        self.entry_point_parameters = {}
644af69d88dSmrg
645af69d88dSmrg        self.process_element( element )
646af69d88dSmrg
647af69d88dSmrg        return
648af69d88dSmrg
649af69d88dSmrg
650af69d88dSmrg    def process_element(self, element):
651af69d88dSmrg        name = element.get( "name" )
652af69d88dSmrg        alias = element.get( "alias" )
653af69d88dSmrg
6547ec681f3Smrg        # marshal isn't allowed with alias
6557ec681f3Smrg        assert not alias or not element.get('marshal')
6567ec681f3Smrg        assert not alias or not element.get('marshal_count')
6577ec681f3Smrg        assert not alias or not element.get('marshal_sync')
6587ec681f3Smrg        assert not alias or not element.get('marshal_call_after')
6597ec681f3Smrg
66001e04c3fSmrg        if name in static_data.functions:
661af69d88dSmrg            self.static_entry_points.append(name)
662af69d88dSmrg
663af69d88dSmrg        self.entry_points.append( name )
664af69d88dSmrg
665af69d88dSmrg        for api in ('es1', 'es2'):
666af69d88dSmrg            version_str = element.get(api, 'none')
667af69d88dSmrg            assert version_str is not None
668af69d88dSmrg            if version_str != 'none':
669af69d88dSmrg                version_decimal = Decimal(version_str)
670af69d88dSmrg                if api not in self.api_map or \
671af69d88dSmrg                        version_decimal < self.api_map[api]:
672af69d88dSmrg                    self.api_map[api] = version_decimal
673af69d88dSmrg
674af69d88dSmrg        exec_flavor = element.get('exec')
675af69d88dSmrg        if exec_flavor:
676af69d88dSmrg            self.exec_flavor = exec_flavor
677af69d88dSmrg
678af69d88dSmrg        deprecated = element.get('deprecated', 'none')
679af69d88dSmrg        if deprecated != 'none':
680af69d88dSmrg            self.deprecated = Decimal(deprecated)
681af69d88dSmrg
682af69d88dSmrg        if not is_attr_true(element, 'desktop', 'true'):
683af69d88dSmrg            self.desktop = False
684af69d88dSmrg
68501e04c3fSmrg        if self.has_no_error_variant or is_attr_true(element, 'no_error'):
68601e04c3fSmrg            self.has_no_error_variant = True
68701e04c3fSmrg        else:
68801e04c3fSmrg            self.has_no_error_variant = False
68901e04c3fSmrg
690af69d88dSmrg        if alias:
691af69d88dSmrg            true_name = alias
692af69d88dSmrg        else:
693af69d88dSmrg            true_name = name
694af69d88dSmrg
695af69d88dSmrg            # Only try to set the offset when a non-alias entry-point
696af69d88dSmrg            # is being processed.
697af69d88dSmrg
6989f464c52Smaya            if name in static_data.offsets and static_data.offsets[name] <= static_data.MAX_OFFSETS:
69901e04c3fSmrg                self.offset = static_data.offsets[name]
7009f464c52Smaya            elif name in static_data.offsets and static_data.offsets[name] > static_data.MAX_OFFSETS:
7019f464c52Smaya                self.offset = static_data.offsets[name]
7029f464c52Smaya                self.assign_offset = True
70301e04c3fSmrg            else:
7049f464c52Smaya                if self.exec_flavor != "skip":
7059f464c52Smaya                    raise RuntimeError("Entry-point %s is missing offset in static_data.py. Add one at the bottom of the list." % (name))
70601e04c3fSmrg                self.assign_offset = self.exec_flavor != "skip" or name in static_data.unused_functions
707af69d88dSmrg
708af69d88dSmrg        if not self.name:
709af69d88dSmrg            self.name = true_name
710af69d88dSmrg        elif self.name != true_name:
711af69d88dSmrg            raise RuntimeError("Function true name redefined.  Was %s, now %s." % (self.name, true_name))
712af69d88dSmrg
713af69d88dSmrg
714af69d88dSmrg        # There are two possible cases.  The first time an entry-point
715af69d88dSmrg        # with data is seen, self.initialized will be 0.  On that
716af69d88dSmrg        # pass, we just fill in the data.  The next time an
717af69d88dSmrg        # entry-point with data is seen, self.initialized will be 1.
718af69d88dSmrg        # On that pass we have to make that the new values match the
719af69d88dSmrg        # valuse from the previous entry-point.
720af69d88dSmrg
721af69d88dSmrg        parameters = []
722af69d88dSmrg        return_type = "void"
7237ec681f3Smrg        for child in element:
724af69d88dSmrg            if child.tag == "return":
725af69d88dSmrg                return_type = child.get( "type", "void" )
726af69d88dSmrg            elif child.tag == "param":
727af69d88dSmrg                param = self.context.factory.create_parameter(child, self.context)
728af69d88dSmrg                parameters.append( param )
7293464ebd5Sriastradh
7303464ebd5Sriastradh
731af69d88dSmrg        if self.initialized:
732af69d88dSmrg            if self.return_type != return_type:
733af69d88dSmrg                raise RuntimeError( "Return type changed in %s.  Was %s, now %s." % (name, self.return_type, return_type))
734af69d88dSmrg
735af69d88dSmrg            if len(parameters) != len(self.parameters):
736af69d88dSmrg                raise RuntimeError( "Parameter count mismatch in %s.  Was %d, now %d." % (name, len(self.parameters), len(parameters)))
7373464ebd5Sriastradh
738af69d88dSmrg            for j in range(0, len(parameters)):
739af69d88dSmrg                p1 = parameters[j]
740af69d88dSmrg                p2 = self.parameters[j]
741af69d88dSmrg                if not p1.compatible( p2 ):
742af69d88dSmrg                    raise RuntimeError( 'Parameter type mismatch in %s.  "%s" was "%s", now "%s".' % (name, p2.name, p2.type_expr.original_string, p1.type_expr.original_string))
743af69d88dSmrg
744af69d88dSmrg
745af69d88dSmrg        if true_name == name or not self.initialized:
746af69d88dSmrg            self.return_type = return_type
747af69d88dSmrg            self.parameters = parameters
748af69d88dSmrg
749af69d88dSmrg            for param in self.parameters:
750af69d88dSmrg                if param.is_image():
751af69d88dSmrg                    self.images.append( param )
752af69d88dSmrg
7537ec681f3Smrg        if list(element):
754af69d88dSmrg            self.initialized = 1
755af69d88dSmrg            self.entry_point_parameters[name] = parameters
756af69d88dSmrg        else:
757af69d88dSmrg            self.entry_point_parameters[name] = []
758af69d88dSmrg
759af69d88dSmrg        return
760af69d88dSmrg
761af69d88dSmrg    def filter_entry_points(self, entry_point_list):
762af69d88dSmrg        """Filter out entry points not in entry_point_list."""
763af69d88dSmrg        if not self.initialized:
764af69d88dSmrg            raise RuntimeError('%s is not initialized yet' % self.name)
765af69d88dSmrg
766af69d88dSmrg        entry_points = []
767af69d88dSmrg        for ent in self.entry_points:
768af69d88dSmrg            if ent not in entry_point_list:
769af69d88dSmrg                if ent in self.static_entry_points:
770af69d88dSmrg                    self.static_entry_points.remove(ent)
771af69d88dSmrg                self.entry_point_parameters.pop(ent)
772af69d88dSmrg            else:
773af69d88dSmrg                entry_points.append(ent)
774af69d88dSmrg
775af69d88dSmrg        if not entry_points:
776af69d88dSmrg            raise RuntimeError('%s has no entry point after filtering' % self.name)
7773464ebd5Sriastradh
778af69d88dSmrg        self.entry_points = entry_points
779af69d88dSmrg        if self.name not in entry_points:
780af69d88dSmrg            # use the first remaining entry point
781af69d88dSmrg            self.name = entry_points[0]
782af69d88dSmrg            self.parameters = self.entry_point_parameters[entry_points[0]]
7833464ebd5Sriastradh
784af69d88dSmrg    def get_images(self):
785af69d88dSmrg        """Return potentially empty list of input images."""
786af69d88dSmrg        return self.images
7873464ebd5Sriastradh
788af69d88dSmrg
789af69d88dSmrg    def parameterIterator(self, name = None):
790af69d88dSmrg        if name is not None:
79101e04c3fSmrg            return iter(self.entry_point_parameters[name]);
792af69d88dSmrg        else:
79301e04c3fSmrg            return iter(self.parameters);
7943464ebd5Sriastradh
7953464ebd5Sriastradh
796af69d88dSmrg    def get_parameter_string(self, entrypoint = None):
797af69d88dSmrg        if entrypoint:
798af69d88dSmrg            params = self.entry_point_parameters[ entrypoint ]
799af69d88dSmrg        else:
800af69d88dSmrg            params = self.parameters
8013464ebd5Sriastradh
802af69d88dSmrg        return create_parameter_string( params, 1 )
8033464ebd5Sriastradh
804af69d88dSmrg    def get_called_parameter_string(self):
805af69d88dSmrg        p_string = ""
806af69d88dSmrg        comma = ""
807af69d88dSmrg
808af69d88dSmrg        for p in self.parameterIterator():
809af69d88dSmrg            if p.is_padding:
810af69d88dSmrg                continue
811af69d88dSmrg            p_string = p_string + comma + p.name
812af69d88dSmrg            comma = ", "
8133464ebd5Sriastradh
814af69d88dSmrg        return p_string
8153464ebd5Sriastradh
8163464ebd5Sriastradh
817af69d88dSmrg    def is_abi(self):
818af69d88dSmrg        return (self.offset >= 0 and not self.assign_offset)
8193464ebd5Sriastradh
820af69d88dSmrg    def is_static_entry_point(self, name):
821af69d88dSmrg        return name in self.static_entry_points
8223464ebd5Sriastradh
823af69d88dSmrg    def dispatch_name(self):
824af69d88dSmrg        if self.name in self.static_entry_points:
825af69d88dSmrg            return self.name
826af69d88dSmrg        else:
827af69d88dSmrg            return "_dispatch_stub_%u" % (self.offset)
8283464ebd5Sriastradh
829af69d88dSmrg    def static_name(self, name):
830af69d88dSmrg        if name in self.static_entry_points:
831af69d88dSmrg            return name
832af69d88dSmrg        else:
833af69d88dSmrg            return "_dispatch_stub_%u" % (self.offset)
8343464ebd5Sriastradh
835af69d88dSmrgclass gl_item_factory(object):
836af69d88dSmrg    """Factory to create objects derived from gl_item."""
8373464ebd5Sriastradh
838af69d88dSmrg    def create_function(self, element, context):
839af69d88dSmrg        return gl_function(element, context)
8403464ebd5Sriastradh
841af69d88dSmrg    def create_type(self, element, context, category):
842af69d88dSmrg        return gl_type(element, context, category)
8433464ebd5Sriastradh
844af69d88dSmrg    def create_enum(self, element, context, category):
845af69d88dSmrg        return gl_enum(element, context, category)
8463464ebd5Sriastradh
847af69d88dSmrg    def create_parameter(self, element, context):
848af69d88dSmrg        return gl_parameter(element, context)
8493464ebd5Sriastradh
850af69d88dSmrg    def create_api(self):
851af69d88dSmrg        return gl_api(self)
8523464ebd5Sriastradh
8533464ebd5Sriastradh
854af69d88dSmrgclass gl_api(object):
855af69d88dSmrg    def __init__(self, factory):
85601e04c3fSmrg        self.functions_by_name = OrderedDict()
857af69d88dSmrg        self.enums_by_name = {}
858af69d88dSmrg        self.types_by_name = {}
8593464ebd5Sriastradh
860af69d88dSmrg        self.category_dict = {}
861af69d88dSmrg        self.categories = [{}, {}, {}, {}]
8623464ebd5Sriastradh
863af69d88dSmrg        self.factory = factory
8643464ebd5Sriastradh
865af69d88dSmrg        self.next_offset = 0
8663464ebd5Sriastradh
867af69d88dSmrg        typeexpr.create_initial_types()
868af69d88dSmrg        return
8693464ebd5Sriastradh
870af69d88dSmrg    def parse_file(self, file_name):
871af69d88dSmrg        doc = ET.parse( file_name )
872af69d88dSmrg        self.process_element(file_name, doc)
8733464ebd5Sriastradh
8743464ebd5Sriastradh
875af69d88dSmrg    def process_element(self, file_name, doc):
876af69d88dSmrg        element = doc.getroot()
877af69d88dSmrg        if element.tag == "OpenGLAPI":
878af69d88dSmrg            self.process_OpenGLAPI(file_name, element)
879af69d88dSmrg        return
8803464ebd5Sriastradh
8813464ebd5Sriastradh
882af69d88dSmrg    def process_OpenGLAPI(self, file_name, element):
8837ec681f3Smrg        for child in element:
884af69d88dSmrg            if child.tag == "category":
885af69d88dSmrg                self.process_category( child )
886af69d88dSmrg            elif child.tag == "OpenGLAPI":
887af69d88dSmrg                self.process_OpenGLAPI( file_name, child )
888af69d88dSmrg            elif child.tag == '{http://www.w3.org/2001/XInclude}include':
889af69d88dSmrg                href = child.get('href')
890af69d88dSmrg                href = os.path.join(os.path.dirname(file_name), href)
891af69d88dSmrg                self.parse_file(href)
8923464ebd5Sriastradh
893af69d88dSmrg        return
8943464ebd5Sriastradh
8953464ebd5Sriastradh
896af69d88dSmrg    def process_category(self, cat):
897af69d88dSmrg        cat_name = cat.get( "name" )
898af69d88dSmrg        cat_number = cat.get( "number" )
8993464ebd5Sriastradh
900af69d88dSmrg        [cat_type, key] = classify_category(cat_name, cat_number)
901af69d88dSmrg        self.categories[cat_type][key] = [cat_name, cat_number]
9023464ebd5Sriastradh
9037ec681f3Smrg        for child in cat:
904af69d88dSmrg            if child.tag == "function":
905af69d88dSmrg                func_name = real_function_name( child )
9063464ebd5Sriastradh
907af69d88dSmrg                temp_name = child.get( "name" )
908af69d88dSmrg                self.category_dict[ temp_name ] = [cat_name, cat_number]
9093464ebd5Sriastradh
91001e04c3fSmrg                if func_name in self.functions_by_name:
911af69d88dSmrg                    func = self.functions_by_name[ func_name ]
912af69d88dSmrg                    func.process_element( child )
913af69d88dSmrg                else:
914af69d88dSmrg                    func = self.factory.create_function( child, self )
915af69d88dSmrg                    self.functions_by_name[ func_name ] = func
9163464ebd5Sriastradh
917af69d88dSmrg                if func.offset >= self.next_offset:
918af69d88dSmrg                    self.next_offset = func.offset + 1
9193464ebd5Sriastradh
9203464ebd5Sriastradh
921af69d88dSmrg            elif child.tag == "enum":
922af69d88dSmrg                enum = self.factory.create_enum( child, self, cat_name )
923af69d88dSmrg                self.enums_by_name[ enum.name ] = enum
924af69d88dSmrg            elif child.tag == "type":
925af69d88dSmrg                t = self.factory.create_type( child, self, cat_name )
926af69d88dSmrg                self.types_by_name[ "GL" + t.name ] = t
9273464ebd5Sriastradh
928af69d88dSmrg        return
9293464ebd5Sriastradh
9303464ebd5Sriastradh
931af69d88dSmrg    def functionIterateByCategory(self, cat = None):
932af69d88dSmrg        """Iterate over functions by category.
9333464ebd5Sriastradh
934af69d88dSmrg        If cat is None, all known functions are iterated in category
935af69d88dSmrg        order.  See classify_category for details of the ordering.
936af69d88dSmrg        Within a category, functions are sorted by name.  If cat is
937af69d88dSmrg        not None, then only functions in that category are iterated.
938af69d88dSmrg        """
939af69d88dSmrg        lists = [{}, {}, {}, {}]
9403464ebd5Sriastradh
941af69d88dSmrg        for func in self.functionIterateAll():
942af69d88dSmrg            [cat_name, cat_number] = self.category_dict[func.name]
9433464ebd5Sriastradh
944af69d88dSmrg            if (cat == None) or (cat == cat_name):
945af69d88dSmrg                [func_cat_type, key] = classify_category(cat_name, cat_number)
9463464ebd5Sriastradh
94701e04c3fSmrg                if key not in lists[func_cat_type]:
948af69d88dSmrg                    lists[func_cat_type][key] = {}
9493464ebd5Sriastradh
950af69d88dSmrg                lists[func_cat_type][key][func.name] = func
9513464ebd5Sriastradh
9523464ebd5Sriastradh
953af69d88dSmrg        functions = []
954af69d88dSmrg        for func_cat_type in range(0,4):
95501e04c3fSmrg            keys = sorted(lists[func_cat_type].keys())
9563464ebd5Sriastradh
957af69d88dSmrg            for key in keys:
95801e04c3fSmrg                names = sorted(lists[func_cat_type][key].keys())
9593464ebd5Sriastradh
960af69d88dSmrg                for name in names:
961af69d88dSmrg                    functions.append(lists[func_cat_type][key][name])
9623464ebd5Sriastradh
96301e04c3fSmrg        return iter(functions)
9643464ebd5Sriastradh
9653464ebd5Sriastradh
966af69d88dSmrg    def functionIterateByOffset(self):
967af69d88dSmrg        max_offset = -1
96801e04c3fSmrg        for func in self.functions_by_name.values():
969af69d88dSmrg            if func.offset > max_offset:
970af69d88dSmrg                max_offset = func.offset
9713464ebd5Sriastradh
9723464ebd5Sriastradh
973af69d88dSmrg        temp = [None for i in range(0, max_offset + 1)]
97401e04c3fSmrg        for func in self.functions_by_name.values():
975af69d88dSmrg            if func.offset != -1:
976af69d88dSmrg                temp[ func.offset ] = func
9773464ebd5Sriastradh
9783464ebd5Sriastradh
979af69d88dSmrg        list = []
980af69d88dSmrg        for i in range(0, max_offset + 1):
981af69d88dSmrg            if temp[i]:
982af69d88dSmrg                list.append(temp[i])
9833464ebd5Sriastradh
98401e04c3fSmrg        return iter(list);
9853464ebd5Sriastradh
9863464ebd5Sriastradh
987af69d88dSmrg    def functionIterateAll(self):
98801e04c3fSmrg        return self.functions_by_name.values()
9893464ebd5Sriastradh
9903464ebd5Sriastradh
991af69d88dSmrg    def enumIterateByName(self):
99201e04c3fSmrg        keys = sorted(self.enums_by_name.keys())
9933464ebd5Sriastradh
994af69d88dSmrg        list = []
995af69d88dSmrg        for enum in keys:
996af69d88dSmrg            list.append( self.enums_by_name[ enum ] )
9973464ebd5Sriastradh
99801e04c3fSmrg        return iter(list)
9993464ebd5Sriastradh
10003464ebd5Sriastradh
1001af69d88dSmrg    def categoryIterate(self):
1002af69d88dSmrg        """Iterate over categories.
10033464ebd5Sriastradh
1004af69d88dSmrg        Iterate over all known categories in the order specified by
1005af69d88dSmrg        classify_category.  Each iterated value is a tuple of the
1006af69d88dSmrg        name and number (which may be None) of the category.
1007af69d88dSmrg        """
10083464ebd5Sriastradh
1009af69d88dSmrg        list = []
1010af69d88dSmrg        for cat_type in range(0,4):
101101e04c3fSmrg            keys = sorted(self.categories[cat_type].keys())
10123464ebd5Sriastradh
1013af69d88dSmrg            for key in keys:
1014af69d88dSmrg                list.append(self.categories[cat_type][key])
10153464ebd5Sriastradh
101601e04c3fSmrg        return iter(list)
10173464ebd5Sriastradh
10183464ebd5Sriastradh
1019af69d88dSmrg    def get_category_for_name( self, name ):
102001e04c3fSmrg        if name in self.category_dict:
1021af69d88dSmrg            return self.category_dict[name]
1022af69d88dSmrg        else:
1023af69d88dSmrg            return ["<unknown category>", None]
10243464ebd5Sriastradh
10253464ebd5Sriastradh
1026af69d88dSmrg    def typeIterate(self):
102701e04c3fSmrg        return self.types_by_name.values()
10283464ebd5Sriastradh
10293464ebd5Sriastradh
1030af69d88dSmrg    def find_type( self, type_name ):
1031af69d88dSmrg        if type_name in self.types_by_name:
1032af69d88dSmrg            return self.types_by_name[ type_name ].type_expr
1033af69d88dSmrg        else:
103401e04c3fSmrg            print("Unable to find base type matching \"%s\"." % (type_name))
1035af69d88dSmrg            return None
1036