Add penmount touchscreen configuration file
[profile/ivi/xorg-x11-server.git] / dix / registry.c
1 /************************************************************
2
3 Author: Eamon Walsh <ewalsh@tycho.nsa.gov>
4
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 this permission notice appear in supporting documentation.  This permission
8 notice shall be included in all copies or substantial portions of the
9 Software.
10
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
14 AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
15 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
16 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17
18 ********************************************************/
19
20 #ifdef HAVE_DIX_CONFIG_H
21 #include <dix-config.h>
22 #endif
23
24 #ifdef XREGISTRY
25
26 #include <stdlib.h>
27 #include <string.h>
28 #include <X11/X.h>
29 #include <X11/Xproto.h>
30 #include "resource.h"
31 #include "registry.h"
32
33 #define BASE_SIZE 16
34 #define CORE "X11"
35 #define FILENAME SERVER_MISC_CONFIG_PATH "/protocol.txt"
36
37 #define PROT_COMMENT '#'
38 #define PROT_REQUEST 'R'
39 #define PROT_EVENT 'V'
40 #define PROT_ERROR 'E'
41
42 static FILE *fh;
43
44 static char ***requests, **events, **errors, **resources;
45 static unsigned nmajor, *nminor, nevent, nerror, nresource;
46
47 /*
48  * File parsing routines
49  */
50 static int double_size(void *p, unsigned n, unsigned size)
51 {
52     char **ptr = (char **)p;
53     unsigned s, f;
54
55     if (n) {
56         s = n * size;
57         n *= 2 * size;
58         f = n;
59     } else {
60         s = 0;
61         n = f = BASE_SIZE * size;
62     }
63
64     *ptr = realloc(*ptr, n);
65     if (!*ptr) {
66         dixResetRegistry();
67         return FALSE;
68     }
69     memset(*ptr + s, 0, f - s);
70     return TRUE;
71 }       
72
73 static void
74 RegisterRequestName(unsigned major, unsigned minor, char *name)
75 {
76     while (major >= nmajor) {
77         if (!double_size(&requests, nmajor, sizeof(char **)))
78             return;
79         if (!double_size(&nminor, nmajor, sizeof(unsigned)))
80             return;
81         nmajor = nmajor ? nmajor * 2 : BASE_SIZE;
82     }
83     while (minor >= nminor[major]) {
84         if (!double_size(requests+major, nminor[major], sizeof(char *)))
85             return;
86         nminor[major] = nminor[major] ? nminor[major] * 2 : BASE_SIZE;
87     }
88
89     free(requests[major][minor]);
90     requests[major][minor] = name;
91 }
92
93 static void
94 RegisterEventName(unsigned event, char *name) {
95     while (event >= nevent) {
96         if (!double_size(&events, nevent, sizeof(char *)))
97             return;
98         nevent = nevent ? nevent * 2 : BASE_SIZE;
99     }
100
101     free(events[event]);
102     events[event] = name;
103 }
104
105 static void
106 RegisterErrorName(unsigned error, char *name) {
107     while (error >= nerror) {
108         if (!double_size(&errors, nerror, sizeof(char *)))
109             return;
110         nerror = nerror ? nerror * 2 : BASE_SIZE;
111     }
112
113     free(errors[error]);
114     errors[error] = name;
115 }
116
117 void
118 RegisterExtensionNames(ExtensionEntry *extEntry)
119 {
120     char buf[256], *lineobj, *ptr;
121     unsigned offset;
122
123     if (fh == NULL)
124         return;
125
126     rewind(fh);
127
128     while (fgets(buf, sizeof(buf), fh)) {
129         lineobj = NULL;
130         ptr = strchr(buf, '\n');
131         if (ptr)
132             *ptr = 0;
133
134         /* Check for comments or empty lines */
135         switch (buf[0]) {
136         case PROT_REQUEST:
137         case PROT_EVENT:
138         case PROT_ERROR:
139             break;
140         case PROT_COMMENT:
141         case '\0':
142             continue;
143         default:
144             goto invalid;
145         }
146
147         /* Check for space character in the fifth position */
148         ptr = strchr(buf, ' ');
149         if (!ptr || ptr != buf + 4)
150             goto invalid;
151
152         /* Duplicate the string after the space */
153         lineobj = strdup(ptr + 1);
154         if (!lineobj)
155             continue;
156
157         /* Check for a colon somewhere on the line */
158         ptr = strchr(buf, ':');
159         if (!ptr)
160             goto invalid;
161
162         /* Compare the part before colon with the target extension name */
163         *ptr = 0;
164         if (strcmp(buf + 5, extEntry->name))
165             goto skip;
166
167         /* Get the opcode for the request, event, or error */
168         offset = strtol(buf + 1, &ptr, 10);
169         if (offset == 0 && ptr == buf + 1)
170             goto invalid;
171
172         /* Save the strdup result in the registry */
173         switch(buf[0]) {
174         case PROT_REQUEST:
175             if (extEntry->base)
176                 RegisterRequestName(extEntry->base, offset, lineobj);
177             else
178                 RegisterRequestName(offset, 0, lineobj);
179             continue;
180         case PROT_EVENT:
181             RegisterEventName(extEntry->eventBase + offset, lineobj);
182             continue;
183         case PROT_ERROR:
184             RegisterErrorName(extEntry->errorBase + offset, lineobj);
185             continue;
186         }
187
188     invalid:
189         LogMessage(X_WARNING, "Invalid line in " FILENAME ", skipping\n");
190     skip:
191         free(lineobj);
192     }
193 }
194
195 /*
196  * Registration functions
197  */
198
199 void
200 RegisterResourceName(RESTYPE resource, char *name)
201 {
202     resource &= TypeMask;
203
204     while (resource >= nresource) {
205         if (!double_size(&resources, nresource, sizeof(char *)))
206             return;
207         nresource = nresource ? nresource * 2 : BASE_SIZE;
208     }
209
210     resources[resource] = name;
211 }
212
213 /*
214  * Lookup functions
215  */
216
217 const char *
218 LookupRequestName(int major, int minor)
219 {
220     if (major >= nmajor)
221         return XREGISTRY_UNKNOWN;
222     if (minor >= nminor[major])
223         return XREGISTRY_UNKNOWN;
224
225     return requests[major][minor] ? requests[major][minor] : XREGISTRY_UNKNOWN;
226 }
227
228 const char *
229 LookupMajorName(int major)
230 {
231     if (major < 128) {
232         const char *retval;
233
234         if (major >= nmajor)
235             return XREGISTRY_UNKNOWN;
236         if (0 >= nminor[major])
237             return XREGISTRY_UNKNOWN;
238
239         retval = requests[major][0];
240         return retval ? retval + sizeof(CORE) : XREGISTRY_UNKNOWN;
241     } else {
242         ExtensionEntry *extEntry = GetExtensionEntry(major);
243         return extEntry ? extEntry->name : XREGISTRY_UNKNOWN;
244     }
245 }
246
247 const char *
248 LookupEventName(int event)
249 {
250     event &= 127;
251     if (event >= nevent)
252         return XREGISTRY_UNKNOWN;
253
254     return events[event] ? events[event] : XREGISTRY_UNKNOWN;
255 }
256
257 const char *
258 LookupErrorName(int error)
259 {
260     if (error >= nerror)
261         return XREGISTRY_UNKNOWN;
262
263     return errors[error] ? errors[error] : XREGISTRY_UNKNOWN;
264 }
265
266 const char *
267 LookupResourceName(RESTYPE resource)
268 {
269     resource &= TypeMask;
270     if (resource >= nresource)
271         return XREGISTRY_UNKNOWN;
272
273     return resources[resource] ? resources[resource] : XREGISTRY_UNKNOWN;
274 }
275
276 /*
277  * Setup and teardown
278  */
279 void
280 dixResetRegistry(void)
281 {
282     ExtensionEntry extEntry;
283
284     /* Free all memory */
285     while (nmajor--) {
286         while (nminor[nmajor])
287             free(requests[nmajor][--nminor[nmajor]]);
288         free(requests[nmajor]);
289     }
290     free(requests);
291     free(nminor);
292
293     while (nevent--)
294         free(events[nevent]);
295     free(events);
296
297     while (nerror--)
298         free(errors[nerror]);
299     free(errors);
300
301     free(resources);
302
303     requests = NULL;
304     nminor = NULL;
305     events = NULL;
306     errors = NULL;
307     resources = NULL;
308
309     nmajor = nevent = nerror = nresource = 0;
310
311     /* Open the protocol file */
312     if (fh)
313         fclose(fh);
314     fh = fopen(FILENAME, "r");
315     if (!fh)
316         LogMessage(X_WARNING, "Failed to open protocol names file " FILENAME "\n");
317
318     /* Add built-in resources */
319     RegisterResourceName(RT_NONE, "NONE");
320     RegisterResourceName(RT_WINDOW, "WINDOW");
321     RegisterResourceName(RT_PIXMAP, "PIXMAP");
322     RegisterResourceName(RT_GC, "GC");
323     RegisterResourceName(RT_FONT, "FONT");
324     RegisterResourceName(RT_CURSOR, "CURSOR");
325     RegisterResourceName(RT_COLORMAP, "COLORMAP");
326     RegisterResourceName(RT_CMAPENTRY, "COLORMAP ENTRY");
327     RegisterResourceName(RT_OTHERCLIENT, "OTHER CLIENT");
328     RegisterResourceName(RT_PASSIVEGRAB, "PASSIVE GRAB");
329
330     /* Add the core protocol */
331     memset(&extEntry, 0, sizeof(extEntry));
332     extEntry.name = CORE;
333     RegisterExtensionNames(&extEntry);
334 }
335
336 #endif /* XREGISTRY */