1 /************************************************************
2 Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
4 Permission to use, copy, modify, and distribute this
5 software and its documentation for any purpose and without
6 fee is hereby granted, provided that the above copyright
7 notice appear in all copies and that both that copyright
8 notice and this permission notice appear in supporting
9 documentation, and that the name of Silicon Graphics not be
10 used in advertising or publicity pertaining to distribution
11 of the software without specific prior written permission.
12 Silicon Graphics makes no representation about the suitability
13 of this software for any purpose. It is provided "as is"
14 without any express or implied warranty.
16 SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18 AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19 GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21 DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
23 THE USE OR PERFORMANCE OF THIS SOFTWARE.
25 ********************************************************/
28 #include <X11/XKBlib.h>
30 #define DEBUG_VAR debugFlags
33 #include <X11/extensions/XKM.h>
36 #ifndef DFLT_XKB_CONFIG_ROOT
37 #define DFLT_XKB_CONFIG_ROOT "/usr/lib/X11/xkb"
44 #define PATH_CHUNK 8 /* initial szPath */
46 static Bool noDefaultPath = False;
47 static int szPath; /* number of entries allocated for includePath */
48 static int nPathEntries; /* number of actual entries in includePath */
49 static char **includePath; /* Holds all directories we might be including data from */
52 * Extract the first token from an include statement.
53 * @param str_inout Input statement, modified in-place. Can be passed in
54 * repeatedly. If str_inout is NULL, the parsing has completed.
55 * @param file_rtrn Set to the include file to be used.
56 * @param map_rtrn Set to whatever comes after ), if any.
57 * @param nextop_rtrn Set to the next operation in the complete statement.
58 * @param extra_data Set to the string between ( and ), if any.
60 * @return True if parsing was succcessful, False for an illegal string.
62 * Example: "evdev+aliases(qwerty)"
63 * str_inout = aliases(qwerty)
69 * 2nd run with "aliases(qwerty)"
78 XkbParseIncludeMap(char **str_inout, char **file_rtrn, char **map_rtrn,
79 char *nextop_rtrn, char **extra_data)
81 char *tmp, *str, *next;
84 if ((*str == '+') || (*str == '|'))
86 *file_rtrn = *map_rtrn = NULL;
92 *file_rtrn = *map_rtrn = NULL;
93 *nextop_rtrn = str[1];
98 /* search for tokens inside the string */
99 next = strpbrk(str, "|+");
102 /* set nextop_rtrn to \0, next to next character */
103 *nextop_rtrn = *next;
111 /* search for :, store result in extra_data */
112 tmp = strchr(str, ':');
116 *extra_data = uStringDup(tmp);
122 tmp = strchr(str, '(');
125 *file_rtrn = uStringDup(str);
128 else if (str[0] == '(')
136 *file_rtrn = uStringDup(str);
138 tmp = strchr(str, ')');
139 if ((tmp == NULL) || (tmp[1] != '\0'))
146 *map_rtrn = uStringDup(str);
149 if (*nextop_rtrn == '\0')
151 else if ((*nextop_rtrn == '|') || (*nextop_rtrn == '+'))
159 * Init memory for include paths.
162 XkbInitIncludePath(void)
165 includePath = (char **) calloc(szPath, sizeof(char *));
166 if (includePath == NULL)
172 XkbAddDefaultDirectoriesToPath(void)
176 XkbAddDirectoryToPath(DFLT_XKB_CONFIG_ROOT);
180 * Remove all entries from the global includePath.
183 XkbClearIncludePath(void)
189 for (i = 0; i < nPathEntries; i++)
191 if (includePath[i] != NULL)
193 uFree(includePath[i]);
194 includePath[i] = NULL;
199 noDefaultPath = True;
204 * Add the given path to the global includePath variable.
205 * If dir is NULL, the includePath is emptied.
208 XkbAddDirectoryToPath(const char *dir)
211 if ((dir == NULL) || (dir[0] == '\0'))
213 XkbClearIncludePath();
217 dir = (char *) __XOS2RedirRoot(dir);
220 if (len + 2 >= PATH_MAX)
221 { /* allow for '/' and at least one character */
222 ERROR2("Path entry (%s) too long (maxiumum length is %d)\n",
226 if (nPathEntries >= szPath)
228 szPath += PATH_CHUNK;
229 includePath = (char **) realloc(includePath, szPath * sizeof(char *));
230 if (includePath == NULL)
232 WSGO("Allocation failed (includePath)\n");
236 includePath[nPathEntries] =
237 (char *) calloc(strlen(dir) + 1, sizeof(char));
238 if (includePath[nPathEntries] == NULL)
240 WSGO1("Allocation failed (includePath[%d])\n", nPathEntries);
243 strcpy(includePath[nPathEntries++], dir);
247 /***====================================================================***/
250 * Return the xkb directory based on the type.
251 * Do not free the memory returned by this function.
254 XkbDirectoryForInclude(unsigned type)
260 case XkmSemanticsFile:
261 strcpy(buf, "semantics");
264 strcpy(buf, "layout");
267 strcpy(buf, "keymap");
269 case XkmKeyNamesIndex:
270 strcpy(buf, "keycodes");
273 strcpy(buf, "types");
275 case XkmSymbolsIndex:
276 strcpy(buf, "symbols");
278 case XkmCompatMapIndex:
279 strcpy(buf, "compat");
281 case XkmGeometryFile:
282 case XkmGeometryIndex:
283 strcpy(buf, "geometry");
292 /***====================================================================***/
294 typedef struct _FileCacheEntry
300 struct _FileCacheEntry *next;
302 static FileCacheEntry *fileCache;
305 * Add the file with the given name to the internal cache to avoid opening and
306 * parsing the file multiple times. If a cache entry for the same name + type
307 * is already present, the entry is overwritten and the data belonging to the
308 * previous entry is returned.
310 * @parameter name The name of the file (e.g. evdev).
311 * @parameter type Type of the file (XkbTypesIdx, ... or XkbSemanticsFile, ...)
312 * @parameter path The full path to the file.
313 * @parameter data Already parsed data.
315 * @return The data from the overwritten file or NULL.
318 XkbAddFileToCache(char *name, unsigned type, char *path, void *data)
320 FileCacheEntry *entry;
322 for (entry = fileCache; entry != NULL; entry = entry->next)
324 if ((type == entry->type) && (uStringEqual(name, entry->name)))
326 void *old = entry->data;
327 WSGO2("Replacing file cache entry (%s/%d)\n", name, type);
333 entry = uTypedAlloc(FileCacheEntry);
340 entry->next = fileCache;
347 * Search for the given name + type in the cache.
349 * @parameter name The name of the file (e.g. evdev).
350 * @parameter type Type of the file (XkbTypesIdx, ... or XkbSemanticsFile, ...)
351 * @parameter pathRtrn Set to the full path of the given entry.
353 * @return the data from the cache entry or NULL if no matching entry was found.
356 XkbFindFileInCache(char *name, unsigned type, char **pathRtrn)
358 FileCacheEntry *entry;
360 for (entry = fileCache; entry != NULL; entry = entry->next)
362 if ((type == entry->type) && (uStringEqual(name, entry->name)))
364 *pathRtrn = entry->path;
371 /***====================================================================***/
374 * Search for the given file name in the include directories.
376 * @param type one of XkbTypesIndex, XkbCompatMapIndex, ..., or
377 * XkbSemanticsFile, XkmKeymapFile, ...
378 * @param pathReturn is set to the full path of the file if found.
380 * @return an FD to the file or NULL. If NULL is returned, the value of
381 * pathRtrn is undefined.
384 XkbFindFileInPath(char *name, unsigned type, char **pathRtrn)
388 int nameLen, typeLen, pathLen;
389 char buf[PATH_MAX], *typeDir;
391 typeDir = XkbDirectoryForInclude(type);
392 nameLen = strlen(name);
393 typeLen = strlen(typeDir);
394 for (i = 0; i < nPathEntries; i++)
396 pathLen = strlen(includePath[i]);
400 if ((nameLen + typeLen + pathLen + 2) >= PATH_MAX)
402 ERROR3("File name (%s/%s/%s) too long\n", includePath[i],
407 snprintf(buf, sizeof(buf), "%s/%s/%s", includePath[i], typeDir, name);
408 file = fopen(buf, "r");
413 if ((file != NULL) && (pathRtrn != NULL))
415 *pathRtrn = (char *) calloc(strlen(buf) + 1, sizeof(char));
416 if (*pathRtrn != NULL)
417 strcpy(*pathRtrn, buf);