1d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu/*
2d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu * Mesa 3-D graphics library
3d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu * Version:  7.9
4d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu *
5d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu * Copyright (C) 2010 LunarG Inc.
6d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu *
7d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu * Permission is hereby granted, free of charge, to any person obtaining a
8d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu * copy of this software and associated documentation files (the "Software"),
9d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu * to deal in the Software without restriction, including without limitation
10d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu * and/or sell copies of the Software, and to permit persons to whom the
12d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu * Software is furnished to do so, subject to the following conditions:
13d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu *
14d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu * The above copyright notice and this permission notice shall be included
15d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu * in all copies or substantial portions of the Software.
16d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu *
17d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu * DEALINGS IN THE SOFTWARE.
24d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu *
25d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu * Authors:
26d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu *    Chia-I Wu <olv@lunarg.com>
27d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu */
28d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu
29d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu#include <stdlib.h>
30d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu#include <string.h>
31d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu
32d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu#include "u_current.h"
33d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu#include "u_thread.h"
34d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu#include "mapi.h"
35d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu#include "stub.h"
36d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu#include "table.h"
37d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu
38d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu/* dynamic stubs will run out before this array */
398f2a974cf2c9b6c00dfac11be4316a7d121dfbb4Chia-I Wustatic const struct mapi_stub *mapi_stub_map[MAPI_TABLE_NUM_SLOTS];
40d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wustatic int mapi_num_stubs;
41d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu
42d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wustatic const struct mapi_stub *
43d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wuget_stub(const char *name, const struct mapi_stub *alias)
44d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu{
45d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu   const struct mapi_stub *stub;
46d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu
47d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu   stub = stub_find_public(name);
48d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu   if (!stub) {
49d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu      struct mapi_stub *dyn = stub_find_dynamic(name, 1);
50d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu      if (dyn) {
51d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu         stub_fix_dynamic(dyn, alias);
52d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu         stub = dyn;
53d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu      }
54d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu   }
55d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu
56d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu   return stub;
57d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu}
58d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu
59d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu/**
60d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu * Initialize mapi.  spec consists of NULL-separated strings.  The first string
61d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu * denotes the version.  It is followed by variable numbers of entries.  Each
62d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu * entry can have multiple names.  An empty name terminates an entry.  An empty
63d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu * entry terminates the spec.  A spec of two entries, Foo and Bar, is as
64d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu * follows
65d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu *
66d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu *   "1\0"
67d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu *   "Foo\0"
68d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu *   "FooEXT\0"
69d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu *   "\0"
70d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu *   "Bar\0"
71d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu *   "\0"
72d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu */
73d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wuvoid
74d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wumapi_init(const char *spec)
75d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu{
76d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu   u_mutex_declare_static(mutex);
77d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu   const char *p;
78d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu   int ver, count;
79d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu
80d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu   u_mutex_lock(mutex);
81d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu
82d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu   /* already initialized */
83d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu   if (mapi_num_stubs) {
84d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu      u_mutex_unlock(mutex);
85d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu      return;
86d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu   }
87d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu
88d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu   count = 0;
89d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu   p = spec;
90d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu
91d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu   /* parse version string */
92d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu   ver = atoi(p);
93d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu   if (ver != 1) {
94d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu      u_mutex_unlock(mutex);
95d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu      return;
96d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu   }
97d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu   p += strlen(p) + 1;
98d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu
99d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu   while (*p) {
100d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu      const struct mapi_stub *stub;
101d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu
102d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu      stub = get_stub(p, NULL);
103d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu      /* out of dynamic entries */
104d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu      if (!stub)
105d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu         break;
106d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu      p += strlen(p) + 1;
107d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu
108d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu      while (*p) {
109d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu         get_stub(p, stub);
110d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu         p += strlen(p) + 1;
111d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu      }
112d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu
113d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu      mapi_stub_map[count++] = stub;
114d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu      p++;
115d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu   }
116d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu
117d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu   mapi_num_stubs = count;
118d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu
119d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu   u_mutex_unlock(mutex);
120d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu}
121d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu
122d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu/**
123d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu * Return the address of an entry.  Optionally generate the entry if it does
124d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu * not exist.
125d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu */
126d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wumapi_proc
127d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wumapi_get_proc_address(const char *name)
128d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu{
129d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu   const struct mapi_stub *stub;
130d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu
131d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu   stub = stub_find_public(name);
132d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu   if (!stub)
133d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu      stub = stub_find_dynamic(name, 0);
134d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu
135897bff67734ec9ab213191386cdf09ddd051aebbChia-I Wu   return (stub) ? (mapi_proc) stub_get_addr(stub) : NULL;
136d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu}
137d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu
138d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu/**
139d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu * Create a dispatch table.
140d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu */
141d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wustruct mapi_table *
142d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wumapi_table_create(void)
143d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu{
144d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu   const struct mapi_table *noop = table_get_noop();
145d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu   struct mapi_table *tbl;
146d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu
1478f2a974cf2c9b6c00dfac11be4316a7d121dfbb4Chia-I Wu   tbl = malloc(MAPI_TABLE_SIZE);
148d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu   if (tbl)
1498f2a974cf2c9b6c00dfac11be4316a7d121dfbb4Chia-I Wu      memcpy(tbl, noop, MAPI_TABLE_SIZE);
150d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu
151d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu   return tbl;
152d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu}
153d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu
154d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu/**
155d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu * Destroy a dispatch table.
156d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu */
157d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wuvoid
158d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wumapi_table_destroy(struct mapi_table *tbl)
159d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu{
160d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu   free(tbl);
161d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu}
162d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu
163d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu/**
164d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu * Fill a dispatch table.  The order of the procs is determined when mapi_init
165d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu * is called.
166d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu */
167d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wuvoid
168d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wumapi_table_fill(struct mapi_table *tbl, const mapi_proc *procs)
169d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu{
170d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu   const struct mapi_table *noop = table_get_noop();
171d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu   int i;
172d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu
173d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu   for (i = 0; i < mapi_num_stubs; i++) {
174d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu      const struct mapi_stub *stub = mapi_stub_map[i];
175897bff67734ec9ab213191386cdf09ddd051aebbChia-I Wu      int slot = stub_get_slot(stub);
176d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu      mapi_func func = (mapi_func) procs[i];
177d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu
178d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu      if (!func)
179897bff67734ec9ab213191386cdf09ddd051aebbChia-I Wu         func = table_get_func(noop, slot);
180897bff67734ec9ab213191386cdf09ddd051aebbChia-I Wu      table_set_func(tbl, slot, func);
181d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu   }
182d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu}
183d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu
184d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu/**
185d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu * Make a dispatch table current.
186d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu */
187d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wuvoid
188d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wumapi_table_make_current(const struct mapi_table *tbl)
189d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu{
190d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu   u_current_set(tbl);
191d4589d381697b4b3dd291a3c93a34370508ef1e8Chia-I Wu}
192