123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418 |
- /************************************************************
- Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
- Permission to use, copy, modify, and distribute this
- software and its documentation for any purpose and without
- fee is hereby granted, provided that the above copyright
- notice appear in all copies and that both that copyright
- notice and this permission notice appear in supporting
- documentation, and that the name of Silicon Graphics not be
- used in advertising or publicity pertaining to distribution
- of the software without specific prior written permission.
- Silicon Graphics makes no representation about the suitability
- of this software for any purpose. It is provided "as is"
- without any express or implied warranty.
-
- SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
- SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
- GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
- DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
- OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
- THE USE OR PERFORMANCE OF THIS SOFTWARE.
- ********************************************************/
- #include <X11/Xlib.h>
- #include <X11/XKBlib.h>
- #define DEBUG_VAR debugFlags
- #include "utils.h"
- #include <stdlib.h>
- #include <X11/extensions/XKM.h>
- #include "xkbpath.h"
- #ifndef DFLT_XKB_CONFIG_ROOT
- #define DFLT_XKB_CONFIG_ROOT "/usr/lib/X11/xkb"
- #endif
- #ifndef PATH_MAX
- #define PATH_MAX 1024
- #endif
- #define PATH_CHUNK 8 /* initial szPath */
- static Bool noDefaultPath = False;
- static int szPath; /* number of entries allocated for includePath */
- static int nPathEntries; /* number of actual entries in includePath */
- static char **includePath; /* Holds all directories we might be including data from */
- /**
- * Extract the first token from an include statement.
- * @param str_inout Input statement, modified in-place. Can be passed in
- * repeatedly. If str_inout is NULL, the parsing has completed.
- * @param file_rtrn Set to the include file to be used.
- * @param map_rtrn Set to whatever comes after ), if any.
- * @param nextop_rtrn Set to the next operation in the complete statement.
- * @param extra_data Set to the string between ( and ), if any.
- *
- * @return True if parsing was succcessful, False for an illegal string.
- *
- * Example: "evdev+aliases(qwerty)"
- * str_inout = aliases(qwerty)
- * nextop_retrn = +
- * extra_data = NULL
- * file_rtrn = evdev
- * map_rtrn = NULL
- *
- * 2nd run with "aliases(qwerty)"
- * str_inout = NULL
- * file_rtrn = aliases
- * map_rtrn = qwerty
- * extra_data = NULL
- * nextop_retrn = ""
- *
- */
- Bool
- XkbParseIncludeMap(char **str_inout, char **file_rtrn, char **map_rtrn,
- char *nextop_rtrn, char **extra_data)
- {
- char *tmp, *str, *next;
- str = *str_inout;
- if ((*str == '+') || (*str == '|'))
- {
- *file_rtrn = *map_rtrn = NULL;
- *nextop_rtrn = *str;
- next = str + 1;
- }
- else if (*str == '%')
- {
- *file_rtrn = *map_rtrn = NULL;
- *nextop_rtrn = str[1];
- next = str + 2;
- }
- else
- {
- /* search for tokens inside the string */
- next = strpbrk(str, "|+");
- if (next)
- {
- /* set nextop_rtrn to \0, next to next character */
- *nextop_rtrn = *next;
- *next++ = '\0';
- }
- else
- {
- *nextop_rtrn = '\0';
- next = NULL;
- }
- /* search for :, store result in extra_data */
- tmp = strchr(str, ':');
- if (tmp != NULL)
- {
- *tmp++ = '\0';
- *extra_data = uStringDup(tmp);
- }
- else
- {
- *extra_data = NULL;
- }
- tmp = strchr(str, '(');
- if (tmp == NULL)
- {
- *file_rtrn = uStringDup(str);
- *map_rtrn = NULL;
- }
- else if (str[0] == '(')
- {
- uFree(*extra_data);
- return False;
- }
- else
- {
- *tmp++ = '\0';
- *file_rtrn = uStringDup(str);
- str = tmp;
- tmp = strchr(str, ')');
- if ((tmp == NULL) || (tmp[1] != '\0'))
- {
- uFree(*file_rtrn);
- uFree(*extra_data);
- return False;
- }
- *tmp++ = '\0';
- *map_rtrn = uStringDup(str);
- }
- }
- if (*nextop_rtrn == '\0')
- *str_inout = NULL;
- else if ((*nextop_rtrn == '|') || (*nextop_rtrn == '+'))
- *str_inout = next;
- else
- return False;
- return True;
- }
- /**
- * Init memory for include paths.
- */
- Bool
- XkbInitIncludePath(void)
- {
- szPath = PATH_CHUNK;
- includePath = (char **) calloc(szPath, sizeof(char *));
- if (includePath == NULL)
- return False;
- return True;
- }
- void
- XkbAddDefaultDirectoriesToPath(void)
- {
- if (noDefaultPath)
- return;
- XkbAddDirectoryToPath(DFLT_XKB_CONFIG_ROOT);
- }
- /**
- * Remove all entries from the global includePath.
- */
- void
- XkbClearIncludePath(void)
- {
- register int i;
- if (szPath > 0)
- {
- for (i = 0; i < nPathEntries; i++)
- {
- if (includePath[i] != NULL)
- {
- uFree(includePath[i]);
- includePath[i] = NULL;
- }
- }
- nPathEntries = 0;
- }
- noDefaultPath = True;
- return;
- }
- /**
- * Add the given path to the global includePath variable.
- * If dir is NULL, the includePath is emptied.
- */
- Bool
- XkbAddDirectoryToPath(const char *dir)
- {
- int len;
- if ((dir == NULL) || (dir[0] == '\0'))
- {
- XkbClearIncludePath();
- return True;
- }
- len = strlen(dir);
- if (len + 2 >= PATH_MAX)
- { /* allow for '/' and at least one character */
- ERROR2("Path entry (%s) too long (maxiumum length is %d)\n",
- dir, PATH_MAX - 3);
- return False;
- }
- if (nPathEntries >= szPath)
- {
- szPath += PATH_CHUNK;
- includePath = (char **) realloc(includePath, szPath * sizeof(char *));
- if (includePath == NULL)
- {
- WSGO("Allocation failed (includePath)\n");
- return False;
- }
- }
- includePath[nPathEntries] =
- (char *) calloc(strlen(dir) + 1, sizeof(char));
- if (includePath[nPathEntries] == NULL)
- {
- WSGO1("Allocation failed (includePath[%d])\n", nPathEntries);
- return False;
- }
- strcpy(includePath[nPathEntries++], dir);
- return True;
- }
- /***====================================================================***/
- /**
- * Return the xkb directory based on the type.
- * Do not free the memory returned by this function.
- */
- char *
- XkbDirectoryForInclude(unsigned type)
- {
- static char buf[32];
- switch (type)
- {
- case XkmSemanticsFile:
- strcpy(buf, "semantics");
- break;
- case XkmLayoutFile:
- strcpy(buf, "layout");
- break;
- case XkmKeymapFile:
- strcpy(buf, "keymap");
- break;
- case XkmKeyNamesIndex:
- strcpy(buf, "keycodes");
- break;
- case XkmTypesIndex:
- strcpy(buf, "types");
- break;
- case XkmSymbolsIndex:
- strcpy(buf, "symbols");
- break;
- case XkmCompatMapIndex:
- strcpy(buf, "compat");
- break;
- case XkmGeometryFile:
- case XkmGeometryIndex:
- strcpy(buf, "geometry");
- break;
- default:
- strcpy(buf, "");
- break;
- }
- return buf;
- }
- /***====================================================================***/
- typedef struct _FileCacheEntry
- {
- char *name;
- unsigned type;
- char *path;
- void *data;
- struct _FileCacheEntry *next;
- } FileCacheEntry;
- static FileCacheEntry *fileCache;
- /**
- * Add the file with the given name to the internal cache to avoid opening and
- * parsing the file multiple times. If a cache entry for the same name + type
- * is already present, the entry is overwritten and the data belonging to the
- * previous entry is returned.
- *
- * @parameter name The name of the file (e.g. evdev).
- * @parameter type Type of the file (XkbTypesIdx, ... or XkbSemanticsFile, ...)
- * @parameter path The full path to the file.
- * @parameter data Already parsed data.
- *
- * @return The data from the overwritten file or NULL.
- */
- void *
- XkbAddFileToCache(char *name, unsigned type, char *path, void *data)
- {
- FileCacheEntry *entry;
- for (entry = fileCache; entry != NULL; entry = entry->next)
- {
- if ((type == entry->type) && (uStringEqual(name, entry->name)))
- {
- void *old = entry->data;
- WSGO2("Replacing file cache entry (%s/%d)\n", name, type);
- entry->path = path;
- entry->data = data;
- return old;
- }
- }
- entry = uTypedAlloc(FileCacheEntry);
- if (entry != NULL)
- {
- entry->name = name;
- entry->type = type;
- entry->path = path;
- entry->data = data;
- entry->next = fileCache;
- fileCache = entry;
- }
- return NULL;
- }
- /**
- * Search for the given name + type in the cache.
- *
- * @parameter name The name of the file (e.g. evdev).
- * @parameter type Type of the file (XkbTypesIdx, ... or XkbSemanticsFile, ...)
- * @parameter pathRtrn Set to the full path of the given entry.
- *
- * @return the data from the cache entry or NULL if no matching entry was found.
- */
- void *
- XkbFindFileInCache(char *name, unsigned type, char **pathRtrn)
- {
- FileCacheEntry *entry;
- for (entry = fileCache; entry != NULL; entry = entry->next)
- {
- if ((type == entry->type) && (uStringEqual(name, entry->name)))
- {
- *pathRtrn = entry->path;
- return entry->data;
- }
- }
- return NULL;
- }
- /***====================================================================***/
- /**
- * Search for the given file name in the include directories.
- *
- * @param type one of XkbTypesIndex, XkbCompatMapIndex, ..., or
- * XkbSemanticsFile, XkmKeymapFile, ...
- * @param pathReturn is set to the full path of the file if found.
- *
- * @return an FD to the file or NULL. If NULL is returned, the value of
- * pathRtrn is undefined.
- */
- FILE *
- XkbFindFileInPath(char *name, unsigned type, char **pathRtrn)
- {
- register int i;
- FILE *file = NULL;
- int nameLen, typeLen, pathLen;
- char buf[PATH_MAX], *typeDir;
- typeDir = XkbDirectoryForInclude(type);
- nameLen = strlen(name);
- typeLen = strlen(typeDir);
- for (i = 0; i < nPathEntries; i++)
- {
- pathLen = strlen(includePath[i]);
- if (typeLen < 1)
- continue;
- if ((nameLen + typeLen + pathLen + 2) >= PATH_MAX)
- {
- ERROR3("File name (%s/%s/%s) too long\n", includePath[i],
- typeDir, name);
- ACTION("Ignored\n");
- continue;
- }
- snprintf(buf, sizeof(buf), "%s/%s/%s", includePath[i], typeDir, name);
- file = fopen(buf, "r");
- if (file != NULL)
- break;
- }
- if ((file != NULL) && (pathRtrn != NULL))
- {
- *pathRtrn = (char *) calloc(strlen(buf) + 1, sizeof(char));
- if (*pathRtrn != NULL)
- strcpy(*pathRtrn, buf);
- }
- return file;
- }
|