From 18b43f8dfe641bf951b92d074b1cc6cee71d9869 Mon Sep 17 00:00:00 2001 From: Dan Nicholson Date: Sun, 19 Apr 2009 16:30:36 -0700 Subject: [PATCH] Rewrite listing code to generate XkbComponentListPtr In xkbcomp, the listing code printed out the xkb files to stdout and the caller would parse the output. Here, we can just generate a XkbComponentListPtr and pass it back. This should be a series of smaller commits, but there was no clean way to do it since it's basically a complete rewrite except for the core map matching logic. A lot of code used for special printing modes in xkbcomp has been shedded. Callers can massage the output as they please. --- include/X11/extensions/XKBcommon.h | 4 + src/xkbcomp/listing.c | 490 +++++++++++++++++++++++++------------ src/xkbcomp/xkbcomp.h | 9 - 3 files changed, 341 insertions(+), 162 deletions(-) diff --git a/include/X11/extensions/XKBcommon.h b/include/X11/extensions/XKBcommon.h index 1a53658..9e8fbf6 100644 --- a/include/X11/extensions/XKBcommon.h +++ b/include/X11/extensions/XKBcommon.h @@ -138,6 +138,10 @@ XkbcCompileKeymapFromComponents(const XkbComponentNamesPtr ktcsg); extern XkbcDescPtr XkbcCompileKeymapFromFile(FILE *inputFile, const char *mapName); +extern XkbComponentListPtr +XkbcListComponents(unsigned int deviceSpec, XkbComponentNamesPtr ptrns, + int *maxMatch); + _XFUNCPROTOEND #endif /* _XKBCOMMON_H_ */ diff --git a/src/xkbcomp/listing.c b/src/xkbcomp/listing.c index 48d5459..78f5af6 100644 --- a/src/xkbcomp/listing.c +++ b/src/xkbcomp/listing.c @@ -6,19 +6,19 @@ 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 + 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 + 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 + + 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 + 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. @@ -52,13 +52,13 @@ Copyright 1988 by Digital Equipment Corporation, Maynard, Massachusetts. All Rights Reserved -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, +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 +both that copyright notice and this permission notice appear in supporting documentation, and that the name of Digital not be used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. +software without specific, written prior permission. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL @@ -124,111 +124,167 @@ SOFTWARE. #include "tokens.h" #include -#define lowbit(x) ((x) & (-(x))) +#ifndef DFLT_XKB_CONFIG_ROOT +#define DFLT_XKB_CONFIG_ROOT "/usr/share/X11/xkb" +#endif unsigned int listingDebug; -static int szListing = 0; -static int nListed = 0; -static int nFilesListed = 0; - -typedef struct _Listing -{ +typedef struct _Listing { char *file; char *map; } Listing; -static Listing *list = NULL; +typedef struct _ListHead { + int szListing; + int nListed; + + Listing *list; +} ListHead; -static unsigned verboseLevel; -static unsigned dirsToStrip; +typedef struct _CompPair { + int num; + int sz; + + XkbComponentNamePtr comp; +} CompPair; /***====================================================================***/ -static int -AddListing(char *file, char *map) +static void +ClearList(ListHead *lh) { - if (nListed >= szListing) - { - if (szListing < 1) - szListing = 10; + int i; + + if (!lh) + return; + + for (i = 0; i < lh->nListed; i++) { + _XkbFree(lh->list[i].file); + lh->list[i].file = NULL; + _XkbFree(lh->list[i].map); + lh->list[i].map = NULL; + } + + lh->nListed = 0; +} + +static void +FreeList(ListHead *lh) +{ + int i; + + if (!lh) + return; + + for (i = 0; i < lh->nListed; i++) { + _XkbFree(lh->list[i].file); + _XkbFree(lh->list[i].map); + } + + _XkbFree(lh->list); + + memset(lh, 0, sizeof(ListHead)); +} + +static Bool +AddListing(ListHead *lh, char *file, char *map) +{ + if (lh->nListed >= lh->szListing) { + int orig_sz = lh->szListing; + Listing *orig_list = lh->list; + + if (lh->szListing < 1) + lh->szListing = 10; else - szListing *= 2; - list = uTypedRealloc(list, szListing, Listing); - if (!list) - { - WSGO("Couldn't allocate list of files and maps\n"); - ACTION("Exiting\n"); - exit(1); + lh->szListing *= 2; + + lh->list = _XkbRealloc(lh->list, lh->szListing * sizeof(Listing)); + if (!lh->list) { + ERROR("Couldn't allocate list of files and maps\n"); + lh->szListing = orig_sz; + lh->list = orig_list; + return False; } } - list[nListed].file = file; - list[nListed].map = map; - nListed++; - if (file != NULL) - nFilesListed++; - return 1; + lh->list[lh->nListed].file = file; + lh->list[lh->nListed].map = map; + lh->nListed++; + + return True; } /***====================================================================***/ -static void -ListFile(FILE * outFile, char *fileName, XkbFile * map) +static Bool +AddComponent(CompPair *cp, char *fileName, XkbFile *map, unsigned dirsToStrip) { - register unsigned flags; - char *mapName; + if (!cp || !fileName || !map) + return False; - flags = map->flags; - if ((flags & XkbLC_Hidden) && (!(verboseLevel & WantHiddenMaps))) - return; - if ((flags & XkbLC_Partial) && (!(verboseLevel & WantPartialMaps))) - return; - if (verboseLevel & WantLongListing) - { - fprintf(outFile, (flags & XkbLC_Hidden) ? "h" : "-"); - fprintf(outFile, (flags & XkbLC_Default) ? "d" : "-"); - fprintf(outFile, (flags & XkbLC_Partial) ? "p" : "-"); - fprintf(outFile, "----- "); - if (map->type == XkmSymbolsIndex) - { - fprintf(outFile, (flags & XkbLC_AlphanumericKeys) ? "a" : "-"); - fprintf(outFile, (flags & XkbLC_ModifierKeys) ? "m" : "-"); - fprintf(outFile, (flags & XkbLC_KeypadKeys) ? "k" : "-"); - fprintf(outFile, (flags & XkbLC_FunctionKeys) ? "f" : "-"); - fprintf(outFile, (flags & XkbLC_AlternateGroup) ? "g" : "-"); - fprintf(outFile, "--- "); - } + if (cp->num >= cp->sz) { + int orig_sz = cp->sz; + XkbComponentNamePtr orig_comp = cp->comp; + + if (cp->sz < 1) + cp->sz = 10; else - fprintf(outFile, "-------- "); + cp->sz *= 2; + + cp->comp = _XkbRealloc(cp->comp, + cp->sz * sizeof(XkbComponentNameRec)); + if (!cp->comp) { + ERROR("Failed reallocating component name list\n"); + cp->sz = orig_sz; + cp->comp = orig_comp; + return False; + } } - mapName = map->name; - if ((!(verboseLevel & WantFullNames)) && ((flags & XkbLC_Default) != 0)) - mapName = NULL; - if (dirsToStrip > 0) - { + + /* Strip off leading directories of component */ + if (dirsToStrip > 0) { char *tmp, *last; int i; - for (i = 0, tmp = last = fileName; (i < dirsToStrip) && tmp; i++) - { + + for (i = 0, tmp = last = fileName; (i <= dirsToStrip) && tmp; i++) { last = tmp; tmp = strchr(tmp, '/'); if (tmp != NULL) tmp++; } + fileName = (tmp ? tmp : last); } - if (mapName) - fprintf(outFile, "%s(%s)\n", fileName, mapName); - else - fprintf(outFile, "%s\n", fileName); - return; + + if (map->name) { + size_t len = strlen(fileName) + strlen(map->name) + 3; + + cp->comp[cp->num].name = _XkbAlloc(len * sizeof(char)); + if (!cp->comp[cp->num].name) { + ERROR("Could not allocate space for component name\n"); + return False; + } + sprintf(cp->comp[cp->num].name, "%s(%s)", fileName, map->name); + } + else { + cp->comp[cp->num].name = strdup(fileName); + if (!cp->comp[cp->num].name) { + ERROR("Could not duplicate component name\n"); + return False; + } + } + + cp->comp[cp->num].flags = map->flags; + cp->num++; + + return True; } /***====================================================================***/ static int -AddDirectory(char *head, char *ptrn, char *rest, char *map) +AddDirectory(ListHead *lh, char *head, char *ptrn, char *rest, char *map) { #ifdef WIN32 HANDLE dirh; @@ -288,10 +344,11 @@ AddDirectory(char *head, char *ptrn, char *rest, char *map) continue; if (ptrn && (!XkbcNameMatchesPattern(filename, ptrn))) continue; - tmp = - (char *) uAlloc((head ? strlen(head) : 0) + strlen(filename) + 2); - if (!tmp) + tmp = _XkbAlloc((head ? strlen(head) : 0) + strlen(filename) + 2); + if (!tmp) { + ERROR("Could not allocate space for file listing\n"); continue; + } sprintf(tmp, "%s%s%s", (head ? head : ""), (head ? "/" : ""), filename); if (stat(tmp, &sbuf) < 0) @@ -306,12 +363,9 @@ AddDirectory(char *head, char *ptrn, char *rest, char *map) continue; } if (S_ISDIR(sbuf.st_mode)) - { - if ((rest != NULL) || (verboseLevel & ListRecursive)) - nMatch += AddDirectory(tmp, rest, NULL, map); - } + nMatch += AddDirectory(lh, tmp, rest, NULL, map); else - nMatch += AddListing(tmp, map); + nMatch += AddListing(lh, tmp, map); } #ifdef WIN32 while (FindNextFile(dirh, &file)); @@ -321,13 +375,16 @@ AddDirectory(char *head, char *ptrn, char *rest, char *map) /***====================================================================***/ -static Bool -AddMatchingFiles(char *head_in, unsigned type) +static int +AddMatchingFiles(ListHead *lh, char *head_in, char *base, unsigned type) { char *str, *head, *ptrn, *rest = NULL; + char buf[PATH_MAX]; + size_t len; if (head_in == NULL) return 0; + ptrn = NULL; for (str = head_in; (*str != '\0') && (*str != '?') && (*str != '*'); str++) @@ -352,6 +409,7 @@ AddMatchingFiles(char *head_in, unsigned type) *ptrn = '\0'; ptrn++; } + if (ptrn) { rest = strchr(ptrn, '/'); @@ -361,6 +419,7 @@ AddMatchingFiles(char *head_in, unsigned type) rest++; } } + if (((rest && ptrn) && ((strchr(ptrn, '(') != NULL) || (strchr(ptrn, ')') != NULL))) || (head @@ -370,7 +429,16 @@ AddMatchingFiles(char *head_in, unsigned type) ACTION("Illegal specifier ignored\n"); return 0; } - return AddDirectory(head, ptrn, rest, NULL); + + /* Prepend XKB directory */ + snprintf(buf, PATH_MAX, "%s%s%s", base ? base : "", base ? "/" : "", + XkbDirectoryForInclude(type)); + len = strlen(buf); + if (head) + snprintf(&buf[len], PATH_MAX - len, "/%s", head); + head = buf; + + return AddDirectory(lh, head, ptrn, rest, NULL); } /***====================================================================***/ @@ -378,89 +446,205 @@ AddMatchingFiles(char *head_in, unsigned type) static Bool MapMatches(char *mapToConsider, char *ptrn) { - if (ptrn != NULL) - return XkbcNameMatchesPattern(mapToConsider, ptrn); - return False; + return ptrn ? XkbcNameMatchesPattern(mapToConsider, ptrn) : True; } -int -GenerateListing(char *out_name) +static int +GenerateComponents(ListHead *lh, XkbComponentListPtr complist, unsigned type, + int *max, unsigned strip) { - int i; - FILE *inputFile, *outFile; + int i, extra = 0; + FILE *inputFile; + CompPair cp = { 0 }; XkbFile *rtrn, *mapToUse; unsigned oldWarningLevel; char *mapName; - if (nFilesListed < 1) - { - ERROR("Must specify at least one file or pattern to list\n"); - return 0; - } - if ((!out_name) || ((out_name[0] == '-') && (out_name[1] == '\0'))) - outFile = stdout; - else if ((outFile = fopen(out_name, "w")) == NULL) - { - ERROR("Cannot open \"%s\" to write keyboard description\n", - out_name); - ACTION("Exiting\n"); + if (!lh || !complist || !max) { + ERROR("Missing arguments to GenerateComponents\n"); return 0; } + #ifdef DEBUG if (warningLevel > 9) fprintf(stderr, "should list:\n"); #endif - for (i = 0; i < nListed; i++) - { + + oldWarningLevel = warningLevel; + warningLevel = 0; + + for (i = 0; i < lh->nListed; i++) { + struct stat sbuf; + #ifdef DEBUG - if (warningLevel > 9) - { + if (oldWarningLevel > 9) { fprintf(stderr, "%s(%s)\n", - (list[i].file ? list[i].file : "*"), - (list[i].map ? list[i].map : "*")); + (lh->list[i].file ? lh->list[i].file : "*"), + (lh->list[i].map ? lh->list[i].map : "*")); } #endif - oldWarningLevel = warningLevel; - warningLevel = 0; - if (list[i].file) - { - struct stat sbuf; - if (stat(list[i].file, &sbuf) < 0) - { - if (oldWarningLevel > 5) - WARN("Couldn't open \"%s\"\n", list[i].file); - continue; - } - if (S_ISDIR(sbuf.st_mode)) - { - if (verboseLevel & ListRecursive) - AddDirectory(list[i].file, NULL, NULL, NULL); - continue; - } + if (!lh->list[i].file) + continue; - inputFile = fopen(list[i].file, "r"); - if (!inputFile) - { - if (oldWarningLevel > 5) - WARN("Couldn't open \"%s\"\n", list[i].file); + if (stat(lh->list[i].file, &sbuf) < 0) { + if (oldWarningLevel > 5) + WARN("Couldn't open \"%s\"\n", lh->list[i].file); + continue; + } + + if (S_ISDIR(sbuf.st_mode)) + continue; + + inputFile = fopen(lh->list[i].file, "r"); + if (!inputFile) { + if (oldWarningLevel > 5) + WARN("Couldn't open \"%s\"\n", lh->list[i].file); + continue; + } + + setScanState(lh->list[i].file, 1); + if (!XKBParseFile(inputFile, &rtrn) || !rtrn) { + if (oldWarningLevel > 5) + WARN("Couldn't parse file \"%s\"\n", lh->list[i].file); + continue; + } + + mapName = lh->list[i].map; + mapToUse = rtrn; + for (; mapToUse; mapToUse = (XkbFile *)mapToUse->common.next) { + if (!MapMatches(mapToUse->name, mapName)) + continue; + if (cp.num >= *max) { + extra++; continue; } - setScanState(list[i].file, 1); - if (XKBParseFile(inputFile, &rtrn) && (rtrn != NULL)) - { - mapName = list[i].map; - mapToUse = rtrn; - for (; mapToUse; mapToUse = (XkbFile *) mapToUse->common.next) - { - if (!MapMatches(mapToUse->name, mapName)) - continue; - ListFile(outFile, list[i].file, mapToUse); - } - } - fclose(inputFile); + AddComponent(&cp, lh->list[i].file, mapToUse, strip); } - warningLevel = oldWarningLevel; } - return 1; + warningLevel = oldWarningLevel; + + /* Trim excess component slots */ + if (cp.sz > 0 && cp.sz > cp.num) { + if (_XkbRealloc(cp.comp, cp.num * sizeof(XkbComponentNameRec))) + cp.sz = cp.num; + else + WARN("Could not reallocate component name list\n"); + } + + if (extra) + *max = 0; + else + *max -= cp.num; + + switch (type) { + case XkmKeymapFile: + complist->num_keymaps = cp.num; + complist->keymaps = cp.comp; + break; + case XkmKeyNamesIndex: + complist->num_keycodes = cp.num; + complist->keycodes = cp.comp; + break; + case XkmTypesIndex: + complist->num_types = cp.num; + complist->types = cp.comp; + break; + case XkmCompatMapIndex: + complist->num_compat = cp.num; + complist->compat = cp.comp; + break; + case XkmSymbolsIndex: + complist->num_symbols = cp.num; + complist->symbols = cp.comp; + break; + case XkmGeometryIndex: + complist->num_geometry = cp.num; + complist->geometry = cp.comp; + break; + } + + return extra; +} + +XkbComponentListPtr +XkbcListComponents(unsigned int deviceSpec, XkbComponentNamesPtr ptrns, + int *maxMatch) +{ + XkbComponentListPtr complist = NULL; + char *cur; + ListHead lh = { 0 }; + int extra = 0; + unsigned dirsToStrip; + + complist = _XkbTypedCalloc(1, XkbComponentListRec); + if (!complist) { + ERROR("could not allocate space for listing\n"); + goto out; + } + + if (!maxMatch || *maxMatch <= 0) + goto out; + + /* Figure out directory stripping (including 1 for type directory) */ + cur = DFLT_XKB_CONFIG_ROOT; + dirsToStrip = 1; + while ((cur = strchr(cur, '/')) != NULL) { + cur++; + dirsToStrip++; + } + + if (ptrns->keymap) { + AddMatchingFiles(&lh, ptrns->keymap, DFLT_XKB_CONFIG_ROOT, + XkmKeymapFile); + extra += GenerateComponents(&lh, complist, XkmKeymapFile, + maxMatch, dirsToStrip); + ClearList(&lh); + } + + if (ptrns->keycodes) { + AddMatchingFiles(&lh, ptrns->keycodes, DFLT_XKB_CONFIG_ROOT, + XkmKeyNamesIndex); + extra += GenerateComponents(&lh, complist, XkmKeyNamesIndex, + maxMatch, dirsToStrip); + ClearList(&lh); + } + + if (ptrns->types) { + AddMatchingFiles(&lh, ptrns->types, DFLT_XKB_CONFIG_ROOT, + XkmTypesIndex); + extra += GenerateComponents(&lh, complist, XkmTypesIndex, + maxMatch, dirsToStrip); + ClearList(&lh); + } + + if (ptrns->compat) { + AddMatchingFiles(&lh, ptrns->compat, DFLT_XKB_CONFIG_ROOT, + XkmCompatMapIndex); + extra += GenerateComponents(&lh, complist, XkmCompatMapIndex, + maxMatch, dirsToStrip); + ClearList(&lh); + } + + if (ptrns->symbols) { + AddMatchingFiles(&lh, ptrns->symbols, DFLT_XKB_CONFIG_ROOT, + XkmSymbolsIndex); + extra += GenerateComponents(&lh, complist, XkmSymbolsIndex, + maxMatch, dirsToStrip); + ClearList(&lh); + } + + if (ptrns->geometry) { + AddMatchingFiles(&lh, ptrns->geometry, DFLT_XKB_CONFIG_ROOT, + XkmGeometryIndex); + extra += GenerateComponents(&lh, complist, XkmGeometryIndex, + maxMatch, dirsToStrip); + ClearList(&lh); + } + + FreeList(&lh); +out: + if (maxMatch) + *maxMatch = extra; + return complist; } diff --git a/src/xkbcomp/xkbcomp.h b/src/xkbcomp/xkbcomp.h index 993bb61..d3a64b9 100644 --- a/src/xkbcomp/xkbcomp.h +++ b/src/xkbcomp/xkbcomp.h @@ -360,13 +360,4 @@ CompileCompatMap(XkbFile *file, XkbcDescPtr xkb, unsigned merge, extern Bool CompileSymbols(XkbFile *file, XkbcDescPtr xkb, unsigned merge); -#define WantLongListing (1<<0) -#define WantPartialMaps (1<<1) -#define WantHiddenMaps (1<<2) -#define WantFullNames (1<<3) -#define ListRecursive (1<<4) - -extern int GenerateListing(char * /* filename */ - ); - #endif /* XKBCOMP_H */ -- 2.7.4