Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4358 Serge 1
#!/usr/bin/env python
2
 
3
# Mesa 3-D graphics library
4
#
5
# Copyright (C) 2010 LunarG Inc.
6
#
7
# Permission is hereby granted, free of charge, to any person obtaining a
8
# copy of this software and associated documentation files (the "Software"),
9
# to deal in the Software without restriction, including without limitation
10
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
11
# and/or sell copies of the Software, and to permit persons to whom the
12
# Software is furnished to do so, subject to the following conditions:
13
#
14
# The above copyright notice and this permission notice shall be included
15
# in all copies or substantial portions of the Software.
16
#
17
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
# DEALINGS IN THE SOFTWARE.
24
#
25
# Authors:
26
#    Chia-I Wu 
27
 
28
import sys
29
# make it possible to import glapi
30
import os
31
GLAPI = os.path.join(".", os.path.dirname(sys.argv[0]), "glapi/gen")
32
sys.path.append(GLAPI)
33
 
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[\w\s*]+?)(?P\w+)(\[(?P\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 __cmp__(self, other):
124
        # compare slot, alias, and then name
125
        res = cmp(self.slot, other.slot)
126
        if not res:
127
            if not self.alias:
128
                res = -1
129
            elif not other.alias:
130
                res = 1
131
 
132
            if not res:
133
                res = cmp(self.name, other.name)
134
 
135
        return res
136
 
137
def abi_parse_xml(xml):
138
    """Parse a GLAPI XML file for ABI entries."""
139
    api = gl_XML.parse_GL_API(xml, glX_XML.glx_item_factory())
140
 
141
    entry_dict = {}
142
    for func in api.functionIterateByOffset():
143
        # make sure func.name appear first
144
        entry_points = func.entry_points[:]
145
        entry_points.remove(func.name)
146
        entry_points.insert(0, func.name)
147
 
148
        for name in entry_points:
149
            attrs = {
150
                    'slot': func.offset,
151
                    'hidden': not func.is_static_entry_point(name),
152
                    'alias': None if name == func.name else func.name,
153
                    'handcode': bool(func.has_different_protocol(name)),
154
            }
155
 
156
            # post-process attrs
157
            if attrs['alias']:
158
                try:
159
                    alias = entry_dict[attrs['alias']]
160
                except KeyError:
161
                    raise Exception('failed to alias %s' % attrs['alias'])
162
                if alias.alias:
163
                    raise Exception('recursive alias %s' % ent.name)
164
                attrs['alias'] = alias
165
            if attrs['handcode']:
166
                attrs['handcode'] = func.static_glx_name(name)
167
            else:
168
                attrs['handcode'] = None
169
 
170
            if entry_dict.has_key(name):
171
                raise Exception('%s is duplicated' % (name))
172
 
173
            cols = []
174
            cols.append(func.return_type)
175
            cols.append(name)
176
            params = func.get_parameter_string(name)
177
            cols.extend([p.strip() for p in params.split(',')])
178
 
179
            ent = ABIEntry(cols, attrs, func)
180
            entry_dict[ent.name] = ent
181
 
182
    entries = entry_dict.values()
183
    entries.sort()
184
 
185
    return entries
186
 
187
def abi_parse_line(line):
188
    cols = [col.strip() for col in line.split(',')]
189
 
190
    attrs = {
191
            'slot': -1,
192
            'hidden': False,
193
            'alias': None,
194
            'handcode': None,
195
    }
196
 
197
    # extract attributes from the first column
198
    vals = cols[0].split(':')
199
    while len(vals) > 1:
200
        val = vals.pop(0)
201
        if val.startswith('slot='):
202
            attrs['slot'] = int(val[5:])
203
        elif val == 'hidden':
204
            attrs['hidden'] = True
205
        elif val.startswith('alias='):
206
            attrs['alias'] = val[6:]
207
        elif val.startswith('handcode='):
208
            attrs['handcode'] = val[9:]
209
        elif not val:
210
            pass
211
        else:
212
            raise Exception('unknown attribute %s' % val)
213
    cols[0] = vals[0]
214
 
215
    return (attrs, cols)
216
 
217
def abi_parse(filename):
218
    """Parse a CSV file for ABI entries."""
219
    fp = open(filename) if filename != '-' else sys.stdin
220
    lines = [line.strip() for line in fp.readlines()
221
            if not line.startswith('#') and line.strip()]
222
 
223
    entry_dict = {}
224
    next_slot = 0
225
    for line in lines:
226
        attrs, cols = abi_parse_line(line)
227
 
228
        # post-process attributes
229
        if attrs['alias']:
230
            try:
231
                alias = entry_dict[attrs['alias']]
232
            except KeyError:
233
                raise Exception('failed to alias %s' % attrs['alias'])
234
            if alias.alias:
235
                raise Exception('recursive alias %s' % ent.name)
236
            slot = alias.slot
237
            attrs['alias'] = alias
238
        else:
239
            slot = next_slot
240
            next_slot += 1
241
 
242
        if attrs['slot'] < 0:
243
            attrs['slot'] = slot
244
        elif attrs['slot'] != slot:
245
            raise Exception('invalid slot in %s' % (line))
246
 
247
        ent = ABIEntry(cols, attrs)
248
        if entry_dict.has_key(ent.name):
249
            raise Exception('%s is duplicated' % (ent.name))
250
        entry_dict[ent.name] = ent
251
 
252
    entries = entry_dict.values()
253
    entries.sort()
254
 
255
    return entries
256
 
257
def abi_sanity_check(entries):
258
    if not entries:
259
        return
260
 
261
    all_names = []
262
    last_slot = entries[-1].slot
263
    i = 0
264
    for slot in xrange(last_slot + 1):
265
        if entries[i].slot != slot:
266
            raise Exception('entries are not ordered by slots')
267
        if entries[i].alias:
268
            raise Exception('first entry of slot %d aliases %s'
269
                    % (slot, entries[i].alias.name))
270
        handcode = None
271
        while i < len(entries) and entries[i].slot == slot:
272
            ent = entries[i]
273
            if not handcode and ent.handcode:
274
                handcode = ent.handcode
275
            elif ent.handcode != handcode:
276
                raise Exception('two aliases with handcode %s != %s',
277
                        ent.handcode, handcode)
278
 
279
            if ent.name in all_names:
280
                raise Exception('%s is duplicated' % (ent.name))
281
            if ent.alias and ent.alias.name not in all_names:
282
                raise Exception('failed to alias %s' % (ent.alias.name))
283
            all_names.append(ent.name)
284
            i += 1
285
    if i < len(entries):
286
        raise Exception('there are %d invalid entries' % (len(entries) - 1))
287
 
288
class ABIPrinter(object):
289
    """MAPI Printer"""
290
 
291
    def __init__(self, entries):
292
        self.entries = entries
293
 
294
        # sort entries by their names
295
        self.entries_sorted_by_names = self.entries[:]
296
        self.entries_sorted_by_names.sort(lambda x, y: cmp(x.name, y.name))
297
 
298
        self.indent = ' ' * 3
299
        self.noop_warn = 'noop_warn'
300
        self.noop_generic = 'noop_generic'
301
        self.current_get = 'entry_current_get'
302
 
303
        self.api_defines = []
304
        self.api_headers = ['"KHR/khrplatform.h"']
305
        self.api_call = 'KHRONOS_APICALL'
306
        self.api_entry = 'KHRONOS_APIENTRY'
307
        self.api_attrs = 'KHRONOS_APIATTRIBUTES'
308
 
309
        self.c_header = ''
310
 
311
        self.lib_need_table_size = True
312
        self.lib_need_noop_array = True
313
        self.lib_need_stubs = True
314
        self.lib_need_all_entries = True
315
        self.lib_need_non_hidden_entries = False
316
 
317
    def c_notice(self):
318
        return '/* This file is automatically generated by mapi_abi.py.  Do not modify. */'
319
 
320
    def c_public_includes(self):
321
        """Return includes of the client API headers."""
322
        defines = ['#define ' + d for d in self.api_defines]
323
        includes = ['#include ' + h for h in self.api_headers]
324
        return "\n".join(defines + includes)
325
 
326
    def need_entry_point(self, ent):
327
        """Return True if an entry point is needed for the entry."""
328
        # non-handcode hidden aliases may share the entry they alias
329
        use_alias = (ent.hidden and ent.alias and not ent.handcode)
330
        return not use_alias
331
 
332
    def c_public_declarations(self, prefix):
333
        """Return the declarations of public entry points."""
334
        decls = []
335
        for ent in self.entries:
336
            if not self.need_entry_point(ent):
337
                continue
338
            export = self.api_call if not ent.hidden else ''
339
            decls.append(self._c_decl(ent, prefix, True, export) + ';')
340
 
341
        return "\n".join(decls)
342
 
343
    def c_mapi_table(self):
344
        """Return defines of the dispatch table size."""
345
        num_static_entries = self.entries[-1].slot + 1
346
        return ('#define MAPI_TABLE_NUM_STATIC %d\n' + \
347
                '#define MAPI_TABLE_NUM_DYNAMIC %d') % (
348
                        num_static_entries, ABI_NUM_DYNAMIC_ENTRIES)
349
 
350
    def c_mapi_table_initializer(self, prefix):
351
        """Return the array initializer for mapi_table_fill."""
352
        entries = [self._c_function(ent, prefix)
353
                for ent in self.entries if not ent.alias]
354
        pre = self.indent + '(mapi_proc) '
355
        return pre + (',\n' + pre).join(entries)
356
 
357
    def c_mapi_table_spec(self):
358
        """Return the spec for mapi_init."""
359
        specv1 = []
360
        line = '"1'
361
        for ent in self.entries:
362
            if not ent.alias:
363
                line += '\\0"\n'
364
                specv1.append(line)
365
                line = '"'
366
            line += '%s\\0' % ent.name
367
        line += '";'
368
        specv1.append(line)
369
 
370
        return self.indent + self.indent.join(specv1)
371
 
372
    def _c_function(self, ent, prefix, mangle=False, stringify=False):
373
        """Return the function name of an entry."""
374
        formats = {
375
                True: { True: '%s_STR(%s)', False: '%s(%s)' },
376
                False: { True: '"%s%s"', False: '%s%s' },
377
        }
378
        fmt = formats[prefix.isupper()][stringify]
379
        name = ent.name
380
        if mangle and ent.hidden:
381
            name = '_dispatch_stub_' + str(ent.slot)
382
        return fmt % (prefix, name)
383
 
384
    def _c_function_call(self, ent, prefix):
385
        """Return the function name used for calling."""
386
        if ent.handcode:
387
            # _c_function does not handle this case
388
            formats = { True: '%s(%s)', False: '%s%s' }
389
            fmt = formats[prefix.isupper()]
390
            name = fmt % (prefix, ent.handcode)
391
        elif self.need_entry_point(ent):
392
            name = self._c_function(ent, prefix, True)
393
        else:
394
            name = self._c_function(ent.alias, prefix, True)
395
        return name
396
 
397
    def _c_decl(self, ent, prefix, mangle=False, export=''):
398
        """Return the C declaration for the entry."""
399
        decl = '%s %s %s(%s)' % (ent.c_return(), self.api_entry,
400
                self._c_function(ent, prefix, mangle), ent.c_params())
401
        if export:
402
            decl = export + ' ' + decl
403
        if self.api_attrs:
404
            decl += ' ' + self.api_attrs
405
 
406
        return decl
407
 
408
    def _c_cast(self, ent):
409
        """Return the C cast for the entry."""
410
        cast = '%s (%s *)(%s)' % (
411
                ent.c_return(), self.api_entry, ent.c_params())
412
 
413
        return cast
414
 
415
    def c_private_declarations(self, prefix):
416
        """Return the declarations of private functions."""
417
        decls = [self._c_decl(ent, prefix) + ';'
418
                for ent in self.entries if not ent.alias]
419
 
420
        return "\n".join(decls)
421
 
422
    def c_public_dispatches(self, prefix, no_hidden):
423
        """Return the public dispatch functions."""
424
        dispatches = []
425
        for ent in self.entries:
426
            if ent.hidden and no_hidden:
427
                continue
428
 
429
            if not self.need_entry_point(ent):
430
                continue
431
 
432
            export = self.api_call if not ent.hidden else ''
433
 
434
            proto = self._c_decl(ent, prefix, True, export)
435
            cast = self._c_cast(ent)
436
 
437
            ret = ''
438
            if ent.ret:
439
                ret = 'return '
440
            stmt1 = self.indent
441
            stmt1 += 'const struct mapi_table *_tbl = %s();' % (
442
                    self.current_get)
443
            stmt2 = self.indent
444
            stmt2 += 'mapi_func _func = ((const mapi_func *) _tbl)[%d];' % (
445
                    ent.slot)
446
            stmt3 = self.indent
447
            stmt3 += '%s((%s) _func)(%s);' % (ret, cast, ent.c_args())
448
 
449
            disp = '%s\n{\n%s\n%s\n%s\n}' % (proto, stmt1, stmt2, stmt3)
450
 
451
            if ent.handcode:
452
                disp = '#if 0\n' + disp + '\n#endif'
453
 
454
            dispatches.append(disp)
455
 
456
        return '\n\n'.join(dispatches)
457
 
458
    def c_public_initializer(self, prefix):
459
        """Return the initializer for public dispatch functions."""
460
        names = []
461
        for ent in self.entries:
462
            if ent.alias:
463
                continue
464
 
465
            name = '%s(mapi_func) %s' % (self.indent,
466
                    self._c_function_call(ent, prefix))
467
            names.append(name)
468
 
469
        return ',\n'.join(names)
470
 
471
    def c_stub_string_pool(self):
472
        """Return the string pool for use by stubs."""
473
        # sort entries by their names
474
        sorted_entries = self.entries[:]
475
        sorted_entries.sort(lambda x, y: cmp(x.name, y.name))
476
 
477
        pool = []
478
        offsets = {}
479
        count = 0
480
        for ent in sorted_entries:
481
            offsets[ent] = count
482
            pool.append('%s' % (ent.name))
483
            count += len(ent.name) + 1
484
 
485
        pool_str =  self.indent + '"' + \
486
                ('\\0"\n' + self.indent + '"').join(pool) + '";'
487
        return (pool_str, offsets)
488
 
489
    def c_stub_initializer(self, prefix, pool_offsets):
490
        """Return the initializer for struct mapi_stub array."""
491
        stubs = []
492
        for ent in self.entries_sorted_by_names:
493
            stubs.append('%s{ (void *) %d, %d, NULL }' % (
494
                self.indent, pool_offsets[ent], ent.slot))
495
 
496
        return ',\n'.join(stubs)
497
 
498
    def c_noop_functions(self, prefix, warn_prefix):
499
        """Return the noop functions."""
500
        noops = []
501
        for ent in self.entries:
502
            if ent.alias:
503
                continue
504
 
505
            proto = self._c_decl(ent, prefix, False, 'static')
506
 
507
            stmt1 = self.indent;
508
            space = ''
509
            for t, n, a in ent.params:
510
                stmt1 += "%s(void) %s;" % (space, n)
511
                space = ' '
512
 
513
            if ent.params:
514
                stmt1 += '\n';
515
 
516
            stmt1 += self.indent + '%s(%s);' % (self.noop_warn,
517
                    self._c_function(ent, warn_prefix, False, True))
518
 
519
            if ent.ret:
520
                stmt2 = self.indent + 'return (%s) 0;' % (ent.ret)
521
                noop = '%s\n{\n%s\n%s\n}' % (proto, stmt1, stmt2)
522
            else:
523
                noop = '%s\n{\n%s\n}' % (proto, stmt1)
524
 
525
            noops.append(noop)
526
 
527
        return '\n\n'.join(noops)
528
 
529
    def c_noop_initializer(self, prefix, use_generic):
530
        """Return an initializer for the noop dispatch table."""
531
        entries = [self._c_function(ent, prefix)
532
                for ent in self.entries if not ent.alias]
533
        if use_generic:
534
            entries = [self.noop_generic] * len(entries)
535
 
536
        entries.extend([self.noop_generic] * ABI_NUM_DYNAMIC_ENTRIES)
537
 
538
        pre = self.indent + '(mapi_func) '
539
        return pre + (',\n' + pre).join(entries)
540
 
541
    def c_asm_gcc(self, prefix, no_hidden):
542
        asm = []
543
 
544
        for ent in self.entries:
545
            if ent.hidden and no_hidden:
546
                continue
547
 
548
            if not self.need_entry_point(ent):
549
                continue
550
 
551
            name = self._c_function(ent, prefix, True, True)
552
 
553
            if ent.handcode:
554
                asm.append('#if 0')
555
 
556
            if ent.hidden:
557
                asm.append('".hidden "%s"\\n"' % (name))
558
 
559
            if ent.alias and not (ent.alias.hidden and no_hidden):
560
                asm.append('".globl "%s"\\n"' % (name))
561
                asm.append('".set "%s", "%s"\\n"' % (name,
562
                    self._c_function(ent.alias, prefix, True, True)))
563
            else:
564
                asm.append('STUB_ASM_ENTRY(%s)"\\n"' % (name))
565
                asm.append('"\\t"STUB_ASM_CODE("%d")"\\n"' % (ent.slot))
566
 
567
            if ent.handcode:
568
                asm.append('#endif')
569
            asm.append('')
570
 
571
        return "\n".join(asm)
572
 
573
    def output_for_lib(self):
574
        print self.c_notice()
575
 
576
        if self.c_header:
577
            print
578
            print self.c_header
579
 
580
        print
581
        print '#ifdef MAPI_TMP_DEFINES'
582
        print self.c_public_includes()
583
        print
584
        print self.c_public_declarations(self.prefix_lib)
585
        print '#undef MAPI_TMP_DEFINES'
586
        print '#endif /* MAPI_TMP_DEFINES */'
587
 
588
        if self.lib_need_table_size:
589
            print
590
            print '#ifdef MAPI_TMP_TABLE'
591
            print self.c_mapi_table()
592
            print '#undef MAPI_TMP_TABLE'
593
            print '#endif /* MAPI_TMP_TABLE */'
594
 
595
        if self.lib_need_noop_array:
596
            print
597
            print '#ifdef MAPI_TMP_NOOP_ARRAY'
598
            print '#ifdef DEBUG'
599
            print
600
            print self.c_noop_functions(self.prefix_noop, self.prefix_warn)
601
            print
602
            print 'const mapi_func table_%s_array[] = {' % (self.prefix_noop)
603
            print self.c_noop_initializer(self.prefix_noop, False)
604
            print '};'
605
            print
606
            print '#else /* DEBUG */'
607
            print
608
            print 'const mapi_func table_%s_array[] = {' % (self.prefix_noop)
609
            print self.c_noop_initializer(self.prefix_noop, True)
610
            print '};'
611
            print
612
            print '#endif /* DEBUG */'
613
            print '#undef MAPI_TMP_NOOP_ARRAY'
614
            print '#endif /* MAPI_TMP_NOOP_ARRAY */'
615
 
616
        if self.lib_need_stubs:
617
            pool, pool_offsets = self.c_stub_string_pool()
618
            print
619
            print '#ifdef MAPI_TMP_PUBLIC_STUBS'
620
            print 'static const char public_string_pool[] ='
621
            print pool
622
            print
623
            print 'static const struct mapi_stub public_stubs[] = {'
624
            print self.c_stub_initializer(self.prefix_lib, pool_offsets)
625
            print '};'
626
            print '#undef MAPI_TMP_PUBLIC_STUBS'
627
            print '#endif /* MAPI_TMP_PUBLIC_STUBS */'
628
 
629
        if self.lib_need_all_entries:
630
            print
631
            print '#ifdef MAPI_TMP_PUBLIC_ENTRIES'
632
            print self.c_public_dispatches(self.prefix_lib, False)
633
            print
634
            print 'static const mapi_func public_entries[] = {'
635
            print self.c_public_initializer(self.prefix_lib)
636
            print '};'
637
            print '#undef MAPI_TMP_PUBLIC_ENTRIES'
638
            print '#endif /* MAPI_TMP_PUBLIC_ENTRIES */'
639
 
640
            print
641
            print '#ifdef MAPI_TMP_STUB_ASM_GCC'
642
            print '__asm__('
643
            print self.c_asm_gcc(self.prefix_lib, False)
644
            print ');'
645
            print '#undef MAPI_TMP_STUB_ASM_GCC'
646
            print '#endif /* MAPI_TMP_STUB_ASM_GCC */'
647
 
648
        if self.lib_need_non_hidden_entries:
649
            all_hidden = True
650
            for ent in self.entries:
651
                if not ent.hidden:
652
                    all_hidden = False
653
                    break
654
            if not all_hidden:
655
                print
656
                print '#ifdef MAPI_TMP_PUBLIC_ENTRIES_NO_HIDDEN'
657
                print self.c_public_dispatches(self.prefix_lib, True)
658
                print
659
                print '/* does not need public_entries */'
660
                print '#undef MAPI_TMP_PUBLIC_ENTRIES_NO_HIDDEN'
661
                print '#endif /* MAPI_TMP_PUBLIC_ENTRIES_NO_HIDDEN */'
662
 
663
                print
664
                print '#ifdef MAPI_TMP_STUB_ASM_GCC_NO_HIDDEN'
665
                print '__asm__('
666
                print self.c_asm_gcc(self.prefix_lib, True)
667
                print ');'
668
                print '#undef MAPI_TMP_STUB_ASM_GCC_NO_HIDDEN'
669
                print '#endif /* MAPI_TMP_STUB_ASM_GCC_NO_HIDDEN */'
670
 
671
    def output_for_app(self):
672
        print self.c_notice()
673
        print
674
        print self.c_private_declarations(self.prefix_app)
675
        print
676
        print '#ifdef API_TMP_DEFINE_SPEC'
677
        print
678
        print 'static const char %s_spec[] =' % (self.prefix_app)
679
        print self.c_mapi_table_spec()
680
        print
681
        print 'static const mapi_proc %s_procs[] = {' % (self.prefix_app)
682
        print self.c_mapi_table_initializer(self.prefix_app)
683
        print '};'
684
        print
685
        print '#endif /* API_TMP_DEFINE_SPEC */'
686
 
687
class GLAPIPrinter(ABIPrinter):
688
    """OpenGL API Printer"""
689
 
690
    def __init__(self, entries):
691
        for ent in entries:
692
            self._override_for_api(ent)
693
        super(GLAPIPrinter, self).__init__(entries)
694
 
695
        self.api_defines = ['GL_GLEXT_PROTOTYPES']
696
        self.api_headers = ['"GL/gl.h"', '"GL/glext.h"']
697
        self.api_call = 'GLAPI'
698
        self.api_entry = 'APIENTRY'
699
        self.api_attrs = ''
700
 
701
        self.lib_need_table_size = False
702
        self.lib_need_noop_array = False
703
        self.lib_need_stubs = False
704
        self.lib_need_all_entries = False
705
        self.lib_need_non_hidden_entries = True
706
 
707
        self.prefix_lib = 'GLAPI_PREFIX'
708
        self.prefix_app = '_mesa_'
709
        self.prefix_noop = 'noop'
710
        self.prefix_warn = self.prefix_lib
711
 
712
        self.c_header = self._get_c_header()
713
 
714
    def _override_for_api(self, ent):
715
        """Override attributes of an entry if necessary for this
716
        printer."""
717
        # By default, no override is necessary.
718
        pass
719
 
720
    def _get_c_header(self):
721
        header = """#ifndef _GLAPI_TMP_H_
722
#define _GLAPI_TMP_H_
723
#ifdef USE_MGL_NAMESPACE
724
#define GLAPI_PREFIX(func)  mgl##func
725
#define GLAPI_PREFIX_STR(func)  "mgl"#func
726
#else
727
#define GLAPI_PREFIX(func)  gl##func
728
#define GLAPI_PREFIX_STR(func)  "gl"#func
729
#endif /* USE_MGL_NAMESPACE */
730
 
731
typedef int GLclampx;
732
#endif /* _GLAPI_TMP_H_ */"""
733
 
734
        return header
735
 
736
class ES1APIPrinter(GLAPIPrinter):
737
    """OpenGL ES 1.x API Printer"""
738
 
739
    def __init__(self, entries):
740
        super(ES1APIPrinter, self).__init__(entries)
741
        self.prefix_lib = 'gl'
742
        self.prefix_warn = 'gl'
743
 
744
    def _override_for_api(self, ent):
745
        if ent.xml_data is None:
746
            raise Exception('ES2 API printer requires XML input')
747
        ent.hidden = ent.name not in \
748
            ent.xml_data.entry_points_for_api_version('es1')
749
        ent.handcode = False
750
 
751
    def _get_c_header(self):
752
        header = """#ifndef _GLAPI_TMP_H_
753
#define _GLAPI_TMP_H_
754
typedef int GLclampx;
755
#endif /* _GLAPI_TMP_H_ */"""
756
 
757
        return header
758
 
759
class ES2APIPrinter(GLAPIPrinter):
760
    """OpenGL ES 2.x API Printer"""
761
 
762
    def __init__(self, entries):
763
        super(ES2APIPrinter, self).__init__(entries)
764
        self.prefix_lib = 'gl'
765
        self.prefix_warn = 'gl'
766
 
767
    def _override_for_api(self, ent):
768
        if ent.xml_data is None:
769
            raise Exception('ES2 API printer requires XML input')
770
        ent.hidden = ent.name not in \
771
            ent.xml_data.entry_points_for_api_version('es2')
772
        ent.handcode = False
773
 
774
    def _get_c_header(self):
775
        header = """#ifndef _GLAPI_TMP_H_
776
#define _GLAPI_TMP_H_
777
typedef int GLclampx;
778
#endif /* _GLAPI_TMP_H_ */"""
779
 
780
        return header
781
 
782
class SharedGLAPIPrinter(GLAPIPrinter):
783
    """Shared GLAPI API Printer"""
784
 
785
    def __init__(self, entries):
786
        super(SharedGLAPIPrinter, self).__init__(entries)
787
 
788
        self.lib_need_table_size = True
789
        self.lib_need_noop_array = True
790
        self.lib_need_stubs = True
791
        self.lib_need_all_entries = True
792
        self.lib_need_non_hidden_entries = False
793
 
794
        self.prefix_lib = 'shared'
795
        self.prefix_warn = 'gl'
796
 
797
    def _override_for_api(self, ent):
798
        ent.hidden = True
799
        ent.handcode = False
800
 
801
    def _get_c_header(self):
802
        header = """#ifndef _GLAPI_TMP_H_
803
#define _GLAPI_TMP_H_
804
typedef int GLclampx;
805
#endif /* _GLAPI_TMP_H_ */"""
806
 
807
        return header
808
 
809
class VGAPIPrinter(ABIPrinter):
810
    """OpenVG API Printer"""
811
 
812
    def __init__(self, entries):
813
        super(VGAPIPrinter, self).__init__(entries)
814
 
815
        self.api_defines = ['VG_VGEXT_PROTOTYPES']
816
        self.api_headers = ['"VG/openvg.h"', '"VG/vgext.h"']
817
        self.api_call = 'VG_API_CALL'
818
        self.api_entry = 'VG_API_ENTRY'
819
        self.api_attrs = 'VG_API_EXIT'
820
 
821
        self.prefix_lib = 'vg'
822
        self.prefix_app = 'vega'
823
        self.prefix_noop = 'noop'
824
        self.prefix_warn = 'vg'
825
 
826
def parse_args():
827
    printers = ['vgapi', 'glapi', 'es1api', 'es2api', 'shared-glapi']
828
    modes = ['lib', 'app']
829
 
830
    parser = OptionParser(usage='usage: %prog [options] ')
831
    parser.add_option('-p', '--printer', dest='printer',
832
            help='printer to use: %s' % (", ".join(printers)))
833
    parser.add_option('-m', '--mode', dest='mode',
834
            help='target user: %s' % (", ".join(modes)))
835
 
836
    options, args = parser.parse_args()
837
    if not args or options.printer not in printers or \
838
            options.mode not in modes:
839
        parser.print_help()
840
        sys.exit(1)
841
 
842
    return (args[0], options)
843
 
844
def main():
845
    printers = {
846
        'vgapi': VGAPIPrinter,
847
        'glapi': GLAPIPrinter,
848
        'es1api': ES1APIPrinter,
849
        'es2api': ES2APIPrinter,
850
        'shared-glapi': SharedGLAPIPrinter,
851
    }
852
 
853
    filename, options = parse_args()
854
 
855
    if filename.endswith('.xml'):
856
        entries = abi_parse_xml(filename)
857
    else:
858
        entries = abi_parse(filename)
859
    abi_sanity_check(entries)
860
 
861
    printer = printers[options.printer](entries)
862
    if options.mode == 'lib':
863
        printer.output_for_lib()
864
    else:
865
        printer.output_for_app()
866
 
867
if __name__ == '__main__':
868
    main()