mapi: Add a generic C dispatcher.
authorChia-I Wu <olv@lunarg.com>
Fri, 23 Apr 2010 08:07:47 +0000 (16:07 +0800)
committerChia-I Wu <olv@lunarg.com>
Fri, 7 May 2010 02:41:12 +0000 (10:41 +0800)
The idea is to have an API generate a header using mapi_abi.py.  The API
can then use the header to build a dispatcher.

12 files changed:
src/mapi/mapi/entry.c [new file with mode: 0644]
src/mapi/mapi/entry.h [new file with mode: 0644]
src/mapi/mapi/mapi.c [new file with mode: 0644]
src/mapi/mapi/mapi.h [new file with mode: 0644]
src/mapi/mapi/mapi_abi.py [new file with mode: 0644]
src/mapi/mapi/mapi_tmp.h [new file with mode: 0644]
src/mapi/mapi/sources.mak
src/mapi/mapi/stub.c [new file with mode: 0644]
src/mapi/mapi/stub.h [new file with mode: 0644]
src/mapi/mapi/table.c [new file with mode: 0644]
src/mapi/mapi/table.h [new file with mode: 0644]
src/mapi/mapi/u_macros.h [new file with mode: 0644]

diff --git a/src/mapi/mapi/entry.c b/src/mapi/mapi/entry.c
new file mode 100644 (file)
index 0000000..b38df07
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  7.9
+ *
+ * Copyright (C) 2010 LunarG Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Chia-I Wu <olv@lunarg.com>
+ */
+
+#include <stdlib.h>
+#include "u_current.h"
+#include "entry.h"
+#include "table.h"
+
+/* C version of the public entries */
+#define MAPI_TMP_PUBLIC_ENTRIES
+#include "mapi_tmp.h"
+
+void
+entry_patch_public(void)
+{
+}
+
+mapi_func
+entry_generate(int slot)
+{
+   return NULL;
+}
+
+void
+entry_patch(mapi_func entry, int slot)
+{
+}
diff --git a/src/mapi/mapi/entry.h b/src/mapi/mapi/entry.h
new file mode 100644 (file)
index 0000000..48ed3f9
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  7.9
+ *
+ * Copyright (C) 2010 LunarG Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Chia-I Wu <olv@lunarg.com>
+ */
+
+#ifndef _ENTRY_H_
+#define _ENTRY_H_
+
+#include "u_compiler.h"
+#include "stub.h"
+
+/* declare public entries */
+#define MAPI_TMP_DEFINES
+#define MAPI_TMP_PUBLIC_DECLARES
+#include "mapi_tmp.h"
+
+void
+entry_patch_public(void);
+
+mapi_func
+entry_generate(int slot);
+
+void
+entry_patch(mapi_func entry, int slot);
+
+#endif /* _ENTRY_H_ */
diff --git a/src/mapi/mapi/mapi.c b/src/mapi/mapi/mapi.c
new file mode 100644 (file)
index 0000000..2f1c3ff
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  7.9
+ *
+ * Copyright (C) 2010 LunarG Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Chia-I Wu <olv@lunarg.com>
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "u_current.h"
+#include "u_thread.h"
+#include "mapi.h"
+#include "stub.h"
+#include "table.h"
+
+/* dynamic stubs will run out before this array */
+#define MAPI_MAX_STUBS (sizeof(struct mapi_table) / sizeof(mapi_func))
+static const struct mapi_stub *mapi_stub_map[MAPI_MAX_STUBS];
+static int mapi_num_stubs;
+
+static const struct mapi_stub *
+get_stub(const char *name, const struct mapi_stub *alias)
+{
+   const struct mapi_stub *stub;
+
+   stub = stub_find_public(name);
+   if (!stub) {
+      struct mapi_stub *dyn = stub_find_dynamic(name, 1);
+      if (dyn) {
+         stub_fix_dynamic(dyn, alias);
+         stub = dyn;
+      }
+   }
+
+   return stub;
+}
+
+/**
+ * Initialize mapi.  spec consists of NULL-separated strings.  The first string
+ * denotes the version.  It is followed by variable numbers of entries.  Each
+ * entry can have multiple names.  An empty name terminates an entry.  An empty
+ * entry terminates the spec.  A spec of two entries, Foo and Bar, is as
+ * follows
+ *
+ *   "1\0"
+ *   "Foo\0"
+ *   "FooEXT\0"
+ *   "\0"
+ *   "Bar\0"
+ *   "\0"
+ */
+void
+mapi_init(const char *spec)
+{
+   u_mutex_declare_static(mutex);
+   const char *p;
+   int ver, count;
+
+   u_mutex_lock(mutex);
+
+   /* already initialized */
+   if (mapi_num_stubs) {
+      u_mutex_unlock(mutex);
+      return;
+   }
+
+   count = 0;
+   p = spec;
+
+   /* parse version string */
+   ver = atoi(p);
+   if (ver != 1) {
+      u_mutex_unlock(mutex);
+      return;
+   }
+   p += strlen(p) + 1;
+
+   while (*p) {
+      const struct mapi_stub *stub;
+
+      stub = get_stub(p, NULL);
+      /* out of dynamic entries */
+      if (!stub)
+         break;
+      p += strlen(p) + 1;
+
+      while (*p) {
+         get_stub(p, stub);
+         p += strlen(p) + 1;
+      }
+
+      mapi_stub_map[count++] = stub;
+      p++;
+   }
+
+   mapi_num_stubs = count;
+
+   u_mutex_unlock(mutex);
+}
+
+/**
+ * Return the address of an entry.  Optionally generate the entry if it does
+ * not exist.
+ */
+mapi_proc
+mapi_get_proc_address(const char *name)
+{
+   const struct mapi_stub *stub;
+
+   stub = stub_find_public(name);
+   if (!stub)
+      stub = stub_find_dynamic(name, 0);
+
+   return (stub) ? (mapi_proc) stub->addr : NULL;
+}
+
+/**
+ * Create a dispatch table.
+ */
+struct mapi_table *
+mapi_table_create(void)
+{
+   const struct mapi_table *noop = table_get_noop();
+   struct mapi_table *tbl;
+
+   tbl = malloc(sizeof(*tbl));
+   if (tbl)
+      memcpy(tbl, noop, sizeof(*tbl));
+
+   return tbl;
+}
+
+/**
+ * Destroy a dispatch table.
+ */
+void
+mapi_table_destroy(struct mapi_table *tbl)
+{
+   free(tbl);
+}
+
+/**
+ * Fill a dispatch table.  The order of the procs is determined when mapi_init
+ * is called.
+ */
+void
+mapi_table_fill(struct mapi_table *tbl, const mapi_proc *procs)
+{
+   const struct mapi_table *noop = table_get_noop();
+   int i;
+
+   for (i = 0; i < mapi_num_stubs; i++) {
+      const struct mapi_stub *stub = mapi_stub_map[i];
+      mapi_func func = (mapi_func) procs[i];
+
+      if (!func)
+         func = table_get_func(noop, stub);
+      table_set_func(tbl, stub, func);
+   }
+}
+
+/**
+ * Make a dispatch table current.
+ */
+void
+mapi_table_make_current(const struct mapi_table *tbl)
+{
+   u_current_set(tbl);
+}
diff --git a/src/mapi/mapi/mapi.h b/src/mapi/mapi/mapi.h
new file mode 100644 (file)
index 0000000..8832b3d
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  7.9
+ *
+ * Copyright (C) 2010 LunarG Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Chia-I Wu <olv@lunarg.com>
+ */
+
+#ifndef _MAPI_H_
+#define _MAPI_H_
+
+#include "u_compiler.h"
+
+typedef void (*mapi_proc)(void);
+
+struct mapi_table;
+
+PUBLIC void
+mapi_init(const char *spec);
+
+PUBLIC mapi_proc
+mapi_get_proc_address(const char *name);
+
+PUBLIC struct mapi_table *
+mapi_table_create(void);
+
+PUBLIC void
+mapi_table_destroy(struct mapi_table *tbl);
+
+PUBLIC void
+mapi_table_fill(struct mapi_table *tbl, const mapi_proc *procs);
+
+PUBLIC void
+mapi_table_make_current(const struct mapi_table *tbl);
+
+#endif /* _MAPI_H_ */
diff --git a/src/mapi/mapi/mapi_abi.py b/src/mapi/mapi/mapi_abi.py
new file mode 100644 (file)
index 0000000..440eb4b
--- /dev/null
@@ -0,0 +1,402 @@
+#!/usr/bin/env python
+
+# Mesa 3-D graphics library
+# Version:  7.9
+#
+# Copyright (C) 2010 LunarG Inc.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+#
+# Authors:
+#    Chia-I Wu <olv@lunarg.com>
+
+import sys
+import re
+from optparse import OptionParser
+
+# number of dynamic entries
+ABI_NUM_DYNAMIC_ENTRIES = 256
+
+class ABIEntry(object):
+    """Represent an ABI entry."""
+
+    _match_c_param = re.compile(
+            '^(?P<type>[\w\s*]+?)(?P<name>\w+)(\[(?P<array>\d+)\])?$')
+
+    def __init__(self, cols, attrs):
+        self._parse(cols)
+
+        self.slot = attrs['slot']
+        self.hidden = attrs['hidden']
+        self.alias = attrs['alias']
+
+    def c_prototype(self):
+        return '%s %s(%s)' % (self.c_return(), self.name, self.c_params())
+
+    def c_return(self):
+        ret = self.ret
+        if not ret:
+            ret = 'void'
+
+        return ret
+
+    def c_params(self):
+        """Return the parameter list used in the entry prototype."""
+        c_params = []
+        for t, n, a in self.params:
+            sep = '' if t.endswith('*') else ' '
+            arr = '[%d]' % a if a else ''
+            c_params.append(t + sep + n + arr)
+        if not c_params:
+            c_params.append('void')
+
+        return ", ".join(c_params)
+
+    def c_args(self):
+        """Return the argument list used in the entry invocation."""
+        c_args = []
+        for t, n, a in self.params:
+            c_args.append(n)
+
+        return ", ".join(c_args)
+
+    def _parse(self, cols):
+        ret = cols.pop(0)
+        if ret == 'void':
+            ret = None
+
+        name = cols.pop(0)
+
+        params = []
+        if not cols:
+            raise Exception(cols)
+        elif len(cols) == 1 and cols[0] == 'void':
+            pass
+        else:
+            for val in cols:
+                params.append(self._parse_param(val))
+
+        self.ret = ret
+        self.name = name
+        self.params = params
+
+    def _parse_param(self, c_param):
+        m = self._match_c_param.match(c_param)
+        if not m:
+            raise Exception('unrecognized param ' + c_param)
+
+        c_type = m.group('type').strip()
+        c_name = m.group('name')
+        c_array = m.group('array')
+        c_array = int(c_array) if c_array else 0
+
+        return (c_type, c_name, c_array)
+
+    def __str__(self):
+        return self.c_prototype()
+
+    def __cmp__(self, other):
+        # compare slot, alias, and then name
+        res = cmp(self.slot, other.slot)
+        if not res:
+            if not self.alias:
+                res = -1
+            elif not other.alias:
+                res = 1
+
+            if not res:
+                res = cmp(self.name, other.name)
+
+        return res
+
+def abi_parse_line(line):
+    cols = [col.strip() for col in line.split(',')]
+
+    attrs = {
+            'slot': -1,
+            'hidden': False,
+            'alias': None,
+    }
+
+    # extract attributes from the first column
+    vals = cols[0].split(':')
+    while len(vals) > 1:
+        val = vals.pop(0)
+        if val.startswith('slot='):
+            attrs['slot'] = int(val[5:])
+        elif val == 'hidden':
+            attrs['hidden'] = True
+        elif val.startswith('alias='):
+            attrs['alias'] = val[6:]
+        elif not val:
+            pass
+        else:
+            raise Exception('unknown attribute %s' % val)
+    cols[0] = vals[0]
+
+    return (attrs, cols)
+
+def abi_parse(filename):
+    """Parse a CSV file for ABI entries."""
+    fp = open(filename) if filename != '-' else sys.stdin
+    lines = [line.strip() for line in fp.readlines()
+            if not line.startswith('#') and line.strip()]
+
+    entry_dict = {}
+    next_slot = 0
+    for line in lines:
+        attrs, cols = abi_parse_line(line)
+
+        # post-process attributes
+        if attrs['alias']:
+            try:
+                ent = entry_dict[attrs['alias']]
+                slot = ent.slot
+            except KeyError:
+                raise Exception('failed to alias %s' % attrs['alias'])
+        else:
+            slot = next_slot
+            next_slot += 1
+
+        if attrs['slot'] < 0:
+            attrs['slot'] = slot
+        elif attrs['slot'] != slot:
+            raise Exception('invalid slot in %s' % (line))
+
+        ent = ABIEntry(cols, attrs)
+        if entry_dict.has_key(ent.name):
+            raise Exception('%s is duplicated' % (ent.name))
+        entry_dict[ent.name] = ent
+
+    entries = entry_dict.values()
+    entries.sort()
+
+    # sanity check
+    i = 0
+    for slot in xrange(next_slot):
+        if entries[i].slot != slot:
+            raise Exception('entries are not ordered by slots')
+        if entries[i].alias:
+            raise Exception('first entry of slot %d aliases %s'
+                    % (slot, entries[i].alias))
+        while i < len(entries) and entries[i].slot == slot:
+            i += 1
+    if i < len(entries):
+        raise Exception('there are %d invalid entries' % (len(entries) - 1))
+
+    return entries
+
+def abi_dynamics():
+    """Return the dynamic entries."""
+    entries = []
+    for i in xrange(ABI_NUM_DYNAMIC_ENTRIES):
+        cols = ['void', 'dynamic%d' % (i), 'void']
+        attrs = { 'slot': -1, 'hidden': False, 'alias': None }
+        entries.append(ABIEntry(cols, attrs))
+    return entries
+
+class ABIPrinter(object):
+    """ABIEntry Printer"""
+
+    def __init__(self, entries, options):
+        self.entries = entries
+        self.options = options
+        self._undefs = []
+
+    def _add_undefs(self, undefs):
+        self._undefs.extend(undefs)
+
+    def output_header(self):
+        print '/* This file is automatically generated.  Do not modify. */'
+        print
+
+    def output_footer(self):
+        print '/* clean up */'
+        for m in self._undefs:
+            print '#undef %s' % (m)
+
+    def output_entry(self, ent):
+        if ent.slot < 0:
+            out_ent = 'MAPI_DYNAMIC_ENTRY(%s, %s, (%s))' % \
+                    (ent.c_return(), ent.name, ent.c_params())
+            out_code = ''
+        else:
+            if ent.alias:
+                macro_ent = 'MAPI_ALIAS_ENTRY'
+                macro_code = 'MAPI_ALIAS_CODE'
+            else:
+                macro_ent = 'MAPI_ABI_ENTRY'
+                macro_code = 'MAPI_ABI_CODE'
+
+            if ent.ret:
+                macro_code += '_RETURN'
+            if ent.hidden:
+                macro_ent += '_HIDDEN'
+                macro_code += '_HIDDEN'
+
+            if ent.alias:
+                out_ent = '%s(%s, %s, %s, (%s))' % (macro_ent,
+                        ent.alias, ent.c_return(), ent.name, ent.c_params())
+                out_code = '%s(%s, %s, %s, (%s))' % (macro_code,
+                        ent.alias, ent.c_return(), ent.name, ent.c_args())
+            else:
+                out_ent = '%s(%s, %s, (%s))' % (macro_ent,
+                        ent.c_return(), ent.name, ent.c_params())
+                out_code = '%s(%s, %s, (%s))' % (macro_code,
+                        ent.c_return(), ent.name, ent.c_args())
+
+        print out_ent
+        if out_code:
+            print '   ' + out_code
+
+    def output_entries(self, pool_offsets):
+        defs = [
+                # normal entries
+                ('MAPI_ABI_ENTRY', '(ret, name, params)', ''),
+                ('MAPI_ABI_CODE', '(ret, name, args)', ''),
+                ('MAPI_ABI_CODE_RETURN', '', 'MAPI_ABI_CODE'),
+                # alias entries
+                ('MAPI_ALIAS_ENTRY', '(alias, ret, name, params)', ''),
+                ('MAPI_ALIAS_CODE', '(alias, ret, name, args)', ''),
+                ('MAPI_ALIAS_CODE_RETURN', '', 'MAPI_ALIAS_CODE'),
+                # hidden normal entries
+                ('MAPI_ABI_ENTRY_HIDDEN', '', 'MAPI_ABI_ENTRY'),
+                ('MAPI_ABI_CODE_HIDDEN', '', 'MAPI_ABI_CODE'),
+                ('MAPI_ABI_CODE_RETURN_HIDDEN', '', 'MAPI_ABI_CODE_RETURN'),
+                # hidden alias entries
+                ('MAPI_ALIAS_ENTRY_HIDDEN', '', 'MAPI_ALIAS_ENTRY'),
+                ('MAPI_ALIAS_CODE_HIDDEN', '', 'MAPI_ALIAS_CODE'),
+                ('MAPI_ALIAS_CODE_RETURN_HIDDEN', '', 'MAPI_ALIAS_CODE_RETURN'),
+                # dynamic entries
+                ('MAPI_DYNAMIC_ENTRY', '(ret, name, params)', ''),
+        ]
+        undefs = [d[0] for d in defs]
+
+        print '#if defined(MAPI_ABI_ENTRY) || defined(MAPI_ABI_ENTRY_HIDDEN)'
+        print
+        for d in defs:
+            print '#ifndef %s' % (d[0])
+            if d[2]:
+                print '#define %s%s %s' % d
+            else:
+                print '#define %s%s' % d[:2]
+
+            print '#endif'
+        print
+
+        print '/* see MAPI_TMP_TABLE */'
+        for ent in self.entries:
+            print '#define MAPI_SLOT_%s %d' % (ent.name, ent.slot)
+        print
+        print '/* see MAPI_TMP_PUBLIC_STUBS */'
+        for ent in self.entries:
+            print '#define MAPI_POOL_%s %d' % (ent.name, pool_offsets[ent])
+        print
+
+        # define macros that generate code
+        for ent in self.entries:
+            self.output_entry(ent)
+        print
+        dynamics = abi_dynamics()
+        for ent in dynamics:
+            self.output_entry(ent)
+        print
+
+        for ent in self.entries:
+            print '#undef MAPI_SLOT_%s' % (ent.name)
+        for ent in self.entries:
+            print '#undef MAPI_POOL_%s' % (ent.name)
+        print
+        print '#endif /* defined(MAPI_ABI_ENTRY) || defined(MAPI_ABI_ENTRY_HIDDEN) */'
+        print
+
+        self._add_undefs(undefs)
+
+    def _get_string_pool(self):
+        """Get the string pool."""
+        pool = []
+        offsets = {}
+
+        count = 0
+        for ent in self.entries:
+            offsets[ent] = count
+            pool.append(ent.name + '\\0')
+            count += len(ent.name) + 1
+
+        return (pool, offsets)
+
+    def output_sorted_indices(self):
+        entry_index_pairs = []
+        for i in xrange(len(self.entries)):
+            entry_index_pairs.append((self.entries[i], i))
+        entry_index_pairs.sort(lambda x, y: cmp(x[0].name, y[0].name))
+
+        print '/* see MAPI_TMP_PUBLIC_STUBS */'
+        print '#ifdef MAPI_ABI_SORTED_INDICES'
+        print
+        print 'static const int MAPI_ABI_SORTED_INDICES[] = {'
+        for ent, idx in entry_index_pairs:
+            print '   %d, /* %s */' % (idx, ent.name)
+        print '   -1'
+        print '};'
+        print
+        print '#endif /* MAPI_ABI_SORTED_INDICES */'
+        print
+
+        self._add_undefs(['MAPI_ABI_SORTED_INDICES'])
+
+    def output_defines(self):
+        print '/* ABI defines */'
+        print '#ifdef MAPI_ABI_DEFINES'
+        print '#include "%s"' % (self.options.include)
+        print '#endif /* MAPI_ABI_DEFINES */'
+        print
+
+        self._add_undefs(['MAPI_ABI_DEFINES'])
+
+    def output(self):
+        pool, pool_offsets = self._get_string_pool()
+
+        self.output_header()
+        self.output_defines()
+        self.output_entries(pool_offsets)
+        self.output_sorted_indices()
+        self.output_footer()
+
+def parse_args():
+    parser = OptionParser(usage='usage: %prog [options] <filename>')
+    parser.add_option('-i', '--include', dest='include',
+            help='include the header for API defines')
+
+    options, args = parser.parse_args()
+    if not args or not options.include:
+        parser.print_help()
+        sys.exit(1)
+
+    return (args[0], options)
+
+def main():
+    filename, options = parse_args()
+
+    entries = abi_parse(filename)
+    printer = ABIPrinter(entries, options)
+    printer.output()
+
+if __name__ == '__main__':
+    main()
diff --git a/src/mapi/mapi/mapi_tmp.h b/src/mapi/mapi/mapi_tmp.h
new file mode 100644 (file)
index 0000000..da4e8ae
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  7.9
+ *
+ * Copyright (C) 2010 LunarG Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Chia-I Wu <olv@lunarg.com>
+ */
+
+#include "u_macros.h"
+
+#ifndef MAPI_ABI_HEADER
+#error "MAPI_ABI_HEADER must be defined"
+#endif
+
+
+/**
+ * Get API defines.
+ */
+#ifdef MAPI_TMP_DEFINES
+#   define MAPI_ABI_DEFINES
+#   include MAPI_ABI_HEADER
+
+#ifndef MAPI_ABI_PREFIX
+#error "MAPI_ABI_PREFIX must be defined"
+#endif
+#ifndef MAPI_ABI_PUBLIC
+#error "MAPI_ABI_PUBLIC must be defined"
+#endif
+#ifndef MAPI_ABI_ATTR
+#error "MAPI_ABI_ATTR must be defined"
+#endif
+
+#undef MAPI_TMP_DEFINES
+#endif /* MAPI_TMP_DEFINES */
+
+
+/**
+ * Generate fields of struct mapi_table.
+ */
+#ifdef MAPI_TMP_TABLE
+#   define MAPI_ABI_ENTRY(ret, name, params)                   \
+      ret (MAPI_ABI_ATTR *name) params;
+#   define MAPI_DYNAMIC_ENTRY(ret, name, params)               \
+      ret (MAPI_ABI_ATTR *name) params;
+#   include MAPI_ABI_HEADER
+#undef MAPI_TMP_TABLE
+#endif /* MAPI_TMP_TABLE */
+
+
+/**
+ * Declare public entries.
+ */
+#ifdef MAPI_TMP_PUBLIC_DECLARES
+#   define MAPI_ABI_ENTRY(ret, name, params)                   \
+      MAPI_ABI_PUBLIC ret MAPI_ABI_ATTR U_CONCAT(MAPI_ABI_PREFIX, name) params;
+#   define MAPI_ALIAS_ENTRY(alias, ret, name, params)          \
+      MAPI_ABI_ENTRY(ret, name, params);
+#   define MAPI_ABI_ENTRY_HIDDEN(ret, name, params)            \
+      HIDDEN ret MAPI_ABI_ATTR U_CONCAT(MAPI_ABI_PREFIX, name) params;
+#   define MAPI_ALIAS_ENTRY_HIDDEN(alias, ret, name, params)   \
+      MAPI_ABI_ENTRY_HIDDEN(ret, name, params)
+#   include MAPI_ABI_HEADER
+#undef MAPI_TMP_PUBLIC_DECLARES
+#endif /* MAPI_TMP_PUBLIC_DECLARES */
+
+
+/**
+ * Generate string pool and public stubs.
+ */
+#ifdef MAPI_TMP_PUBLIC_STUBS
+/* define the string pool */
+static const char public_string_pool[] =
+#   define MAPI_ABI_ENTRY(ret, name, params)                   \
+      U_STRINGIFY(name) "\0"
+#   define MAPI_ALIAS_ENTRY(alias, ret, name, params)          \
+      MAPI_ABI_ENTRY(ret, name, params)
+#   include MAPI_ABI_HEADER
+   ;
+/* define public_sorted_indices */
+#   define MAPI_ABI_SORTED_INDICES public_sorted_indices
+#   include MAPI_ABI_HEADER
+
+/* define public_stubs */
+static const struct mapi_stub public_stubs[] = {
+#   define MAPI_ABI_ENTRY(ret, name, params)                   \
+      { (mapi_func) U_CONCAT(MAPI_ABI_PREFIX, name),           \
+         MAPI_SLOT_ ## name, (void *) MAPI_POOL_ ## name },
+#   define MAPI_ALIAS_ENTRY(alias, ret, name, params)          \
+      MAPI_ABI_ENTRY(ret, name, params)
+#   include MAPI_ABI_HEADER
+   { NULL, -1, (void *) -1 }
+};
+
+#undef MAPI_TMP_PUBLIC_STUBS
+#endif /* MAPI_TMP_PUBLIC_STUBS */
+
+
+/**
+ * Generate public entries.
+ */
+#ifdef MAPI_TMP_PUBLIC_ENTRIES
+#   define MAPI_ABI_ENTRY(ret, name, params)                   \
+      ret MAPI_ABI_ATTR U_CONCAT(MAPI_ABI_PREFIX, name) params
+#   define MAPI_ABI_CODE(ret, name, args)                      \
+      {                                                        \
+         const struct mapi_table *tbl = u_current_get();       \
+         tbl->name args;                                       \
+      }
+#   define MAPI_ABI_CODE_RETURN(ret, name, args)               \
+      {                                                        \
+         const struct mapi_table *tbl = u_current_get();       \
+         return tbl->name args;                                \
+      }
+#   define MAPI_ALIAS_ENTRY(alias, ret, name, params)          \
+      MAPI_ABI_ENTRY(ret, name, params)
+#   define MAPI_ALIAS_CODE(alias, ret, name, args)             \
+      MAPI_ABI_CODE(ret, alias, args)
+#   define MAPI_ALIAS_CODE_RETURN(alias, ret, name, args)      \
+      MAPI_ABI_CODE_RETURN(ret, alias, args)
+#   include MAPI_ABI_HEADER
+#undef MAPI_TMP_PUBLIC_ENTRIES
+#endif /* MAPI_TMP_PUBLIC_ENTRIES */
+
+
+/**
+ * Generate noop entries.
+ */
+#ifdef MAPI_TMP_NOOP_ARRAY
+#ifdef DEBUG
+#   define MAPI_ABI_ENTRY(ret, name, params)                         \
+      static ret MAPI_ABI_ATTR U_CONCAT(noop_, name) params
+#   define MAPI_ABI_CODE(ret, name, args)                            \
+      {                                                              \
+         noop_warn(U_CONCAT_STR(MAPI_ABI_PREFIX, name));             \
+      }
+#   define MAPI_ABI_CODE_RETURN(ret, name, args)                     \
+      {                                                              \
+         noop_warn(U_CONCAT_STR(MAPI_ABI_PREFIX, name));             \
+         return (ret) 0;                                             \
+      }
+#   include MAPI_ABI_HEADER
+
+/* define the noop function array that may be casted to mapi_table */
+const mapi_func table_noop_array[] = {
+#   define MAPI_ABI_ENTRY(ret, name, params)                   \
+      (mapi_func) U_CONCAT(noop_, name),
+#   define MAPI_DYNAMIC_ENTRY(ret, name, params)               \
+      (mapi_func) noop_generic,
+#   include MAPI_ABI_HEADER
+      (mapi_func) noop_generic
+};
+
+#else /* DEBUG */
+
+const mapi_func table_noop_array[] = {
+#   define MAPI_ABI_ENTRY(ret, name, params)                   \
+      (mapi_func) noop_generic,
+#   define MAPI_DYNAMIC_ENTRY(ret, name, params)               \
+      (mapi_func) noop_generic,
+#   include MAPI_ABI_HEADER
+      (mapi_func) noop_generic
+};
+
+#endif /* DEBUG */
+#undef MAPI_TMP_NOOP_ARRAY
+#endif /* MAPI_TMP_NOOP_ARRAY */
index 9e27f45e2a99237f6a85dee9ba8c0057f0e1ef70..5f327f3df628809036f22ed563a471461348159f 100644 (file)
@@ -1,6 +1,19 @@
 # src/mapi/mapi/sources.mak
+#
+# When MAPI_GLAPI_CURRENT is defined, MAPI_GLAPI_SOURCES can be built without
+# MAPI_SOURCES and it is used by glapi.
+#
+# Otherwise, MAPI_ABI_HEADER must be defined.  It should expand to the header
+# generated by mapi_abi.py.
 
 MAPI_GLAPI_SOURCES = \
        u_current.c \
        u_execmem.c \
        u_thread.c
+
+MAPI_SOURCES = \
+       entry.c \
+       mapi.c \
+       stub.c \
+       table.c \
+       $(MAPI_GLAPI_SOURCES)
diff --git a/src/mapi/mapi/stub.c b/src/mapi/mapi/stub.c
new file mode 100644 (file)
index 0000000..8ceaec3
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  7.9
+ *
+ * Copyright (C) 2010 LunarG Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Chia-I Wu <olv@lunarg.com>
+ */
+
+#include <stdlib.h>
+#include <stddef.h> /* for offsetof */
+#include <string.h>
+#include <assert.h>
+
+#include "u_current.h"
+#include "u_thread.h"
+#include "entry.h"
+#include "stub.h"
+#include "table.h"
+
+#define MAPI_TABLE_FIRST_DYNAMIC \
+   (offsetof(struct mapi_table, dynamic0) / sizeof(mapi_func))
+#define MAPI_TABLE_NUM_DYNAMIC \
+   ((offsetof(struct mapi_table, last) - \
+     offsetof(struct mapi_table, dynamic0)) / sizeof(mapi_func))
+#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
+
+/*
+ * This will define public_string_pool, public_sorted_indices, and
+ * public_stubs.
+ */
+#define MAPI_TMP_PUBLIC_STUBS
+#include "mapi_tmp.h"
+
+static struct mapi_stub dynamic_stubs[MAPI_TABLE_NUM_DYNAMIC];
+static int num_dynamic_stubs;
+static int next_dynamic_slot = MAPI_TABLE_FIRST_DYNAMIC;
+
+void
+stub_init_once(void)
+{
+#ifdef PTHREADS
+   static pthread_once_t once = PTHREAD_ONCE_INIT;
+   pthread_once(&once, entry_patch_public);
+#else
+   static int first = 1;
+   if (first) {
+      first = 0;
+      entry_patch_public();
+   }
+#endif
+}
+
+static int
+stub_compare(const void *key, const void *elem)
+{
+   const char *name = (const char *) key;
+   const int *index = (const int *) elem;
+   const struct mapi_stub *stub;
+   const char *stub_name;
+
+   stub = &public_stubs[*index];
+   stub_name = &public_string_pool[(unsigned long) stub->name];
+
+   return strcmp(name, stub_name);
+}
+
+/**
+ * Return the public stub with the given name.
+ */
+const struct mapi_stub *
+stub_find_public(const char *name)
+{
+   const int *index;
+
+   index = (const int *) bsearch(name, public_sorted_indices,
+         ARRAY_SIZE(public_sorted_indices) - 1,
+         sizeof(public_sorted_indices[0]), stub_compare);
+
+   return (index) ? &public_stubs[*index] : NULL;
+}
+
+/**
+ * Add a dynamic stub.
+ */
+static struct mapi_stub *
+stub_add_dynamic(const char *name)
+{
+   struct mapi_stub *stub;
+   int idx;
+
+   idx = num_dynamic_stubs;
+   if (idx >= MAPI_TABLE_NUM_DYNAMIC)
+      return NULL;
+
+   stub = &dynamic_stubs[idx];
+
+   /* dispatch to mapi_table->last, which is always no-op */
+   stub->addr =
+      entry_generate(MAPI_TABLE_FIRST_DYNAMIC + MAPI_TABLE_NUM_DYNAMIC);
+   if (!stub->addr)
+      return NULL;
+
+   stub->name = (const void *) name;
+   /* to be fixed later */
+   stub->slot = -1;
+
+   num_dynamic_stubs = idx + 1;
+
+   return stub;
+}
+
+/**
+ * Return the dynamic stub with the given name.  If no such stub exists and
+ * generate is true, a new stub is generated.
+ */
+struct mapi_stub *
+stub_find_dynamic(const char *name, int generate)
+{
+   u_mutex_declare_static(dynamic_mutex);
+   struct mapi_stub *stub = NULL;
+   int count, i;
+   
+   u_mutex_lock(dynamic_mutex);
+
+   if (generate)
+      assert(!stub_find_public(name));
+
+   count = num_dynamic_stubs;
+   for (i = 0; i < count; i++) {
+      if (strcmp(name, (const char *) dynamic_stubs[i].name) == 0) {
+         stub = &dynamic_stubs[i];
+         break;
+      }
+   }
+
+   /* generate a dynamic stub */
+   if (generate && !stub)
+         stub = stub_add_dynamic(name);
+
+   u_mutex_unlock(dynamic_mutex);
+
+   return stub;
+}
+
+void
+stub_fix_dynamic(struct mapi_stub *stub, const struct mapi_stub *alias)
+{
+   int slot;
+
+   if (stub->slot >= 0)
+      return;
+
+   if (alias)
+      slot = alias->slot;
+   else
+      slot = next_dynamic_slot++;
+
+   entry_patch(stub->addr, slot);
+   stub->slot = slot;
+}
diff --git a/src/mapi/mapi/stub.h b/src/mapi/mapi/stub.h
new file mode 100644 (file)
index 0000000..c7e194c
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  7.9
+ *
+ * Copyright (C) 2010 LunarG Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Chia-I Wu <olv@lunarg.com>
+ */
+
+#ifndef _STUB_H_
+#define _STUB_H_
+
+typedef void (*mapi_func)(void);
+
+struct mapi_stub {
+   mapi_func addr;
+   int slot;
+   const void *name;
+};
+
+void
+stub_init_once(void);
+
+const struct mapi_stub *
+stub_find_public(const char *name);
+
+struct mapi_stub *
+stub_find_dynamic(const char *name, int generate);
+
+void
+stub_fix_dynamic(struct mapi_stub *stub, const struct mapi_stub *alias);
+
+#endif /* _STUB_H_ */
diff --git a/src/mapi/mapi/table.c b/src/mapi/mapi/table.c
new file mode 100644 (file)
index 0000000..8f4f700
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  7.9
+ *
+ * Copyright (C) 2010 LunarG Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Chia-I Wu <olv@lunarg.com>
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "stub.h"
+#include "table.h"
+
+static void
+noop_warn(const char *name)
+{
+   static int debug = -1;
+   
+   if (debug < 0)
+      debug = (getenv("MESA_DEBUG") || getenv("LIBGL_DEBUG"));
+
+   if (debug)
+      fprintf(stderr, "%s is no-op", name);
+}
+
+static int
+noop_generic(void)
+{
+   noop_warn("function");
+   return 0;
+}
+
+/* define noop_array */
+#define MAPI_TMP_NOOP_ARRAY
+#include "mapi_tmp.h"
diff --git a/src/mapi/mapi/table.h b/src/mapi/mapi/table.h
new file mode 100644 (file)
index 0000000..48c9901
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  7.9
+ *
+ * Copyright (C) 2010 LunarG Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Chia-I Wu <olv@lunarg.com>
+ */
+
+#ifndef _TABLE_H_
+#define _TABLE_H_
+
+#include "u_compiler.h"
+#include "stub.h"
+
+#define MAPI_TMP_DEFINES
+#include "mapi_tmp.h"
+
+struct mapi_table {
+#define MAPI_TMP_TABLE
+#include "mapi_tmp.h"
+   mapi_func last;
+};
+
+extern const mapi_func table_noop_array[];
+
+/**
+ * Get the no-op dispatch table.
+ */
+static INLINE const struct mapi_table *
+table_get_noop(void)
+{
+   return (const struct mapi_table *) table_noop_array;
+}
+
+/**
+ * Update the dispatch table to dispatch a stub to the given function.
+ */
+static INLINE void
+table_set_func(struct mapi_table *tbl,
+               const struct mapi_stub *stub, mapi_func func)
+{
+   mapi_func *funcs = (mapi_func *) tbl;
+   funcs[stub->slot] = func;
+}
+
+/**
+ * Return the dispatched function of a stub.
+ */
+static INLINE mapi_func
+table_get_func(const struct mapi_table *tbl, const struct mapi_stub *stub)
+{
+   const mapi_func *funcs = (const mapi_func *) tbl;
+   return funcs[stub->slot];
+}
+
+#endif /* _TABLE_H_ */
diff --git a/src/mapi/mapi/u_macros.h b/src/mapi/mapi/u_macros.h
new file mode 100644 (file)
index 0000000..72345b5
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef _U_MACROS_
+#define _U_MACROS_
+
+#define _U_STRINGIFY(x) #x
+#define _U_CONCAT(x, y) x ## y
+#define _U_CONCAT_STR(x, y) #x#y
+
+#define U_STRINGIFY(x) _U_STRINGIFY(x)
+#define U_CONCAT(x, y) _U_CONCAT(x, y)
+#define U_CONCAT_STR(x, y) _U_CONCAT_STR(x, y)
+
+#endif /* _U_MACROS_ */