1 /************************************************************
2 Copyright 1996 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 ********************************************************/
26 /***********************************************************
28 Copyright 1988, 1998 The Open Group
30 Permission to use, copy, modify, distribute, and sell this software and its
31 documentation for any purpose is hereby granted without fee, provided that
32 the above copyright notice appear in all copies and that both that
33 copyright notice and this permission notice appear in supporting
36 The above copyright notice and this permission notice shall be included in
37 all copies or substantial portions of the Software.
39 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
40 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
41 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
42 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
43 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
44 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
46 Except as contained in this notice, the name of The Open Group shall not be
47 used in advertising or otherwise to promote the sale, use or other dealings
48 in this Software without prior written authorization from The Open Group.
51 Copyright 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
55 Permission to use, copy, modify, and distribute this software and its
56 documentation for any purpose and without fee is hereby granted,
57 provided that the above copyright notice appear in all copies and that
58 both that copyright notice and this permission notice appear in
59 supporting documentation, and that the name of Digital not be
60 used in advertising or publicity pertaining to distribution of the
61 software without specific, written prior permission.
63 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
64 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
65 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
66 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
67 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
68 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
71 ******************************************************************/
75 #include <sys/types.h>
77 #include <X11/keysym.h>
83 #define DEBUG_VAR listingDebug
90 # define _POSIX_SOURCE
99 #include <sys/param.h>
103 #define PATH_MAX MAXPATHLEN
105 #define PATH_MAX 1024
111 # include <windows.h>
112 # define FileName(file) file.cFileName
117 # define FileName(file) file->d_name
122 #include "parseutils.h"
125 #include <X11/extensions/XKBgeomcommon.h>
127 #ifndef DFLT_XKB_CONFIG_ROOT
128 #define DFLT_XKB_CONFIG_ROOT "/usr/share/X11/xkb"
131 unsigned int listingDebug;
133 typedef struct _CompPair {
137 XkbComponentNamePtr comp;
140 /***====================================================================***/
143 AddComponent(CompPair *cp, char *fileName, XkbFile *map, unsigned dirsToStrip)
145 if (!cp || !fileName || !map)
148 if (cp->num >= cp->sz) {
149 int orig_sz = cp->sz;
150 XkbComponentNamePtr orig_comp = cp->comp;
157 cp->comp = _XkbRealloc(cp->comp,
158 cp->sz * sizeof(XkbComponentNameRec));
160 ERROR("Failed reallocating component name list\n");
162 cp->comp = orig_comp;
167 /* Strip off leading directories of component */
168 if (dirsToStrip > 0) {
172 for (i = 0, tmp = last = fileName; (i <= dirsToStrip) && tmp; i++) {
174 tmp = strchr(tmp, '/');
179 fileName = (tmp ? tmp : last);
183 size_t len = strlen(fileName) + strlen(map->name) + 3;
185 cp->comp[cp->num].name = _XkbAlloc(len * sizeof(char));
186 if (!cp->comp[cp->num].name) {
187 ERROR("Could not allocate space for component name\n");
190 sprintf(cp->comp[cp->num].name, "%s(%s)", fileName, map->name);
193 cp->comp[cp->num].name = strdup(fileName);
194 if (!cp->comp[cp->num].name) {
195 ERROR("Could not duplicate component name\n");
200 cp->comp[cp->num].flags = map->flags;
207 MapMatches(char *mapToConsider, char *ptrn)
209 return ptrn ? XkbcNameMatchesPattern(mapToConsider, ptrn) : True;
213 ParseComponents(CompPair *cp, char *path, char *map, int *max, unsigned strip)
217 XkbFile *rtrn, *mapToUse;
218 unsigned oldWarningLevel;
220 if (!cp || !path || !max)
224 if (warningLevel > 9)
225 fprintf(stderr, "should list:\n");
228 oldWarningLevel = warningLevel;
232 if (oldWarningLevel > 9)
233 fprintf(stderr, "%s(%s)\n", path ? path : "*", map ? map : "*");
236 inputFile = fopen(path, "r");
238 if (oldWarningLevel > 5)
239 WARN("Couldn't open \"%s\"\n", path);
243 setScanState(path, 1);
244 if (!XKBParseFile(inputFile, &rtrn) || !rtrn) {
245 if (oldWarningLevel > 5)
246 WARN("Couldn't parse file \"%s\"\n", path);
252 for (; mapToUse; mapToUse = (XkbFile *)mapToUse->common.next) {
253 if (!MapMatches(mapToUse->name, map))
259 if (AddComponent(cp, path, mapToUse, strip))
263 warningLevel = oldWarningLevel;
271 /***====================================================================***/
274 AddDirectory(CompPair *cp, char *head, char *ptrn, char *rest, char *map,
275 int *max, unsigned strip)
279 WIN32_FIND_DATA file;
289 ERROR("Must specify directory name\n");
293 strncpy(path, head, sizeof(path));
294 path[PATH_MAX - 1] = '\0';
295 baselen = strlen(path);
300 if (!rest && ptrn && !strchr(ptrn, '/')) {
302 map = strchr(ptrn, '(');
304 else if (!rest && !ptrn && !strchr(head, '/')) {
306 map = strchr(head, '(');
310 tmp = strchr(tmp, ')');
311 if (!tmp || tmp[1] != '\0') {
312 ERROR("File and map must have the format file(map)\n");
322 if ((dirh = FindFirstFile("*.*", &file)) == INVALID_HANDLE_VALUE)
325 if (!(dirp = opendir(head))) {
326 ERROR("Could not open directory \"%s\"\n", head ? head : ".");
334 while ((file = readdir(dirp)) != NULL)
340 filename = FileName(file);
341 if (!filename || filename[0] == '.')
343 if (ptrn && (!XkbcNameMatchesPattern(filename, ptrn)))
346 snprintf(&path[baselen], sizeof(path) - baselen, "/%s", filename);
347 if (stat(path, &sbuf) < 0) {
348 ERROR("Could not read file \"%s\"\n", path);
352 if ((rest && !S_ISDIR(sbuf.st_mode)) ||
353 (map && S_ISDIR(sbuf.st_mode)))
356 if (S_ISDIR(sbuf.st_mode))
357 nMatch += AddDirectory(cp, path, rest, NULL, map, max, strip);
359 nMatch += ParseComponents(cp, path, map, max, strip);
362 while (FindNextFile(dirh, &file));
367 /***====================================================================***/
370 GenerateComponent(XkbComponentListPtr complist, unsigned type, char *head_in,
371 char *base, int *max)
373 char *str, *head, *ptrn = NULL, *rest = NULL;
377 unsigned dirsToStrip;
380 if (!complist || !head_in || !max)
384 for (str = head_in; (*str != '\0') && (*str != '?') && (*str != '*');
387 if ((str != head_in) && (*str == '/'))
396 /* no slash before the first wildcard */
401 /* slash followed by wildcard */
408 rest = strchr(ptrn, '/');
415 if ((rest && ptrn && (strchr(ptrn, '(') || strchr(ptrn, ')'))) ||
416 (head && (strchr(head, '(') || strchr(head, ')')))) {
417 ERROR("Files/maps to list must have the form file(map)\n");
421 /* Prepend XKB directory */
422 snprintf(buf, sizeof(buf), "%s%s%s", base ? base : "", base ? "/" : "",
423 XkbDirectoryForInclude(type));
426 /* Figure out directory stripping */
429 while ((str = strchr(str, '/')) != NULL) {
435 snprintf(&buf[len], PATH_MAX - len, "/%s", head);
438 memset(&cp, 0, sizeof(CompPair));
439 extra = AddDirectory(&cp, head, ptrn, rest, NULL, max, dirsToStrip);
441 /* Trim excess component slots */
442 if (cp.sz > 0 && cp.sz > cp.num) {
443 if (_XkbRealloc(cp.comp, cp.num * sizeof(XkbComponentNameRec)))
446 WARN("Could not reallocate component name list\n");
451 complist->num_keymaps = cp.num;
452 complist->keymaps = cp.comp;
454 case XkmKeyNamesIndex:
455 complist->num_keycodes = cp.num;
456 complist->keycodes = cp.comp;
459 complist->num_types = cp.num;
460 complist->types = cp.comp;
462 case XkmCompatMapIndex:
463 complist->num_compat = cp.num;
464 complist->compat = cp.comp;
466 case XkmSymbolsIndex:
467 complist->num_symbols = cp.num;
468 complist->symbols = cp.comp;
470 case XkmGeometryIndex:
471 complist->num_geometry = cp.num;
472 complist->geometry = cp.comp;
479 /***====================================================================***/
482 XkbcListComponents(unsigned int deviceSpec, XkbComponentNamesPtr ptrns,
485 XkbComponentListPtr complist = NULL;
488 complist = _XkbTypedCalloc(1, XkbComponentListRec);
490 ERROR("could not allocate space for listing\n");
494 if (!maxMatch || *maxMatch <= 0)
497 if (ptrns->keymap && *ptrns->keymap != '\0')
498 extra += GenerateComponent(complist, XkmKeymapFile, ptrns->keycodes,
499 DFLT_XKB_CONFIG_ROOT, maxMatch);
501 if (ptrns->keycodes && *ptrns->keycodes != '\0')
502 extra += GenerateComponent(complist, XkmKeyNamesIndex, ptrns->keycodes,
503 DFLT_XKB_CONFIG_ROOT, maxMatch);
505 if (ptrns->types && *ptrns->types != '\0')
506 extra += GenerateComponent(complist, XkmTypesIndex, ptrns->types,
507 DFLT_XKB_CONFIG_ROOT, maxMatch);
509 if (ptrns->compat && *ptrns->compat != '\0')
510 extra += GenerateComponent(complist, XkmCompatMapIndex, ptrns->compat,
511 DFLT_XKB_CONFIG_ROOT, maxMatch);
513 if (ptrns->symbols && *ptrns->symbols != '\0')
514 extra += GenerateComponent(complist, XkmSymbolsIndex, ptrns->symbols,
515 DFLT_XKB_CONFIG_ROOT, maxMatch);
517 if (ptrns->geometry && *ptrns->geometry != '\0')
518 extra += GenerateComponent(complist, XkmGeometryIndex, ptrns->geometry,
519 DFLT_XKB_CONFIG_ROOT, maxMatch);