~mmach/netext73/mesa-haswell

« back to all changes in this revision

Viewing changes to src/mapi/mapi_abi.py

  • Committer: mmach
  • Date: 2022-09-22 19:56:13 UTC
  • Revision ID: netbit73@gmail.com-20220922195613-wtik9mmy20tmor0i
2022-09-22 21:17:09

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
 
2
 
# Mesa 3-D graphics library
3
 
#
4
 
# Copyright (C) 2010 LunarG Inc.
5
 
#
6
 
# Permission is hereby granted, free of charge, to any person obtaining a
7
 
# copy of this software and associated documentation files (the "Software"),
8
 
# to deal in the Software without restriction, including without limitation
9
 
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
 
# and/or sell copies of the Software, and to permit persons to whom the
11
 
# Software is furnished to do so, subject to the following conditions:
12
 
#
13
 
# The above copyright notice and this permission notice shall be included
14
 
# in all copies or substantial portions of the Software.
15
 
#
16
 
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19
 
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
 
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22
 
# DEALINGS IN THE SOFTWARE.
23
 
#
24
 
# Authors:
25
 
#    Chia-I Wu <olv@lunarg.com>
26
 
 
27
 
import sys
28
 
# make it possible to import glapi
29
 
import os
30
 
GLAPI = os.path.join(".", os.path.dirname(__file__), "glapi", "gen")
31
 
sys.path.insert(0, GLAPI)
32
 
 
33
 
from operator import attrgetter
34
 
import re
35
 
from optparse import OptionParser
36
 
import gl_XML
37
 
import glX_XML
38
 
 
39
 
 
40
 
# number of dynamic entries
41
 
ABI_NUM_DYNAMIC_ENTRIES = 256
42
 
 
43
 
class ABIEntry(object):
44
 
    """Represent an ABI entry."""
45
 
 
46
 
    _match_c_param = re.compile(
47
 
            '^(?P<type>[\w\s*]+?)(?P<name>\w+)(\[(?P<array>\d+)\])?$')
48
 
 
49
 
    def __init__(self, cols, attrs, xml_data = None):
50
 
        self._parse(cols)
51
 
 
52
 
        self.slot = attrs['slot']
53
 
        self.hidden = attrs['hidden']
54
 
        self.alias = attrs['alias']
55
 
        self.handcode = attrs['handcode']
56
 
        self.xml_data = xml_data
57
 
 
58
 
    def c_prototype(self):
59
 
        return '%s %s(%s)' % (self.c_return(), self.name, self.c_params())
60
 
 
61
 
    def c_return(self):
62
 
        ret = self.ret
63
 
        if not ret:
64
 
            ret = 'void'
65
 
 
66
 
        return ret
67
 
 
68
 
    def c_params(self):
69
 
        """Return the parameter list used in the entry prototype."""
70
 
        c_params = []
71
 
        for t, n, a in self.params:
72
 
            sep = '' if t.endswith('*') else ' '
73
 
            arr = '[%d]' % a if a else ''
74
 
            c_params.append(t + sep + n + arr)
75
 
        if not c_params:
76
 
            c_params.append('void')
77
 
 
78
 
        return ", ".join(c_params)
79
 
 
80
 
    def c_args(self):
81
 
        """Return the argument list used in the entry invocation."""
82
 
        c_args = []
83
 
        for t, n, a in self.params:
84
 
            c_args.append(n)
85
 
 
86
 
        return ", ".join(c_args)
87
 
 
88
 
    def _parse(self, cols):
89
 
        ret = cols.pop(0)
90
 
        if ret == 'void':
91
 
            ret = None
92
 
 
93
 
        name = cols.pop(0)
94
 
 
95
 
        params = []
96
 
        if not cols:
97
 
            raise Exception(cols)
98
 
        elif len(cols) == 1 and cols[0] == 'void':
99
 
            pass
100
 
        else:
101
 
            for val in cols:
102
 
                params.append(self._parse_param(val))
103
 
 
104
 
        self.ret = ret
105
 
        self.name = name
106
 
        self.params = params
107
 
 
108
 
    def _parse_param(self, c_param):
109
 
        m = self._match_c_param.match(c_param)
110
 
        if not m:
111
 
            raise Exception('unrecognized param ' + c_param)
112
 
 
113
 
        c_type = m.group('type').strip()
114
 
        c_name = m.group('name')
115
 
        c_array = m.group('array')
116
 
        c_array = int(c_array) if c_array else 0
117
 
 
118
 
        return (c_type, c_name, c_array)
119
 
 
120
 
    def __str__(self):
121
 
        return self.c_prototype()
122
 
 
123
 
    def __lt__(self, other):
124
 
        # compare slot, alias, and then name
125
 
        if self.slot == other.slot:
126
 
            if not self.alias:
127
 
                return True
128
 
            elif not other.alias:
129
 
                return False
130
 
 
131
 
            return self.name < other.name
132
 
 
133
 
        return self.slot < other.slot
134
 
 
135
 
 
136
 
def abi_parse_xml(xml):
137
 
    """Parse a GLAPI XML file for ABI entries."""
138
 
    api = gl_XML.parse_GL_API(xml, glX_XML.glx_item_factory())
139
 
 
140
 
    entry_dict = {}
141
 
    for func in api.functionIterateByOffset():
142
 
        # make sure func.name appear first
143
 
        entry_points = func.entry_points[:]
144
 
        entry_points.remove(func.name)
145
 
        entry_points.insert(0, func.name)
146
 
 
147
 
        for name in entry_points:
148
 
            attrs = {
149
 
                    'slot': func.offset,
150
 
                    'hidden': not func.is_static_entry_point(name),
151
 
                    'alias': None if name == func.name else func.name,
152
 
                    'handcode': bool(func.has_different_protocol(name)),
153
 
            }
154
 
 
155
 
            # post-process attrs
156
 
            if attrs['alias']:
157
 
                try:
158
 
                    alias = entry_dict[attrs['alias']]
159
 
                except KeyError:
160
 
                    raise Exception('failed to alias %s' % attrs['alias'])
161
 
                if alias.alias:
162
 
                    raise Exception('recursive alias %s' % ent.name)
163
 
                attrs['alias'] = alias
164
 
            if attrs['handcode']:
165
 
                attrs['handcode'] = func.static_glx_name(name)
166
 
            else:
167
 
                attrs['handcode'] = None
168
 
 
169
 
            if name in entry_dict:
170
 
                raise Exception('%s is duplicated' % (name))
171
 
 
172
 
            cols = []
173
 
            cols.append(func.return_type)
174
 
            cols.append(name)
175
 
            params = func.get_parameter_string(name)
176
 
            cols.extend([p.strip() for p in params.split(',')])
177
 
 
178
 
            ent = ABIEntry(cols, attrs, func)
179
 
            entry_dict[ent.name] = ent
180
 
 
181
 
    entries = sorted(entry_dict.values())
182
 
 
183
 
    return entries
184
 
 
185
 
def abi_sanity_check(entries):
186
 
    if not entries:
187
 
        return
188
 
 
189
 
    all_names = []
190
 
    last_slot = entries[-1].slot
191
 
    i = 0
192
 
    for slot in range(last_slot + 1):
193
 
        if entries[i].slot != slot:
194
 
            raise Exception('entries are not ordered by slots')
195
 
        if entries[i].alias:
196
 
            raise Exception('first entry of slot %d aliases %s'
197
 
                    % (slot, entries[i].alias.name))
198
 
        handcode = None
199
 
        while i < len(entries) and entries[i].slot == slot:
200
 
            ent = entries[i]
201
 
            if not handcode and ent.handcode:
202
 
                handcode = ent.handcode
203
 
            elif ent.handcode != handcode:
204
 
                raise Exception('two aliases with handcode %s != %s',
205
 
                        ent.handcode, handcode)
206
 
 
207
 
            if ent.name in all_names:
208
 
                raise Exception('%s is duplicated' % (ent.name))
209
 
            if ent.alias and ent.alias.name not in all_names:
210
 
                raise Exception('failed to alias %s' % (ent.alias.name))
211
 
            all_names.append(ent.name)
212
 
            i += 1
213
 
    if i < len(entries):
214
 
        raise Exception('there are %d invalid entries' % (len(entries) - 1))
215
 
 
216
 
class ABIPrinter(object):
217
 
    """MAPI Printer"""
218
 
 
219
 
    def __init__(self, entries):
220
 
        self.entries = entries
221
 
 
222
 
        # sort entries by their names
223
 
        self.entries_sorted_by_names = sorted(self.entries, key=attrgetter('name'))
224
 
 
225
 
        self.indent = ' ' * 3
226
 
        self.noop_warn = 'noop_warn'
227
 
        self.noop_generic = 'noop_generic'
228
 
        self.current_get = 'entry_current_get'
229
 
 
230
 
        self.api_defines = []
231
 
        self.api_headers = ['"KHR/khrplatform.h"']
232
 
        self.api_call = 'KHRONOS_APICALL'
233
 
        self.api_entry = 'KHRONOS_APIENTRY'
234
 
        self.api_attrs = 'KHRONOS_APIATTRIBUTES'
235
 
 
236
 
        self.c_header = ''
237
 
 
238
 
        self.lib_need_table_size = True
239
 
        self.lib_need_noop_array = True
240
 
        self.lib_need_stubs = True
241
 
        self.lib_need_all_entries = True
242
 
        self.lib_need_non_hidden_entries = False
243
 
 
244
 
    def c_notice(self):
245
 
        return '/* This file is automatically generated by mapi_abi.py.  Do not modify. */'
246
 
 
247
 
    def c_public_includes(self):
248
 
        """Return includes of the client API headers."""
249
 
        defines = ['#define ' + d for d in self.api_defines]
250
 
        includes = ['#include ' + h for h in self.api_headers]
251
 
        return "\n".join(defines + includes)
252
 
 
253
 
    def need_entry_point(self, ent):
254
 
        """Return True if an entry point is needed for the entry."""
255
 
        # non-handcode hidden aliases may share the entry they alias
256
 
        use_alias = (ent.hidden and ent.alias and not ent.handcode)
257
 
        return not use_alias
258
 
 
259
 
    def c_public_declarations(self, prefix):
260
 
        """Return the declarations of public entry points."""
261
 
        decls = []
262
 
        for ent in self.entries:
263
 
            if not self.need_entry_point(ent):
264
 
                continue
265
 
            export = self.api_call if not ent.hidden else ''
266
 
            if not ent.hidden or not self.lib_need_non_hidden_entries:
267
 
                decls.append(self._c_decl(ent, prefix, True, export) + ';')
268
 
 
269
 
        return "\n".join(decls)
270
 
 
271
 
    def c_mapi_table(self):
272
 
        """Return defines of the dispatch table size."""
273
 
        num_static_entries = self.entries[-1].slot + 1
274
 
        return ('#define MAPI_TABLE_NUM_STATIC %d\n' + \
275
 
                '#define MAPI_TABLE_NUM_DYNAMIC %d') % (
276
 
                        num_static_entries, ABI_NUM_DYNAMIC_ENTRIES)
277
 
 
278
 
    def _c_function(self, ent, prefix, mangle=False, stringify=False):
279
 
        """Return the function name of an entry."""
280
 
        formats = {
281
 
                True: { True: '%s_STR(%s)', False: '%s(%s)' },
282
 
                False: { True: '"%s%s"', False: '%s%s' },
283
 
        }
284
 
        fmt = formats[prefix.isupper()][stringify]
285
 
        name = ent.name
286
 
        if mangle and ent.hidden:
287
 
            name = '_dispatch_stub_' + str(ent.slot)
288
 
        return fmt % (prefix, name)
289
 
 
290
 
    def _c_function_call(self, ent, prefix):
291
 
        """Return the function name used for calling."""
292
 
        if ent.handcode:
293
 
            # _c_function does not handle this case
294
 
            formats = { True: '%s(%s)', False: '%s%s' }
295
 
            fmt = formats[prefix.isupper()]
296
 
            name = fmt % (prefix, ent.handcode)
297
 
        elif self.need_entry_point(ent):
298
 
            name = self._c_function(ent, prefix, True)
299
 
        else:
300
 
            name = self._c_function(ent.alias, prefix, True)
301
 
        return name
302
 
 
303
 
    def _c_decl(self, ent, prefix, mangle=False, export=''):
304
 
        """Return the C declaration for the entry."""
305
 
        decl = '%s %s %s(%s)' % (ent.c_return(), self.api_entry,
306
 
                self._c_function(ent, prefix, mangle), ent.c_params())
307
 
        if export:
308
 
            decl = export + ' ' + decl
309
 
        if self.api_attrs:
310
 
            decl += ' ' + self.api_attrs
311
 
 
312
 
        return decl
313
 
 
314
 
    def _c_cast(self, ent):
315
 
        """Return the C cast for the entry."""
316
 
        cast = '%s (%s *)(%s)' % (
317
 
                ent.c_return(), self.api_entry, ent.c_params())
318
 
 
319
 
        return cast
320
 
 
321
 
    def c_public_dispatches(self, prefix, no_hidden):
322
 
        """Return the public dispatch functions."""
323
 
        dispatches = []
324
 
        for ent in self.entries:
325
 
            if ent.hidden and no_hidden:
326
 
                continue
327
 
 
328
 
            if not self.need_entry_point(ent):
329
 
                continue
330
 
 
331
 
            export = self.api_call if not ent.hidden else ''
332
 
 
333
 
            proto = self._c_decl(ent, prefix, True, export)
334
 
            cast = self._c_cast(ent)
335
 
 
336
 
            ret = ''
337
 
            if ent.ret:
338
 
                ret = 'return '
339
 
            stmt1 = self.indent
340
 
            stmt1 += 'const struct _glapi_table *_tbl = %s();' % (
341
 
                    self.current_get)
342
 
            stmt2 = self.indent
343
 
            stmt2 += 'mapi_func _func = ((const mapi_func *) _tbl)[%d];' % (
344
 
                    ent.slot)
345
 
            stmt3 = self.indent
346
 
            stmt3 += '%s((%s) _func)(%s);' % (ret, cast, ent.c_args())
347
 
 
348
 
            disp = '%s\n{\n%s\n%s\n%s\n}' % (proto, stmt1, stmt2, stmt3)
349
 
 
350
 
            if ent.handcode:
351
 
                disp = '#if 0\n' + disp + '\n#endif'
352
 
 
353
 
            dispatches.append(disp)
354
 
 
355
 
        return '\n\n'.join(dispatches)
356
 
 
357
 
    def c_public_initializer(self, prefix):
358
 
        """Return the initializer for public dispatch functions."""
359
 
        names = []
360
 
        for ent in self.entries:
361
 
            if ent.alias:
362
 
                continue
363
 
 
364
 
            name = '%s(mapi_func) %s' % (self.indent,
365
 
                    self._c_function_call(ent, prefix))
366
 
            names.append(name)
367
 
 
368
 
        return ',\n'.join(names)
369
 
 
370
 
    def c_stub_string_pool(self):
371
 
        """Return the string pool for use by stubs."""
372
 
        # sort entries by their names
373
 
        sorted_entries = sorted(self.entries, key=attrgetter('name'))
374
 
 
375
 
        pool = []
376
 
        offsets = {}
377
 
        count = 0
378
 
        for ent in sorted_entries:
379
 
            offsets[ent] = count
380
 
            pool.append('%s' % (ent.name))
381
 
            count += len(ent.name) + 1
382
 
 
383
 
        pool_str =  self.indent + '"' + \
384
 
                ('\\0"\n' + self.indent + '"').join(pool) + '";'
385
 
        return (pool_str, offsets)
386
 
 
387
 
    def c_stub_initializer(self, prefix, pool_offsets):
388
 
        """Return the initializer for struct mapi_stub array."""
389
 
        stubs = []
390
 
        for ent in self.entries_sorted_by_names:
391
 
            stubs.append('%s{ (void *) %d, %d, NULL }' % (
392
 
                self.indent, pool_offsets[ent], ent.slot))
393
 
 
394
 
        return ',\n'.join(stubs)
395
 
 
396
 
    def c_noop_functions(self, prefix, warn_prefix):
397
 
        """Return the noop functions."""
398
 
        noops = []
399
 
        for ent in self.entries:
400
 
            if ent.alias:
401
 
                continue
402
 
 
403
 
            proto = self._c_decl(ent, prefix, False, 'static')
404
 
 
405
 
            stmt1 = self.indent;
406
 
            space = ''
407
 
            for t, n, a in ent.params:
408
 
                stmt1 += "%s(void) %s;" % (space, n)
409
 
                space = ' '
410
 
 
411
 
            if ent.params:
412
 
                stmt1 += '\n';
413
 
 
414
 
            stmt1 += self.indent + '%s(%s);' % (self.noop_warn,
415
 
                    self._c_function(ent, warn_prefix, False, True))
416
 
 
417
 
            if ent.ret:
418
 
                stmt2 = self.indent + 'return (%s) 0;' % (ent.ret)
419
 
                noop = '%s\n{\n%s\n%s\n}' % (proto, stmt1, stmt2)
420
 
            else:
421
 
                noop = '%s\n{\n%s\n}' % (proto, stmt1)
422
 
 
423
 
            noops.append(noop)
424
 
 
425
 
        return '\n\n'.join(noops)
426
 
 
427
 
    def c_noop_initializer(self, prefix, use_generic):
428
 
        """Return an initializer for the noop dispatch table."""
429
 
        entries = [self._c_function(ent, prefix)
430
 
                for ent in self.entries if not ent.alias]
431
 
        if use_generic:
432
 
            entries = [self.noop_generic] * len(entries)
433
 
 
434
 
        entries.extend([self.noop_generic] * ABI_NUM_DYNAMIC_ENTRIES)
435
 
 
436
 
        pre = self.indent + '(mapi_func) '
437
 
        return pre + (',\n' + pre).join(entries)
438
 
 
439
 
    def c_asm_gcc(self, prefix, no_hidden):
440
 
        asm = []
441
 
 
442
 
        for ent in self.entries:
443
 
            if ent.hidden and no_hidden:
444
 
                continue
445
 
 
446
 
            if not self.need_entry_point(ent):
447
 
                continue
448
 
 
449
 
            name = self._c_function(ent, prefix, True, True)
450
 
 
451
 
            if ent.handcode:
452
 
                asm.append('#if 0')
453
 
 
454
 
            if ent.hidden:
455
 
                asm.append('".hidden "%s"\\n"' % (name))
456
 
 
457
 
            if ent.alias and not (ent.alias.hidden and no_hidden):
458
 
                asm.append('".globl "%s"\\n"' % (name))
459
 
                asm.append('".set "%s", "%s"\\n"' % (name,
460
 
                    self._c_function(ent.alias, prefix, True, True)))
461
 
            else:
462
 
                asm.append('STUB_ASM_ENTRY(%s)"\\n"' % (name))
463
 
                asm.append('"\\t"STUB_ASM_CODE("%d")"\\n"' % (ent.slot))
464
 
 
465
 
            if ent.handcode:
466
 
                asm.append('#endif')
467
 
            asm.append('')
468
 
 
469
 
        return "\n".join(asm)
470
 
 
471
 
    def output_for_lib(self):
472
 
        print(self.c_notice())
473
 
 
474
 
        if self.c_header:
475
 
            print()
476
 
            print(self.c_header)
477
 
 
478
 
        print()
479
 
        print('#ifdef MAPI_TMP_DEFINES')
480
 
        print(self.c_public_includes())
481
 
        print()
482
 
        print('#ifdef MemoryBarrier')
483
 
        print('#undef MemoryBarrier')
484
 
        print('#endif')
485
 
        print()
486
 
        print(self.c_public_declarations(self.prefix_lib))
487
 
        print('#undef MAPI_TMP_DEFINES')
488
 
        print('#endif /* MAPI_TMP_DEFINES */')
489
 
 
490
 
        if self.lib_need_table_size:
491
 
            print()
492
 
            print('#ifdef MAPI_TMP_TABLE')
493
 
            print(self.c_mapi_table())
494
 
            print('#undef MAPI_TMP_TABLE')
495
 
            print('#endif /* MAPI_TMP_TABLE */')
496
 
 
497
 
        if self.lib_need_noop_array:
498
 
            print()
499
 
            print('#ifdef MAPI_TMP_NOOP_ARRAY')
500
 
            print('#ifdef DEBUG')
501
 
            print()
502
 
            print(self.c_noop_functions(self.prefix_noop, self.prefix_warn))
503
 
            print()
504
 
            print('const mapi_func table_%s_array[] = {' % (self.prefix_noop))
505
 
            print(self.c_noop_initializer(self.prefix_noop, False))
506
 
            print('};')
507
 
            print()
508
 
            print('#else /* DEBUG */')
509
 
            print()
510
 
            print('const mapi_func table_%s_array[] = {' % (self.prefix_noop))
511
 
            print(self.c_noop_initializer(self.prefix_noop, True))
512
 
            print('};')
513
 
            print()
514
 
            print('#endif /* DEBUG */')
515
 
            print('#undef MAPI_TMP_NOOP_ARRAY')
516
 
            print('#endif /* MAPI_TMP_NOOP_ARRAY */')
517
 
 
518
 
        if self.lib_need_stubs:
519
 
            pool, pool_offsets = self.c_stub_string_pool()
520
 
            print()
521
 
            print('#ifdef MAPI_TMP_PUBLIC_STUBS')
522
 
            print('static const char public_string_pool[] =')
523
 
            print(pool)
524
 
            print()
525
 
            print('static const struct mapi_stub public_stubs[] = {')
526
 
            print(self.c_stub_initializer(self.prefix_lib, pool_offsets))
527
 
            print('};')
528
 
            print('#undef MAPI_TMP_PUBLIC_STUBS')
529
 
            print('#endif /* MAPI_TMP_PUBLIC_STUBS */')
530
 
 
531
 
        if self.lib_need_all_entries:
532
 
            print()
533
 
            print('#ifdef MAPI_TMP_PUBLIC_ENTRIES')
534
 
            print(self.c_public_dispatches(self.prefix_lib, False))
535
 
            print()
536
 
            print('static const mapi_func public_entries[] = {')
537
 
            print(self.c_public_initializer(self.prefix_lib))
538
 
            print('};')
539
 
            print('#undef MAPI_TMP_PUBLIC_ENTRIES')
540
 
            print('#endif /* MAPI_TMP_PUBLIC_ENTRIES */')
541
 
 
542
 
            print()
543
 
            print('#ifdef MAPI_TMP_STUB_ASM_GCC')
544
 
            print('__asm__(')
545
 
            print(self.c_asm_gcc(self.prefix_lib, False))
546
 
            print(');')
547
 
            print('#undef MAPI_TMP_STUB_ASM_GCC')
548
 
            print('#endif /* MAPI_TMP_STUB_ASM_GCC */')
549
 
 
550
 
        if self.lib_need_non_hidden_entries:
551
 
            all_hidden = True
552
 
            for ent in self.entries:
553
 
                if not ent.hidden:
554
 
                    all_hidden = False
555
 
                    break
556
 
            if not all_hidden:
557
 
                print()
558
 
                print('#ifdef MAPI_TMP_PUBLIC_ENTRIES_NO_HIDDEN')
559
 
                print(self.c_public_dispatches(self.prefix_lib, True))
560
 
                print()
561
 
                print('/* does not need public_entries */')
562
 
                print('#undef MAPI_TMP_PUBLIC_ENTRIES_NO_HIDDEN')
563
 
                print('#endif /* MAPI_TMP_PUBLIC_ENTRIES_NO_HIDDEN */')
564
 
 
565
 
                print()
566
 
                print('#ifdef MAPI_TMP_STUB_ASM_GCC_NO_HIDDEN')
567
 
                print('__asm__(')
568
 
                print(self.c_asm_gcc(self.prefix_lib, True))
569
 
                print(');')
570
 
                print('#undef MAPI_TMP_STUB_ASM_GCC_NO_HIDDEN')
571
 
                print('#endif /* MAPI_TMP_STUB_ASM_GCC_NO_HIDDEN */')
572
 
 
573
 
class GLAPIPrinter(ABIPrinter):
574
 
    """OpenGL API Printer"""
575
 
 
576
 
    def __init__(self, entries):
577
 
        for ent in entries:
578
 
            self._override_for_api(ent)
579
 
        super(GLAPIPrinter, self).__init__(entries)
580
 
 
581
 
        self.api_defines = ['GL_GLEXT_PROTOTYPES']
582
 
        self.api_headers = ['"GL/gl.h"', '"GL/glext.h"']
583
 
        self.api_call = 'GLAPI'
584
 
        self.api_entry = 'APIENTRY'
585
 
        self.api_attrs = ''
586
 
 
587
 
        self.lib_need_table_size = False
588
 
        self.lib_need_noop_array = False
589
 
        self.lib_need_stubs = False
590
 
        self.lib_need_all_entries = False
591
 
        self.lib_need_non_hidden_entries = True
592
 
 
593
 
        self.prefix_lib = 'GLAPI_PREFIX'
594
 
        self.prefix_noop = 'noop'
595
 
        self.prefix_warn = self.prefix_lib
596
 
 
597
 
        self.c_header = self._get_c_header()
598
 
 
599
 
    def _override_for_api(self, ent):
600
 
        """Override attributes of an entry if necessary for this
601
 
        printer."""
602
 
        # By default, no override is necessary.
603
 
        pass
604
 
 
605
 
    def _get_c_header(self):
606
 
        header = """#ifndef _GLAPI_TMP_H_
607
 
#define _GLAPI_TMP_H_
608
 
#define GLAPI_PREFIX(func)  gl##func
609
 
#define GLAPI_PREFIX_STR(func)  "gl"#func
610
 
 
611
 
typedef int GLclampx;
612
 
#endif /* _GLAPI_TMP_H_ */"""
613
 
 
614
 
        return header
615
 
 
616
 
class SharedGLAPIPrinter(GLAPIPrinter):
617
 
    """Shared GLAPI API Printer"""
618
 
 
619
 
    def __init__(self, entries):
620
 
        super(SharedGLAPIPrinter, self).__init__(entries)
621
 
 
622
 
        self.lib_need_table_size = True
623
 
        self.lib_need_noop_array = True
624
 
        self.lib_need_stubs = True
625
 
        self.lib_need_all_entries = True
626
 
        self.lib_need_non_hidden_entries = False
627
 
 
628
 
        self.prefix_lib = 'shared'
629
 
        self.prefix_warn = 'gl'
630
 
 
631
 
    def _override_for_api(self, ent):
632
 
        ent.hidden = True
633
 
        ent.handcode = False
634
 
 
635
 
    def _get_c_header(self):
636
 
        header = """#ifndef _GLAPI_TMP_H_
637
 
#define _GLAPI_TMP_H_
638
 
typedef int GLclampx;
639
 
#endif /* _GLAPI_TMP_H_ */"""
640
 
 
641
 
        return header
642
 
 
643
 
def parse_args():
644
 
    printers = ['glapi', 'es1api', 'es2api', 'shared-glapi']
645
 
 
646
 
    parser = OptionParser(usage='usage: %prog [options] <xml_file>')
647
 
    parser.add_option('-p', '--printer', dest='printer',
648
 
            help='printer to use: %s' % (", ".join(printers)))
649
 
 
650
 
    options, args = parser.parse_args()
651
 
    if not args or options.printer not in printers:
652
 
        parser.print_help()
653
 
        sys.exit(1)
654
 
 
655
 
    if not args[0].endswith('.xml'):
656
 
        parser.print_help()
657
 
        sys.exit(1)
658
 
 
659
 
    return (args[0], options)
660
 
 
661
 
def main():
662
 
    printers = {
663
 
        'glapi': GLAPIPrinter,
664
 
        'shared-glapi': SharedGLAPIPrinter,
665
 
    }
666
 
 
667
 
    filename, options = parse_args()
668
 
 
669
 
    entries = abi_parse_xml(filename)
670
 
    abi_sanity_check(entries)
671
 
 
672
 
    printer = printers[options.printer](entries)
673
 
    printer.output_for_lib()
674
 
 
675
 
if __name__ == '__main__':
676
 
    main()