1bf215546Sopenharmony_ci
2bf215546Sopenharmony_ci# (C) Copyright IBM Corporation 2004, 2005
3bf215546Sopenharmony_ci# All Rights Reserved.
4bf215546Sopenharmony_ci#
5bf215546Sopenharmony_ci# Permission is hereby granted, free of charge, to any person obtaining a
6bf215546Sopenharmony_ci# copy of this software and associated documentation files (the "Software"),
7bf215546Sopenharmony_ci# to deal in the Software without restriction, including without limitation
8bf215546Sopenharmony_ci# on the rights to use, copy, modify, merge, publish, distribute, sub
9bf215546Sopenharmony_ci# license, and/or sell copies of the Software, and to permit persons to whom
10bf215546Sopenharmony_ci# the Software is furnished to do so, subject to the following conditions:
11bf215546Sopenharmony_ci#
12bf215546Sopenharmony_ci# The above copyright notice and this permission notice (including the next
13bf215546Sopenharmony_ci# paragraph) shall be included in all copies or substantial portions of the
14bf215546Sopenharmony_ci# Software.
15bf215546Sopenharmony_ci#
16bf215546Sopenharmony_ci# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17bf215546Sopenharmony_ci# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18bf215546Sopenharmony_ci# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
19bf215546Sopenharmony_ci# IBM AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20bf215546Sopenharmony_ci# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21bf215546Sopenharmony_ci# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22bf215546Sopenharmony_ci# IN THE SOFTWARE.
23bf215546Sopenharmony_ci#
24bf215546Sopenharmony_ci# Authors:
25bf215546Sopenharmony_ci#    Ian Romanick <idr@us.ibm.com>
26bf215546Sopenharmony_ci
27bf215546Sopenharmony_cifrom collections import OrderedDict
28bf215546Sopenharmony_cifrom decimal import Decimal
29bf215546Sopenharmony_ciimport xml.etree.ElementTree as ET
30bf215546Sopenharmony_ciimport re, sys
31bf215546Sopenharmony_ciimport os.path
32bf215546Sopenharmony_ciimport typeexpr
33bf215546Sopenharmony_ciimport static_data
34bf215546Sopenharmony_ci
35bf215546Sopenharmony_ci
36bf215546Sopenharmony_cidef parse_GL_API( file_name, factory = None ):
37bf215546Sopenharmony_ci
38bf215546Sopenharmony_ci    if not factory:
39bf215546Sopenharmony_ci        factory = gl_item_factory()
40bf215546Sopenharmony_ci
41bf215546Sopenharmony_ci    api = factory.create_api()
42bf215546Sopenharmony_ci    api.parse_file( file_name )
43bf215546Sopenharmony_ci
44bf215546Sopenharmony_ci    # After the XML has been processed, we need to go back and assign
45bf215546Sopenharmony_ci    # dispatch offsets to the functions that request that their offsets
46bf215546Sopenharmony_ci    # be assigned by the scripts.  Typically this means all functions
47bf215546Sopenharmony_ci    # that are not part of the ABI.
48bf215546Sopenharmony_ci
49bf215546Sopenharmony_ci    for func in api.functionIterateByCategory():
50bf215546Sopenharmony_ci        if func.assign_offset and func.offset < 0:
51bf215546Sopenharmony_ci            func.offset = api.next_offset;
52bf215546Sopenharmony_ci            api.next_offset += 1
53bf215546Sopenharmony_ci
54bf215546Sopenharmony_ci    return api
55bf215546Sopenharmony_ci
56bf215546Sopenharmony_ci
57bf215546Sopenharmony_cidef is_attr_true( element, name, default = "false" ):
58bf215546Sopenharmony_ci    """Read a name value from an element's attributes.
59bf215546Sopenharmony_ci
60bf215546Sopenharmony_ci    The value read from the attribute list must be either 'true' or
61bf215546Sopenharmony_ci    'false'.  If the value is 'false', zero will be returned.  If the
62bf215546Sopenharmony_ci    value is 'true', non-zero will be returned.  An exception will be
63bf215546Sopenharmony_ci    raised for any other value."""
64bf215546Sopenharmony_ci
65bf215546Sopenharmony_ci    value = element.get( name, default )
66bf215546Sopenharmony_ci    if value == "true":
67bf215546Sopenharmony_ci        return 1
68bf215546Sopenharmony_ci    elif value == "false":
69bf215546Sopenharmony_ci        return 0
70bf215546Sopenharmony_ci    else:
71bf215546Sopenharmony_ci        raise RuntimeError('Invalid value "%s" for boolean "%s".' % (value, name))
72bf215546Sopenharmony_ci
73bf215546Sopenharmony_ci
74bf215546Sopenharmony_ciclass gl_print_base(object):
75bf215546Sopenharmony_ci    """Base class of all API pretty-printers.
76bf215546Sopenharmony_ci
77bf215546Sopenharmony_ci    In the model-view-controller pattern, this is the view.  Any derived
78bf215546Sopenharmony_ci    class will want to over-ride the printBody, printRealHader, and
79bf215546Sopenharmony_ci    printRealFooter methods.  Some derived classes may want to over-ride
80bf215546Sopenharmony_ci    printHeader and printFooter, or even Print (though this is unlikely).
81bf215546Sopenharmony_ci    """
82bf215546Sopenharmony_ci
83bf215546Sopenharmony_ci    def __init__(self):
84bf215546Sopenharmony_ci        # Name of the script that is generating the output file.
85bf215546Sopenharmony_ci        # Every derived class should set this to the name of its
86bf215546Sopenharmony_ci        # source file.
87bf215546Sopenharmony_ci
88bf215546Sopenharmony_ci        self.name = "a"
89bf215546Sopenharmony_ci
90bf215546Sopenharmony_ci
91bf215546Sopenharmony_ci        # License on the *generated* source file.  This may differ
92bf215546Sopenharmony_ci        # from the license on the script that is generating the file.
93bf215546Sopenharmony_ci        # Every derived class should set this to some reasonable
94bf215546Sopenharmony_ci        # value.
95bf215546Sopenharmony_ci        #
96bf215546Sopenharmony_ci        # See license.py for an example of a reasonable value.
97bf215546Sopenharmony_ci
98bf215546Sopenharmony_ci        self.license = "The license for this file is unspecified."
99bf215546Sopenharmony_ci
100bf215546Sopenharmony_ci
101bf215546Sopenharmony_ci        # The header_tag is the name of the C preprocessor define
102bf215546Sopenharmony_ci        # used to prevent multiple inclusion.  Typically only
103bf215546Sopenharmony_ci        # generated C header files need this to be set.  Setting it
104bf215546Sopenharmony_ci        # causes code to be generated automatically in printHeader
105bf215546Sopenharmony_ci        # and printFooter.
106bf215546Sopenharmony_ci
107bf215546Sopenharmony_ci        self.header_tag = None
108bf215546Sopenharmony_ci
109bf215546Sopenharmony_ci
110bf215546Sopenharmony_ci        # List of file-private defines that must be undefined at the
111bf215546Sopenharmony_ci        # end of the file.  This can be used in header files to define
112bf215546Sopenharmony_ci        # names for use in the file, then undefine them at the end of
113bf215546Sopenharmony_ci        # the header file.
114bf215546Sopenharmony_ci
115bf215546Sopenharmony_ci        self.undef_list = []
116bf215546Sopenharmony_ci        return
117bf215546Sopenharmony_ci
118bf215546Sopenharmony_ci
119bf215546Sopenharmony_ci    def Print(self, api):
120bf215546Sopenharmony_ci        self.printHeader()
121bf215546Sopenharmony_ci        self.printBody(api)
122bf215546Sopenharmony_ci        self.printFooter()
123bf215546Sopenharmony_ci        return
124bf215546Sopenharmony_ci
125bf215546Sopenharmony_ci
126bf215546Sopenharmony_ci    def printHeader(self):
127bf215546Sopenharmony_ci        """Print the header associated with all files and call the printRealHeader method."""
128bf215546Sopenharmony_ci
129bf215546Sopenharmony_ci        print('/* DO NOT EDIT - This file generated automatically by %s script */' \
130bf215546Sopenharmony_ci                % (self.name))
131bf215546Sopenharmony_ci        print('')
132bf215546Sopenharmony_ci        print('/*')
133bf215546Sopenharmony_ci        print((' * ' + self.license.replace('\n', '\n * ')).replace(' \n', '\n'))
134bf215546Sopenharmony_ci        print(' */')
135bf215546Sopenharmony_ci        print('')
136bf215546Sopenharmony_ci        if self.header_tag:
137bf215546Sopenharmony_ci            print('#if !defined( %s )' % (self.header_tag))
138bf215546Sopenharmony_ci            print('#  define %s' % (self.header_tag))
139bf215546Sopenharmony_ci            print('')
140bf215546Sopenharmony_ci        self.printRealHeader();
141bf215546Sopenharmony_ci        return
142bf215546Sopenharmony_ci
143bf215546Sopenharmony_ci
144bf215546Sopenharmony_ci    def printFooter(self):
145bf215546Sopenharmony_ci        """Print the header associated with all files and call the printRealFooter method."""
146bf215546Sopenharmony_ci
147bf215546Sopenharmony_ci        self.printRealFooter()
148bf215546Sopenharmony_ci
149bf215546Sopenharmony_ci        if self.undef_list:
150bf215546Sopenharmony_ci            print('')
151bf215546Sopenharmony_ci            for u in self.undef_list:
152bf215546Sopenharmony_ci                print("#  undef %s" % (u))
153bf215546Sopenharmony_ci
154bf215546Sopenharmony_ci        if self.header_tag:
155bf215546Sopenharmony_ci            print('')
156bf215546Sopenharmony_ci            print('#endif /* !defined( %s ) */' % (self.header_tag))
157bf215546Sopenharmony_ci
158bf215546Sopenharmony_ci
159bf215546Sopenharmony_ci    def printRealHeader(self):
160bf215546Sopenharmony_ci        """Print the "real" header for the created file.
161bf215546Sopenharmony_ci
162bf215546Sopenharmony_ci        In the base class, this function is empty.  All derived
163bf215546Sopenharmony_ci        classes should over-ride this function."""
164bf215546Sopenharmony_ci        return
165bf215546Sopenharmony_ci
166bf215546Sopenharmony_ci
167bf215546Sopenharmony_ci    def printRealFooter(self):
168bf215546Sopenharmony_ci        """Print the "real" footer for the created file.
169bf215546Sopenharmony_ci
170bf215546Sopenharmony_ci        In the base class, this function is empty.  All derived
171bf215546Sopenharmony_ci        classes should over-ride this function."""
172bf215546Sopenharmony_ci        return
173bf215546Sopenharmony_ci
174bf215546Sopenharmony_ci
175bf215546Sopenharmony_ci    def printPure(self):
176bf215546Sopenharmony_ci        """Conditionally define `PURE' function attribute.
177bf215546Sopenharmony_ci
178bf215546Sopenharmony_ci        Conditionally defines a preprocessor macro `PURE' that wraps
179bf215546Sopenharmony_ci        GCC's `pure' function attribute.  The conditional code can be
180bf215546Sopenharmony_ci        easilly adapted to other compilers that support a similar
181bf215546Sopenharmony_ci        feature.
182bf215546Sopenharmony_ci
183bf215546Sopenharmony_ci        The name is also added to the file's undef_list.
184bf215546Sopenharmony_ci        """
185bf215546Sopenharmony_ci        self.undef_list.append("PURE")
186bf215546Sopenharmony_ci        print("""#  if defined(__GNUC__) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590))
187bf215546Sopenharmony_ci#    define PURE __attribute__((pure))
188bf215546Sopenharmony_ci#  else
189bf215546Sopenharmony_ci#    define PURE
190bf215546Sopenharmony_ci#  endif""")
191bf215546Sopenharmony_ci        return
192bf215546Sopenharmony_ci
193bf215546Sopenharmony_ci
194bf215546Sopenharmony_ci    def printFastcall(self):
195bf215546Sopenharmony_ci        """Conditionally define `FASTCALL' function attribute.
196bf215546Sopenharmony_ci
197bf215546Sopenharmony_ci        Conditionally defines a preprocessor macro `FASTCALL' that
198bf215546Sopenharmony_ci        wraps GCC's `fastcall' function attribute.  The conditional
199bf215546Sopenharmony_ci        code can be easilly adapted to other compilers that support a
200bf215546Sopenharmony_ci        similar feature.
201bf215546Sopenharmony_ci
202bf215546Sopenharmony_ci        The name is also added to the file's undef_list.
203bf215546Sopenharmony_ci        """
204bf215546Sopenharmony_ci
205bf215546Sopenharmony_ci        self.undef_list.append("FASTCALL")
206bf215546Sopenharmony_ci        print("""#  if defined(__i386__) && defined(__GNUC__) && !defined(__CYGWIN__) && !defined(__MINGW32__)
207bf215546Sopenharmony_ci#    define FASTCALL __attribute__((fastcall))
208bf215546Sopenharmony_ci#  else
209bf215546Sopenharmony_ci#    define FASTCALL
210bf215546Sopenharmony_ci#  endif""")
211bf215546Sopenharmony_ci        return
212bf215546Sopenharmony_ci
213bf215546Sopenharmony_ci
214bf215546Sopenharmony_ci    def printVisibility(self, S, s):
215bf215546Sopenharmony_ci        """Conditionally define visibility function attribute.
216bf215546Sopenharmony_ci
217bf215546Sopenharmony_ci        Conditionally defines a preprocessor macro name S that wraps
218bf215546Sopenharmony_ci        GCC's visibility function attribute.  The visibility used is
219bf215546Sopenharmony_ci        the parameter s.  The conditional code can be easilly adapted
220bf215546Sopenharmony_ci        to other compilers that support a similar feature.
221bf215546Sopenharmony_ci
222bf215546Sopenharmony_ci        The name is also added to the file's undef_list.
223bf215546Sopenharmony_ci        """
224bf215546Sopenharmony_ci
225bf215546Sopenharmony_ci        self.undef_list.append(S)
226bf215546Sopenharmony_ci        print("""#  if defined(__GNUC__) && !defined(__CYGWIN__) && !defined(__MINGW32__)
227bf215546Sopenharmony_ci#    define %s  __attribute__((visibility("%s")))
228bf215546Sopenharmony_ci#  else
229bf215546Sopenharmony_ci#    define %s
230bf215546Sopenharmony_ci#  endif""" % (S, s, S))
231bf215546Sopenharmony_ci        return
232bf215546Sopenharmony_ci
233bf215546Sopenharmony_ci
234bf215546Sopenharmony_ci    def printNoinline(self):
235bf215546Sopenharmony_ci        """Conditionally define `NOINLINE' function attribute.
236bf215546Sopenharmony_ci
237bf215546Sopenharmony_ci        Conditionally defines a preprocessor macro `NOINLINE' that
238bf215546Sopenharmony_ci        wraps GCC's `noinline' function attribute.  The conditional
239bf215546Sopenharmony_ci        code can be easilly adapted to other compilers that support a
240bf215546Sopenharmony_ci        similar feature.
241bf215546Sopenharmony_ci
242bf215546Sopenharmony_ci        The name is also added to the file's undef_list.
243bf215546Sopenharmony_ci        """
244bf215546Sopenharmony_ci
245bf215546Sopenharmony_ci        self.undef_list.append("NOINLINE")
246bf215546Sopenharmony_ci        print("""#  if defined(__GNUC__)
247bf215546Sopenharmony_ci#    define NOINLINE __attribute__((noinline))
248bf215546Sopenharmony_ci#  else
249bf215546Sopenharmony_ci#    define NOINLINE
250bf215546Sopenharmony_ci#  endif""")
251bf215546Sopenharmony_ci        return
252bf215546Sopenharmony_ci
253bf215546Sopenharmony_ci
254bf215546Sopenharmony_cidef real_function_name(element):
255bf215546Sopenharmony_ci    name = element.get( "name" )
256bf215546Sopenharmony_ci    alias = element.get( "alias" )
257bf215546Sopenharmony_ci
258bf215546Sopenharmony_ci    if alias:
259bf215546Sopenharmony_ci        return alias
260bf215546Sopenharmony_ci    else:
261bf215546Sopenharmony_ci        return name
262bf215546Sopenharmony_ci
263bf215546Sopenharmony_ci
264bf215546Sopenharmony_cidef real_category_name(c):
265bf215546Sopenharmony_ci    if re.compile("[1-9][0-9]*[.][0-9]+").match(c):
266bf215546Sopenharmony_ci        return "GL_VERSION_" + c.replace(".", "_")
267bf215546Sopenharmony_ci    else:
268bf215546Sopenharmony_ci        return c
269bf215546Sopenharmony_ci
270bf215546Sopenharmony_ci
271bf215546Sopenharmony_cidef classify_category(name, number):
272bf215546Sopenharmony_ci    """Based on the category name and number, select a numerical class for it.
273bf215546Sopenharmony_ci
274bf215546Sopenharmony_ci    Categories are divided into four classes numbered 0 through 3.  The
275bf215546Sopenharmony_ci    classes are:
276bf215546Sopenharmony_ci
277bf215546Sopenharmony_ci            0. Core GL versions, sorted by version number.
278bf215546Sopenharmony_ci            1. ARB extensions, sorted by extension number.
279bf215546Sopenharmony_ci            2. Non-ARB extensions, sorted by extension number.
280bf215546Sopenharmony_ci            3. Un-numbered extensions, sorted by extension name.
281bf215546Sopenharmony_ci    """
282bf215546Sopenharmony_ci
283bf215546Sopenharmony_ci    try:
284bf215546Sopenharmony_ci        core_version = float(name)
285bf215546Sopenharmony_ci    except Exception:
286bf215546Sopenharmony_ci        core_version = 0.0
287bf215546Sopenharmony_ci
288bf215546Sopenharmony_ci    if core_version > 0.0:
289bf215546Sopenharmony_ci        cat_type = 0
290bf215546Sopenharmony_ci        key = name
291bf215546Sopenharmony_ci    elif name.startswith("GL_ARB_") or name.startswith("GLX_ARB_") or name.startswith("WGL_ARB_"):
292bf215546Sopenharmony_ci        cat_type = 1
293bf215546Sopenharmony_ci        key = int(number)
294bf215546Sopenharmony_ci    else:
295bf215546Sopenharmony_ci        if number != None:
296bf215546Sopenharmony_ci            cat_type = 2
297bf215546Sopenharmony_ci            key = int(number)
298bf215546Sopenharmony_ci        else:
299bf215546Sopenharmony_ci            cat_type = 3
300bf215546Sopenharmony_ci            key = name
301bf215546Sopenharmony_ci
302bf215546Sopenharmony_ci
303bf215546Sopenharmony_ci    return [cat_type, key]
304bf215546Sopenharmony_ci
305bf215546Sopenharmony_ci
306bf215546Sopenharmony_cidef create_parameter_string(parameters, include_names):
307bf215546Sopenharmony_ci    """Create a parameter string from a list of gl_parameters."""
308bf215546Sopenharmony_ci
309bf215546Sopenharmony_ci    list = []
310bf215546Sopenharmony_ci    for p in parameters:
311bf215546Sopenharmony_ci        if p.is_padding:
312bf215546Sopenharmony_ci            continue
313bf215546Sopenharmony_ci
314bf215546Sopenharmony_ci        if include_names:
315bf215546Sopenharmony_ci            list.append( p.string() )
316bf215546Sopenharmony_ci        else:
317bf215546Sopenharmony_ci            list.append( p.type_string() )
318bf215546Sopenharmony_ci
319bf215546Sopenharmony_ci    if len(list) == 0: list = ["void"]
320bf215546Sopenharmony_ci
321bf215546Sopenharmony_ci    return ", ".join(list)
322bf215546Sopenharmony_ci
323bf215546Sopenharmony_ci
324bf215546Sopenharmony_ciclass gl_item(object):
325bf215546Sopenharmony_ci    def __init__(self, element, context, category):
326bf215546Sopenharmony_ci        self.context = context
327bf215546Sopenharmony_ci        self.name = element.get( "name" )
328bf215546Sopenharmony_ci        self.category = real_category_name( category )
329bf215546Sopenharmony_ci
330bf215546Sopenharmony_ci        return
331bf215546Sopenharmony_ci
332bf215546Sopenharmony_ci
333bf215546Sopenharmony_ciclass gl_type( gl_item ):
334bf215546Sopenharmony_ci    def __init__(self, element, context, category):
335bf215546Sopenharmony_ci        gl_item.__init__(self, element, context, category)
336bf215546Sopenharmony_ci        self.size = int( element.get( "size" ), 0 )
337bf215546Sopenharmony_ci
338bf215546Sopenharmony_ci        te = typeexpr.type_expression( None )
339bf215546Sopenharmony_ci        tn = typeexpr.type_node()
340bf215546Sopenharmony_ci        tn.size = int( element.get( "size" ), 0 )
341bf215546Sopenharmony_ci        tn.integer = not is_attr_true( element, "float" )
342bf215546Sopenharmony_ci        tn.unsigned = is_attr_true( element, "unsigned" )
343bf215546Sopenharmony_ci        tn.pointer = is_attr_true( element, "pointer" )
344bf215546Sopenharmony_ci        tn.name = "GL" + self.name
345bf215546Sopenharmony_ci        te.set_base_type_node( tn )
346bf215546Sopenharmony_ci
347bf215546Sopenharmony_ci        self.type_expr = te
348bf215546Sopenharmony_ci        return
349bf215546Sopenharmony_ci
350bf215546Sopenharmony_ci
351bf215546Sopenharmony_ci    def get_type_expression(self):
352bf215546Sopenharmony_ci        return self.type_expr
353bf215546Sopenharmony_ci
354bf215546Sopenharmony_ci
355bf215546Sopenharmony_ciclass gl_enum( gl_item ):
356bf215546Sopenharmony_ci    def __init__(self, element, context, category):
357bf215546Sopenharmony_ci        gl_item.__init__(self, element, context, category)
358bf215546Sopenharmony_ci        self.value = int( element.get( "value" ), 0 )
359bf215546Sopenharmony_ci
360bf215546Sopenharmony_ci        temp = element.get( "count" )
361bf215546Sopenharmony_ci        if not temp or temp == "?":
362bf215546Sopenharmony_ci            self.default_count = -1
363bf215546Sopenharmony_ci        else:
364bf215546Sopenharmony_ci            try:
365bf215546Sopenharmony_ci                c = int(temp)
366bf215546Sopenharmony_ci            except Exception:
367bf215546Sopenharmony_ci                raise RuntimeError('Invalid count value "%s" for enum "%s" in function "%s" when an integer was expected.' % (temp, self.name, n))
368bf215546Sopenharmony_ci
369bf215546Sopenharmony_ci            self.default_count = c
370bf215546Sopenharmony_ci
371bf215546Sopenharmony_ci        return
372bf215546Sopenharmony_ci
373bf215546Sopenharmony_ci
374bf215546Sopenharmony_ci    def priority(self):
375bf215546Sopenharmony_ci        """Calculate a 'priority' for this enum name.
376bf215546Sopenharmony_ci
377bf215546Sopenharmony_ci        When an enum is looked up by number, there may be many
378bf215546Sopenharmony_ci        possible names, but only one is the 'prefered' name.  The
379bf215546Sopenharmony_ci        priority is used to select which name is the 'best'.
380bf215546Sopenharmony_ci
381bf215546Sopenharmony_ci        Highest precedence is given to core GL name.  ARB extension
382bf215546Sopenharmony_ci        names have the next highest, followed by EXT extension names.
383bf215546Sopenharmony_ci        Vendor extension names are the lowest.
384bf215546Sopenharmony_ci        """
385bf215546Sopenharmony_ci
386bf215546Sopenharmony_ci        if self.name.endswith( "_BIT" ):
387bf215546Sopenharmony_ci            bias = 1
388bf215546Sopenharmony_ci        else:
389bf215546Sopenharmony_ci            bias = 0
390bf215546Sopenharmony_ci
391bf215546Sopenharmony_ci        if self.category.startswith( "GL_VERSION_" ):
392bf215546Sopenharmony_ci            priority = 0
393bf215546Sopenharmony_ci        elif self.category.startswith( "GL_ARB_" ):
394bf215546Sopenharmony_ci            priority = 2
395bf215546Sopenharmony_ci        elif self.category.startswith( "GL_EXT_" ):
396bf215546Sopenharmony_ci            priority = 4
397bf215546Sopenharmony_ci        else:
398bf215546Sopenharmony_ci            priority = 6
399bf215546Sopenharmony_ci
400bf215546Sopenharmony_ci        return priority + bias
401bf215546Sopenharmony_ci
402bf215546Sopenharmony_ci
403bf215546Sopenharmony_ci
404bf215546Sopenharmony_ciclass gl_parameter(object):
405bf215546Sopenharmony_ci    def __init__(self, element, context):
406bf215546Sopenharmony_ci        self.name = element.get( "name" )
407bf215546Sopenharmony_ci
408bf215546Sopenharmony_ci        ts = element.get( "type" )
409bf215546Sopenharmony_ci        self.type_expr = typeexpr.type_expression( ts, context )
410bf215546Sopenharmony_ci
411bf215546Sopenharmony_ci        temp = element.get( "variable_param" )
412bf215546Sopenharmony_ci        if temp:
413bf215546Sopenharmony_ci            self.count_parameter_list = temp.split( ' ' )
414bf215546Sopenharmony_ci        else:
415bf215546Sopenharmony_ci            self.count_parameter_list = []
416bf215546Sopenharmony_ci
417bf215546Sopenharmony_ci        # The count tag can be either a numeric string or the name of
418bf215546Sopenharmony_ci        # a variable.  If it is the name of a variable, the int(c)
419bf215546Sopenharmony_ci        # statement will throw an exception, and the except block will
420bf215546Sopenharmony_ci        # take over.
421bf215546Sopenharmony_ci
422bf215546Sopenharmony_ci        c = element.get( "count" )
423bf215546Sopenharmony_ci        try:
424bf215546Sopenharmony_ci            count = int(c)
425bf215546Sopenharmony_ci            self.count = count
426bf215546Sopenharmony_ci            self.counter = None
427bf215546Sopenharmony_ci        except Exception:
428bf215546Sopenharmony_ci            count = 1
429bf215546Sopenharmony_ci            self.count = 0
430bf215546Sopenharmony_ci            self.counter = c
431bf215546Sopenharmony_ci
432bf215546Sopenharmony_ci        self.marshal_count = element.get("marshal_count")
433bf215546Sopenharmony_ci        self.count_scale = int(element.get( "count_scale", "1" ))
434bf215546Sopenharmony_ci
435bf215546Sopenharmony_ci        elements = (count * self.count_scale)
436bf215546Sopenharmony_ci        if elements == 1:
437bf215546Sopenharmony_ci            elements = 0
438bf215546Sopenharmony_ci
439bf215546Sopenharmony_ci        #if ts == "GLdouble":
440bf215546Sopenharmony_ci        #	print '/* stack size -> %s = %u (before)*/' % (self.name, self.type_expr.get_stack_size())
441bf215546Sopenharmony_ci        #	print '/* # elements = %u */' % (elements)
442bf215546Sopenharmony_ci        self.type_expr.set_elements( elements )
443bf215546Sopenharmony_ci        #if ts == "GLdouble":
444bf215546Sopenharmony_ci        #	print '/* stack size -> %s = %u (after) */' % (self.name, self.type_expr.get_stack_size())
445bf215546Sopenharmony_ci
446bf215546Sopenharmony_ci        self.is_client_only = is_attr_true( element, 'client_only' )
447bf215546Sopenharmony_ci        self.is_counter     = is_attr_true( element, 'counter' )
448bf215546Sopenharmony_ci        self.is_output      = is_attr_true( element, 'output' )
449bf215546Sopenharmony_ci
450bf215546Sopenharmony_ci
451bf215546Sopenharmony_ci        # Pixel data has special parameters.
452bf215546Sopenharmony_ci
453bf215546Sopenharmony_ci        self.width      = element.get('img_width')
454bf215546Sopenharmony_ci        self.height     = element.get('img_height')
455bf215546Sopenharmony_ci        self.depth      = element.get('img_depth')
456bf215546Sopenharmony_ci        self.extent     = element.get('img_extent')
457bf215546Sopenharmony_ci
458bf215546Sopenharmony_ci        self.img_xoff   = element.get('img_xoff')
459bf215546Sopenharmony_ci        self.img_yoff   = element.get('img_yoff')
460bf215546Sopenharmony_ci        self.img_zoff   = element.get('img_zoff')
461bf215546Sopenharmony_ci        self.img_woff   = element.get('img_woff')
462bf215546Sopenharmony_ci
463bf215546Sopenharmony_ci        self.img_format = element.get('img_format')
464bf215546Sopenharmony_ci        self.img_type   = element.get('img_type')
465bf215546Sopenharmony_ci        self.img_target = element.get('img_target')
466bf215546Sopenharmony_ci
467bf215546Sopenharmony_ci        self.img_pad_dimensions = is_attr_true( element, 'img_pad_dimensions' )
468bf215546Sopenharmony_ci        self.img_null_flag      = is_attr_true( element, 'img_null_flag' )
469bf215546Sopenharmony_ci        self.img_send_null      = is_attr_true( element, 'img_send_null' )
470bf215546Sopenharmony_ci
471bf215546Sopenharmony_ci        self.is_padding = is_attr_true( element, 'padding' )
472bf215546Sopenharmony_ci        return
473bf215546Sopenharmony_ci
474bf215546Sopenharmony_ci
475bf215546Sopenharmony_ci    def compatible(self, other):
476bf215546Sopenharmony_ci        return 1
477bf215546Sopenharmony_ci
478bf215546Sopenharmony_ci
479bf215546Sopenharmony_ci    def is_array(self):
480bf215546Sopenharmony_ci        return self.is_pointer()
481bf215546Sopenharmony_ci
482bf215546Sopenharmony_ci
483bf215546Sopenharmony_ci    def is_pointer(self):
484bf215546Sopenharmony_ci        return self.type_expr.is_pointer()
485bf215546Sopenharmony_ci
486bf215546Sopenharmony_ci
487bf215546Sopenharmony_ci    def is_image(self):
488bf215546Sopenharmony_ci        if self.width:
489bf215546Sopenharmony_ci            return 1
490bf215546Sopenharmony_ci        else:
491bf215546Sopenharmony_ci            return 0
492bf215546Sopenharmony_ci
493bf215546Sopenharmony_ci
494bf215546Sopenharmony_ci    def is_variable_length(self):
495bf215546Sopenharmony_ci        return len(self.count_parameter_list) or self.counter or self.marshal_count
496bf215546Sopenharmony_ci
497bf215546Sopenharmony_ci
498bf215546Sopenharmony_ci    def is_64_bit(self):
499bf215546Sopenharmony_ci        count = self.type_expr.get_element_count()
500bf215546Sopenharmony_ci        if count:
501bf215546Sopenharmony_ci            if (self.size() / count) == 8:
502bf215546Sopenharmony_ci                return 1
503bf215546Sopenharmony_ci        else:
504bf215546Sopenharmony_ci            if self.size() == 8:
505bf215546Sopenharmony_ci                return 1
506bf215546Sopenharmony_ci
507bf215546Sopenharmony_ci        return 0
508bf215546Sopenharmony_ci
509bf215546Sopenharmony_ci
510bf215546Sopenharmony_ci    def string(self):
511bf215546Sopenharmony_ci        return self.type_expr.original_string + " " + self.name
512bf215546Sopenharmony_ci
513bf215546Sopenharmony_ci
514bf215546Sopenharmony_ci    def type_string(self):
515bf215546Sopenharmony_ci        return self.type_expr.original_string
516bf215546Sopenharmony_ci
517bf215546Sopenharmony_ci
518bf215546Sopenharmony_ci    def get_base_type_string(self):
519bf215546Sopenharmony_ci        return self.type_expr.get_base_name()
520bf215546Sopenharmony_ci
521bf215546Sopenharmony_ci
522bf215546Sopenharmony_ci    def get_dimensions(self):
523bf215546Sopenharmony_ci        if not self.width:
524bf215546Sopenharmony_ci            return [ 0, "0", "0", "0", "0" ]
525bf215546Sopenharmony_ci
526bf215546Sopenharmony_ci        dim = 1
527bf215546Sopenharmony_ci        w = self.width
528bf215546Sopenharmony_ci        h = "1"
529bf215546Sopenharmony_ci        d = "1"
530bf215546Sopenharmony_ci        e = "1"
531bf215546Sopenharmony_ci
532bf215546Sopenharmony_ci        if self.height:
533bf215546Sopenharmony_ci            dim = 2
534bf215546Sopenharmony_ci            h = self.height
535bf215546Sopenharmony_ci
536bf215546Sopenharmony_ci        if self.depth:
537bf215546Sopenharmony_ci            dim = 3
538bf215546Sopenharmony_ci            d = self.depth
539bf215546Sopenharmony_ci
540bf215546Sopenharmony_ci        if self.extent:
541bf215546Sopenharmony_ci            dim = 4
542bf215546Sopenharmony_ci            e = self.extent
543bf215546Sopenharmony_ci
544bf215546Sopenharmony_ci        return [ dim, w, h, d, e ]
545bf215546Sopenharmony_ci
546bf215546Sopenharmony_ci
547bf215546Sopenharmony_ci    def get_stack_size(self):
548bf215546Sopenharmony_ci        return self.type_expr.get_stack_size()
549bf215546Sopenharmony_ci
550bf215546Sopenharmony_ci
551bf215546Sopenharmony_ci    def size(self):
552bf215546Sopenharmony_ci        if self.is_image():
553bf215546Sopenharmony_ci            return 0
554bf215546Sopenharmony_ci        else:
555bf215546Sopenharmony_ci            return self.type_expr.get_element_size()
556bf215546Sopenharmony_ci
557bf215546Sopenharmony_ci
558bf215546Sopenharmony_ci    def get_element_count(self):
559bf215546Sopenharmony_ci        c = self.type_expr.get_element_count()
560bf215546Sopenharmony_ci        if c == 0:
561bf215546Sopenharmony_ci            return 1
562bf215546Sopenharmony_ci
563bf215546Sopenharmony_ci        return c
564bf215546Sopenharmony_ci
565bf215546Sopenharmony_ci
566bf215546Sopenharmony_ci    def size_string(self, use_parens = 1, marshal = 0):
567bf215546Sopenharmony_ci        base_size_str = ""
568bf215546Sopenharmony_ci
569bf215546Sopenharmony_ci        count = self.get_element_count()
570bf215546Sopenharmony_ci        if count:
571bf215546Sopenharmony_ci            base_size_str = "%d * " % count
572bf215546Sopenharmony_ci
573bf215546Sopenharmony_ci        base_size_str += "sizeof(%s)" % ( self.get_base_type_string() )
574bf215546Sopenharmony_ci
575bf215546Sopenharmony_ci        if self.counter or self.count_parameter_list or (self.marshal_count and marshal):
576bf215546Sopenharmony_ci            list = [ "compsize" ]
577bf215546Sopenharmony_ci
578bf215546Sopenharmony_ci            if self.marshal_count and marshal:
579bf215546Sopenharmony_ci                list = [ self.marshal_count ]
580bf215546Sopenharmony_ci            elif self.counter and self.count_parameter_list:
581bf215546Sopenharmony_ci                list.append( self.counter )
582bf215546Sopenharmony_ci            elif self.counter:
583bf215546Sopenharmony_ci                list = [ self.counter ]
584bf215546Sopenharmony_ci
585bf215546Sopenharmony_ci            if self.size() > 1:
586bf215546Sopenharmony_ci                list.append( base_size_str )
587bf215546Sopenharmony_ci
588bf215546Sopenharmony_ci            if len(list) > 1 and use_parens :
589bf215546Sopenharmony_ci                return "safe_mul(%s)" % ", ".join(list)
590bf215546Sopenharmony_ci            else:
591bf215546Sopenharmony_ci                return " * ".join(list)
592bf215546Sopenharmony_ci
593bf215546Sopenharmony_ci        elif self.is_image():
594bf215546Sopenharmony_ci            return "compsize"
595bf215546Sopenharmony_ci        else:
596bf215546Sopenharmony_ci            return base_size_str
597bf215546Sopenharmony_ci
598bf215546Sopenharmony_ci
599bf215546Sopenharmony_ci    def format_string(self):
600bf215546Sopenharmony_ci        if self.type_expr.original_string == "GLenum":
601bf215546Sopenharmony_ci            return "0x%x"
602bf215546Sopenharmony_ci        else:
603bf215546Sopenharmony_ci            return self.type_expr.format_string()
604bf215546Sopenharmony_ci
605bf215546Sopenharmony_ci
606bf215546Sopenharmony_ciclass gl_function( gl_item ):
607bf215546Sopenharmony_ci    def __init__(self, element, context):
608bf215546Sopenharmony_ci        self.context = context
609bf215546Sopenharmony_ci        self.name = None
610bf215546Sopenharmony_ci
611bf215546Sopenharmony_ci        self.entry_points = []
612bf215546Sopenharmony_ci        self.return_type = "void"
613bf215546Sopenharmony_ci        self.parameters = []
614bf215546Sopenharmony_ci        self.offset = -1
615bf215546Sopenharmony_ci        self.initialized = 0
616bf215546Sopenharmony_ci        self.images = []
617bf215546Sopenharmony_ci        self.exec_flavor = 'mesa'
618bf215546Sopenharmony_ci        self.desktop = True
619bf215546Sopenharmony_ci        self.deprecated = None
620bf215546Sopenharmony_ci        self.has_no_error_variant = False
621bf215546Sopenharmony_ci
622bf215546Sopenharmony_ci        # self.api_map[api] is a decimal value indicating the earliest
623bf215546Sopenharmony_ci        # version of the given API in which ANY alias for the function
624bf215546Sopenharmony_ci        # exists.  The map only lists APIs which contain the function
625bf215546Sopenharmony_ci        # in at least one version.  For example, for the ClipPlanex
626bf215546Sopenharmony_ci        # function, self.api_map == { 'es1':
627bf215546Sopenharmony_ci        # Decimal('1.1') }.
628bf215546Sopenharmony_ci        self.api_map = {}
629bf215546Sopenharmony_ci
630bf215546Sopenharmony_ci        self.assign_offset = False
631bf215546Sopenharmony_ci
632bf215546Sopenharmony_ci        self.static_entry_points = []
633bf215546Sopenharmony_ci
634bf215546Sopenharmony_ci        # Track the parameter string (for the function prototype)
635bf215546Sopenharmony_ci        # for each entry-point.  This is done because some functions
636bf215546Sopenharmony_ci        # change their prototype slightly when promoted from extension
637bf215546Sopenharmony_ci        # to ARB extension to core.  glTexImage3DEXT and glTexImage3D
638bf215546Sopenharmony_ci        # are good examples of this.  Scripts that need to generate
639bf215546Sopenharmony_ci        # code for these differing aliases need to real prototype
640bf215546Sopenharmony_ci        # for each entry-point.  Otherwise, they may generate code
641bf215546Sopenharmony_ci        # that won't compile.
642bf215546Sopenharmony_ci
643bf215546Sopenharmony_ci        self.entry_point_parameters = {}
644bf215546Sopenharmony_ci
645bf215546Sopenharmony_ci        self.process_element( element )
646bf215546Sopenharmony_ci
647bf215546Sopenharmony_ci        return
648bf215546Sopenharmony_ci
649bf215546Sopenharmony_ci
650bf215546Sopenharmony_ci    def process_element(self, element):
651bf215546Sopenharmony_ci        name = element.get( "name" )
652bf215546Sopenharmony_ci        alias = element.get( "alias" )
653bf215546Sopenharmony_ci
654bf215546Sopenharmony_ci        # marshal isn't allowed with alias
655bf215546Sopenharmony_ci        assert not alias or not element.get('marshal')
656bf215546Sopenharmony_ci        assert not alias or not element.get('marshal_count')
657bf215546Sopenharmony_ci        assert not alias or not element.get('marshal_sync')
658bf215546Sopenharmony_ci        assert not alias or not element.get('marshal_call_before')
659bf215546Sopenharmony_ci        assert not alias or not element.get('marshal_call_after')
660bf215546Sopenharmony_ci
661bf215546Sopenharmony_ci        if name in static_data.functions:
662bf215546Sopenharmony_ci            self.static_entry_points.append(name)
663bf215546Sopenharmony_ci
664bf215546Sopenharmony_ci        self.entry_points.append( name )
665bf215546Sopenharmony_ci
666bf215546Sopenharmony_ci        for api in ('es1', 'es2'):
667bf215546Sopenharmony_ci            version_str = element.get(api, 'none')
668bf215546Sopenharmony_ci            assert version_str is not None
669bf215546Sopenharmony_ci            if version_str != 'none':
670bf215546Sopenharmony_ci                version_decimal = Decimal(version_str)
671bf215546Sopenharmony_ci                if api not in self.api_map or \
672bf215546Sopenharmony_ci                        version_decimal < self.api_map[api]:
673bf215546Sopenharmony_ci                    self.api_map[api] = version_decimal
674bf215546Sopenharmony_ci
675bf215546Sopenharmony_ci        exec_flavor = element.get('exec')
676bf215546Sopenharmony_ci        if exec_flavor:
677bf215546Sopenharmony_ci            self.exec_flavor = exec_flavor
678bf215546Sopenharmony_ci
679bf215546Sopenharmony_ci        deprecated = element.get('deprecated', 'none')
680bf215546Sopenharmony_ci        if deprecated != 'none':
681bf215546Sopenharmony_ci            self.deprecated = Decimal(deprecated)
682bf215546Sopenharmony_ci
683bf215546Sopenharmony_ci        if not is_attr_true(element, 'desktop', 'true'):
684bf215546Sopenharmony_ci            self.desktop = False
685bf215546Sopenharmony_ci
686bf215546Sopenharmony_ci        if self.has_no_error_variant or is_attr_true(element, 'no_error'):
687bf215546Sopenharmony_ci            self.has_no_error_variant = True
688bf215546Sopenharmony_ci        else:
689bf215546Sopenharmony_ci            self.has_no_error_variant = False
690bf215546Sopenharmony_ci
691bf215546Sopenharmony_ci        if alias:
692bf215546Sopenharmony_ci            true_name = alias
693bf215546Sopenharmony_ci        else:
694bf215546Sopenharmony_ci            true_name = name
695bf215546Sopenharmony_ci
696bf215546Sopenharmony_ci            # Only try to set the offset when a non-alias entry-point
697bf215546Sopenharmony_ci            # is being processed.
698bf215546Sopenharmony_ci
699bf215546Sopenharmony_ci            if name in static_data.offsets and static_data.offsets[name] <= static_data.MAX_OFFSETS:
700bf215546Sopenharmony_ci                self.offset = static_data.offsets[name]
701bf215546Sopenharmony_ci            elif name in static_data.offsets and static_data.offsets[name] > static_data.MAX_OFFSETS:
702bf215546Sopenharmony_ci                self.offset = static_data.offsets[name]
703bf215546Sopenharmony_ci                self.assign_offset = True
704bf215546Sopenharmony_ci            else:
705bf215546Sopenharmony_ci                if self.exec_flavor != "skip":
706bf215546Sopenharmony_ci                    raise RuntimeError("Entry-point %s is missing offset in static_data.py. Add one at the bottom of the list." % (name))
707bf215546Sopenharmony_ci                self.assign_offset = self.exec_flavor != "skip" or name in static_data.unused_functions
708bf215546Sopenharmony_ci
709bf215546Sopenharmony_ci        if not self.name:
710bf215546Sopenharmony_ci            self.name = true_name
711bf215546Sopenharmony_ci        elif self.name != true_name:
712bf215546Sopenharmony_ci            raise RuntimeError("Function true name redefined.  Was %s, now %s." % (self.name, true_name))
713bf215546Sopenharmony_ci
714bf215546Sopenharmony_ci
715bf215546Sopenharmony_ci        # There are two possible cases.  The first time an entry-point
716bf215546Sopenharmony_ci        # with data is seen, self.initialized will be 0.  On that
717bf215546Sopenharmony_ci        # pass, we just fill in the data.  The next time an
718bf215546Sopenharmony_ci        # entry-point with data is seen, self.initialized will be 1.
719bf215546Sopenharmony_ci        # On that pass we have to make that the new values match the
720bf215546Sopenharmony_ci        # valuse from the previous entry-point.
721bf215546Sopenharmony_ci
722bf215546Sopenharmony_ci        parameters = []
723bf215546Sopenharmony_ci        return_type = "void"
724bf215546Sopenharmony_ci        for child in element:
725bf215546Sopenharmony_ci            if child.tag == "return":
726bf215546Sopenharmony_ci                return_type = child.get( "type", "void" )
727bf215546Sopenharmony_ci            elif child.tag == "param":
728bf215546Sopenharmony_ci                param = self.context.factory.create_parameter(child, self.context)
729bf215546Sopenharmony_ci                parameters.append( param )
730bf215546Sopenharmony_ci
731bf215546Sopenharmony_ci
732bf215546Sopenharmony_ci        if self.initialized:
733bf215546Sopenharmony_ci            if self.return_type != return_type:
734bf215546Sopenharmony_ci                raise RuntimeError( "Return type changed in %s.  Was %s, now %s." % (name, self.return_type, return_type))
735bf215546Sopenharmony_ci
736bf215546Sopenharmony_ci            if len(parameters) != len(self.parameters):
737bf215546Sopenharmony_ci                raise RuntimeError( "Parameter count mismatch in %s.  Was %d, now %d." % (name, len(self.parameters), len(parameters)))
738bf215546Sopenharmony_ci
739bf215546Sopenharmony_ci            for j in range(0, len(parameters)):
740bf215546Sopenharmony_ci                p1 = parameters[j]
741bf215546Sopenharmony_ci                p2 = self.parameters[j]
742bf215546Sopenharmony_ci                if not p1.compatible( p2 ):
743bf215546Sopenharmony_ci                    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))
744bf215546Sopenharmony_ci
745bf215546Sopenharmony_ci
746bf215546Sopenharmony_ci        if true_name == name or not self.initialized:
747bf215546Sopenharmony_ci            self.return_type = return_type
748bf215546Sopenharmony_ci            self.parameters = parameters
749bf215546Sopenharmony_ci
750bf215546Sopenharmony_ci            for param in self.parameters:
751bf215546Sopenharmony_ci                if param.is_image():
752bf215546Sopenharmony_ci                    self.images.append( param )
753bf215546Sopenharmony_ci
754bf215546Sopenharmony_ci        if list(element):
755bf215546Sopenharmony_ci            self.initialized = 1
756bf215546Sopenharmony_ci            self.entry_point_parameters[name] = parameters
757bf215546Sopenharmony_ci        else:
758bf215546Sopenharmony_ci            self.entry_point_parameters[name] = []
759bf215546Sopenharmony_ci
760bf215546Sopenharmony_ci        return
761bf215546Sopenharmony_ci
762bf215546Sopenharmony_ci    def filter_entry_points(self, entry_point_list):
763bf215546Sopenharmony_ci        """Filter out entry points not in entry_point_list."""
764bf215546Sopenharmony_ci        if not self.initialized:
765bf215546Sopenharmony_ci            raise RuntimeError('%s is not initialized yet' % self.name)
766bf215546Sopenharmony_ci
767bf215546Sopenharmony_ci        entry_points = []
768bf215546Sopenharmony_ci        for ent in self.entry_points:
769bf215546Sopenharmony_ci            if ent not in entry_point_list:
770bf215546Sopenharmony_ci                if ent in self.static_entry_points:
771bf215546Sopenharmony_ci                    self.static_entry_points.remove(ent)
772bf215546Sopenharmony_ci                self.entry_point_parameters.pop(ent)
773bf215546Sopenharmony_ci            else:
774bf215546Sopenharmony_ci                entry_points.append(ent)
775bf215546Sopenharmony_ci
776bf215546Sopenharmony_ci        if not entry_points:
777bf215546Sopenharmony_ci            raise RuntimeError('%s has no entry point after filtering' % self.name)
778bf215546Sopenharmony_ci
779bf215546Sopenharmony_ci        self.entry_points = entry_points
780bf215546Sopenharmony_ci        if self.name not in entry_points:
781bf215546Sopenharmony_ci            # use the first remaining entry point
782bf215546Sopenharmony_ci            self.name = entry_points[0]
783bf215546Sopenharmony_ci            self.parameters = self.entry_point_parameters[entry_points[0]]
784bf215546Sopenharmony_ci
785bf215546Sopenharmony_ci    def get_images(self):
786bf215546Sopenharmony_ci        """Return potentially empty list of input images."""
787bf215546Sopenharmony_ci        return self.images
788bf215546Sopenharmony_ci
789bf215546Sopenharmony_ci
790bf215546Sopenharmony_ci    def parameterIterator(self, name = None):
791bf215546Sopenharmony_ci        if name is not None:
792bf215546Sopenharmony_ci            return iter(self.entry_point_parameters[name]);
793bf215546Sopenharmony_ci        else:
794bf215546Sopenharmony_ci            return iter(self.parameters);
795bf215546Sopenharmony_ci
796bf215546Sopenharmony_ci
797bf215546Sopenharmony_ci    def get_parameter_string(self, entrypoint = None):
798bf215546Sopenharmony_ci        if entrypoint:
799bf215546Sopenharmony_ci            params = self.entry_point_parameters[ entrypoint ]
800bf215546Sopenharmony_ci        else:
801bf215546Sopenharmony_ci            params = self.parameters
802bf215546Sopenharmony_ci
803bf215546Sopenharmony_ci        return create_parameter_string( params, 1 )
804bf215546Sopenharmony_ci
805bf215546Sopenharmony_ci    def get_called_parameter_string(self):
806bf215546Sopenharmony_ci        p_string = ""
807bf215546Sopenharmony_ci        comma = ""
808bf215546Sopenharmony_ci
809bf215546Sopenharmony_ci        for p in self.parameterIterator():
810bf215546Sopenharmony_ci            if p.is_padding:
811bf215546Sopenharmony_ci                continue
812bf215546Sopenharmony_ci            p_string = p_string + comma + p.name
813bf215546Sopenharmony_ci            comma = ", "
814bf215546Sopenharmony_ci
815bf215546Sopenharmony_ci        return p_string
816bf215546Sopenharmony_ci
817bf215546Sopenharmony_ci
818bf215546Sopenharmony_ci    def is_abi(self):
819bf215546Sopenharmony_ci        return (self.offset >= 0 and not self.assign_offset)
820bf215546Sopenharmony_ci
821bf215546Sopenharmony_ci    def is_static_entry_point(self, name):
822bf215546Sopenharmony_ci        return name in self.static_entry_points
823bf215546Sopenharmony_ci
824bf215546Sopenharmony_ci    def dispatch_name(self):
825bf215546Sopenharmony_ci        if self.name in self.static_entry_points:
826bf215546Sopenharmony_ci            return self.name
827bf215546Sopenharmony_ci        else:
828bf215546Sopenharmony_ci            return "_dispatch_stub_%u" % (self.offset)
829bf215546Sopenharmony_ci
830bf215546Sopenharmony_ci    def static_name(self, name):
831bf215546Sopenharmony_ci        if name in self.static_entry_points:
832bf215546Sopenharmony_ci            return name
833bf215546Sopenharmony_ci        else:
834bf215546Sopenharmony_ci            return "_dispatch_stub_%u" % (self.offset)
835bf215546Sopenharmony_ci
836bf215546Sopenharmony_ciclass gl_item_factory(object):
837bf215546Sopenharmony_ci    """Factory to create objects derived from gl_item."""
838bf215546Sopenharmony_ci
839bf215546Sopenharmony_ci    def create_function(self, element, context):
840bf215546Sopenharmony_ci        return gl_function(element, context)
841bf215546Sopenharmony_ci
842bf215546Sopenharmony_ci    def create_type(self, element, context, category):
843bf215546Sopenharmony_ci        return gl_type(element, context, category)
844bf215546Sopenharmony_ci
845bf215546Sopenharmony_ci    def create_enum(self, element, context, category):
846bf215546Sopenharmony_ci        return gl_enum(element, context, category)
847bf215546Sopenharmony_ci
848bf215546Sopenharmony_ci    def create_parameter(self, element, context):
849bf215546Sopenharmony_ci        return gl_parameter(element, context)
850bf215546Sopenharmony_ci
851bf215546Sopenharmony_ci    def create_api(self):
852bf215546Sopenharmony_ci        return gl_api(self)
853bf215546Sopenharmony_ci
854bf215546Sopenharmony_ci
855bf215546Sopenharmony_ciclass gl_api(object):
856bf215546Sopenharmony_ci    def __init__(self, factory):
857bf215546Sopenharmony_ci        self.functions_by_name = OrderedDict()
858bf215546Sopenharmony_ci        self.enums_by_name = {}
859bf215546Sopenharmony_ci        self.types_by_name = {}
860bf215546Sopenharmony_ci
861bf215546Sopenharmony_ci        self.category_dict = {}
862bf215546Sopenharmony_ci        self.categories = [{}, {}, {}, {}]
863bf215546Sopenharmony_ci
864bf215546Sopenharmony_ci        self.factory = factory
865bf215546Sopenharmony_ci
866bf215546Sopenharmony_ci        self.next_offset = 0
867bf215546Sopenharmony_ci
868bf215546Sopenharmony_ci        typeexpr.create_initial_types()
869bf215546Sopenharmony_ci        return
870bf215546Sopenharmony_ci
871bf215546Sopenharmony_ci    def parse_file(self, file_name):
872bf215546Sopenharmony_ci        doc = ET.parse( file_name )
873bf215546Sopenharmony_ci        self.process_element(file_name, doc)
874bf215546Sopenharmony_ci
875bf215546Sopenharmony_ci
876bf215546Sopenharmony_ci    def process_element(self, file_name, doc):
877bf215546Sopenharmony_ci        element = doc.getroot()
878bf215546Sopenharmony_ci        if element.tag == "OpenGLAPI":
879bf215546Sopenharmony_ci            self.process_OpenGLAPI(file_name, element)
880bf215546Sopenharmony_ci        return
881bf215546Sopenharmony_ci
882bf215546Sopenharmony_ci
883bf215546Sopenharmony_ci    def process_OpenGLAPI(self, file_name, element):
884bf215546Sopenharmony_ci        for child in element:
885bf215546Sopenharmony_ci            if child.tag == "category":
886bf215546Sopenharmony_ci                self.process_category( child )
887bf215546Sopenharmony_ci            elif child.tag == "OpenGLAPI":
888bf215546Sopenharmony_ci                self.process_OpenGLAPI( file_name, child )
889bf215546Sopenharmony_ci            elif child.tag == '{http://www.w3.org/2001/XInclude}include':
890bf215546Sopenharmony_ci                href = child.get('href')
891bf215546Sopenharmony_ci                href = os.path.join(os.path.dirname(file_name), href)
892bf215546Sopenharmony_ci                self.parse_file(href)
893bf215546Sopenharmony_ci
894bf215546Sopenharmony_ci        return
895bf215546Sopenharmony_ci
896bf215546Sopenharmony_ci
897bf215546Sopenharmony_ci    def process_category(self, cat):
898bf215546Sopenharmony_ci        cat_name = cat.get( "name" )
899bf215546Sopenharmony_ci        cat_number = cat.get( "number" )
900bf215546Sopenharmony_ci
901bf215546Sopenharmony_ci        [cat_type, key] = classify_category(cat_name, cat_number)
902bf215546Sopenharmony_ci        self.categories[cat_type][key] = [cat_name, cat_number]
903bf215546Sopenharmony_ci
904bf215546Sopenharmony_ci        for child in cat:
905bf215546Sopenharmony_ci            if child.tag == "function":
906bf215546Sopenharmony_ci                func_name = real_function_name( child )
907bf215546Sopenharmony_ci
908bf215546Sopenharmony_ci                temp_name = child.get( "name" )
909bf215546Sopenharmony_ci                self.category_dict[ temp_name ] = [cat_name, cat_number]
910bf215546Sopenharmony_ci
911bf215546Sopenharmony_ci                if func_name in self.functions_by_name:
912bf215546Sopenharmony_ci                    func = self.functions_by_name[ func_name ]
913bf215546Sopenharmony_ci                    func.process_element( child )
914bf215546Sopenharmony_ci                else:
915bf215546Sopenharmony_ci                    func = self.factory.create_function( child, self )
916bf215546Sopenharmony_ci                    self.functions_by_name[ func_name ] = func
917bf215546Sopenharmony_ci
918bf215546Sopenharmony_ci                if func.offset >= self.next_offset:
919bf215546Sopenharmony_ci                    self.next_offset = func.offset + 1
920bf215546Sopenharmony_ci
921bf215546Sopenharmony_ci
922bf215546Sopenharmony_ci            elif child.tag == "enum":
923bf215546Sopenharmony_ci                enum = self.factory.create_enum( child, self, cat_name )
924bf215546Sopenharmony_ci                self.enums_by_name[ enum.name ] = enum
925bf215546Sopenharmony_ci            elif child.tag == "type":
926bf215546Sopenharmony_ci                t = self.factory.create_type( child, self, cat_name )
927bf215546Sopenharmony_ci                self.types_by_name[ "GL" + t.name ] = t
928bf215546Sopenharmony_ci
929bf215546Sopenharmony_ci        return
930bf215546Sopenharmony_ci
931bf215546Sopenharmony_ci
932bf215546Sopenharmony_ci    def functionIterateByCategory(self, cat = None):
933bf215546Sopenharmony_ci        """Iterate over functions by category.
934bf215546Sopenharmony_ci
935bf215546Sopenharmony_ci        If cat is None, all known functions are iterated in category
936bf215546Sopenharmony_ci        order.  See classify_category for details of the ordering.
937bf215546Sopenharmony_ci        Within a category, functions are sorted by name.  If cat is
938bf215546Sopenharmony_ci        not None, then only functions in that category are iterated.
939bf215546Sopenharmony_ci        """
940bf215546Sopenharmony_ci        lists = [{}, {}, {}, {}]
941bf215546Sopenharmony_ci
942bf215546Sopenharmony_ci        for func in self.functionIterateAll():
943bf215546Sopenharmony_ci            [cat_name, cat_number] = self.category_dict[func.name]
944bf215546Sopenharmony_ci
945bf215546Sopenharmony_ci            if (cat == None) or (cat == cat_name):
946bf215546Sopenharmony_ci                [func_cat_type, key] = classify_category(cat_name, cat_number)
947bf215546Sopenharmony_ci
948bf215546Sopenharmony_ci                if key not in lists[func_cat_type]:
949bf215546Sopenharmony_ci                    lists[func_cat_type][key] = {}
950bf215546Sopenharmony_ci
951bf215546Sopenharmony_ci                lists[func_cat_type][key][func.name] = func
952bf215546Sopenharmony_ci
953bf215546Sopenharmony_ci
954bf215546Sopenharmony_ci        functions = []
955bf215546Sopenharmony_ci        for func_cat_type in range(0,4):
956bf215546Sopenharmony_ci            keys = sorted(lists[func_cat_type].keys())
957bf215546Sopenharmony_ci
958bf215546Sopenharmony_ci            for key in keys:
959bf215546Sopenharmony_ci                names = sorted(lists[func_cat_type][key].keys())
960bf215546Sopenharmony_ci
961bf215546Sopenharmony_ci                for name in names:
962bf215546Sopenharmony_ci                    functions.append(lists[func_cat_type][key][name])
963bf215546Sopenharmony_ci
964bf215546Sopenharmony_ci        return iter(functions)
965bf215546Sopenharmony_ci
966bf215546Sopenharmony_ci
967bf215546Sopenharmony_ci    def functionIterateByOffset(self):
968bf215546Sopenharmony_ci        max_offset = -1
969bf215546Sopenharmony_ci        for func in self.functions_by_name.values():
970bf215546Sopenharmony_ci            if func.offset > max_offset:
971bf215546Sopenharmony_ci                max_offset = func.offset
972bf215546Sopenharmony_ci
973bf215546Sopenharmony_ci
974bf215546Sopenharmony_ci        temp = [None for i in range(0, max_offset + 1)]
975bf215546Sopenharmony_ci        for func in self.functions_by_name.values():
976bf215546Sopenharmony_ci            if func.offset != -1:
977bf215546Sopenharmony_ci                temp[ func.offset ] = func
978bf215546Sopenharmony_ci
979bf215546Sopenharmony_ci
980bf215546Sopenharmony_ci        list = []
981bf215546Sopenharmony_ci        for i in range(0, max_offset + 1):
982bf215546Sopenharmony_ci            if temp[i]:
983bf215546Sopenharmony_ci                list.append(temp[i])
984bf215546Sopenharmony_ci
985bf215546Sopenharmony_ci        return iter(list);
986bf215546Sopenharmony_ci
987bf215546Sopenharmony_ci
988bf215546Sopenharmony_ci    def functionIterateAll(self):
989bf215546Sopenharmony_ci        return self.functions_by_name.values()
990bf215546Sopenharmony_ci
991bf215546Sopenharmony_ci
992bf215546Sopenharmony_ci    def enumIterateByName(self):
993bf215546Sopenharmony_ci        keys = sorted(self.enums_by_name.keys())
994bf215546Sopenharmony_ci
995bf215546Sopenharmony_ci        list = []
996bf215546Sopenharmony_ci        for enum in keys:
997bf215546Sopenharmony_ci            list.append( self.enums_by_name[ enum ] )
998bf215546Sopenharmony_ci
999bf215546Sopenharmony_ci        return iter(list)
1000bf215546Sopenharmony_ci
1001bf215546Sopenharmony_ci
1002bf215546Sopenharmony_ci    def categoryIterate(self):
1003bf215546Sopenharmony_ci        """Iterate over categories.
1004bf215546Sopenharmony_ci
1005bf215546Sopenharmony_ci        Iterate over all known categories in the order specified by
1006bf215546Sopenharmony_ci        classify_category.  Each iterated value is a tuple of the
1007bf215546Sopenharmony_ci        name and number (which may be None) of the category.
1008bf215546Sopenharmony_ci        """
1009bf215546Sopenharmony_ci
1010bf215546Sopenharmony_ci        list = []
1011bf215546Sopenharmony_ci        for cat_type in range(0,4):
1012bf215546Sopenharmony_ci            keys = sorted(self.categories[cat_type].keys())
1013bf215546Sopenharmony_ci
1014bf215546Sopenharmony_ci            for key in keys:
1015bf215546Sopenharmony_ci                list.append(self.categories[cat_type][key])
1016bf215546Sopenharmony_ci
1017bf215546Sopenharmony_ci        return iter(list)
1018bf215546Sopenharmony_ci
1019bf215546Sopenharmony_ci
1020bf215546Sopenharmony_ci    def get_category_for_name( self, name ):
1021bf215546Sopenharmony_ci        if name in self.category_dict:
1022bf215546Sopenharmony_ci            return self.category_dict[name]
1023bf215546Sopenharmony_ci        else:
1024bf215546Sopenharmony_ci            return ["<unknown category>", None]
1025bf215546Sopenharmony_ci
1026bf215546Sopenharmony_ci
1027bf215546Sopenharmony_ci    def typeIterate(self):
1028bf215546Sopenharmony_ci        return self.types_by_name.values()
1029bf215546Sopenharmony_ci
1030bf215546Sopenharmony_ci
1031bf215546Sopenharmony_ci    def find_type( self, type_name ):
1032bf215546Sopenharmony_ci        if type_name in self.types_by_name:
1033bf215546Sopenharmony_ci            return self.types_by_name[ type_name ].type_expr
1034bf215546Sopenharmony_ci        else:
1035bf215546Sopenharmony_ci            print("Unable to find base type matching \"%s\"." % (type_name))
1036bf215546Sopenharmony_ci            return None
1037