xkbcomp: Another fairly major rewrite of the listing mode
The listing code in xkbcomp had been setup to allocate a set of buffers with file paths and then later parse through them to find which maps were needed. All the allocation (with the additional allocation for the components list) was making it really slow, so this patch makes everything simpler by just generating the components list as we walk the directory tree.master
parent
18b43f8dfe
commit
481deea178
|
@ -130,18 +130,6 @@ SOFTWARE.
|
|||
|
||||
unsigned int listingDebug;
|
||||
|
||||
typedef struct _Listing {
|
||||
char *file;
|
||||
char *map;
|
||||
} Listing;
|
||||
|
||||
typedef struct _ListHead {
|
||||
int szListing;
|
||||
int nListed;
|
||||
|
||||
Listing *list;
|
||||
} ListHead;
|
||||
|
||||
typedef struct _CompPair {
|
||||
int num;
|
||||
int sz;
|
||||
|
@ -151,72 +139,6 @@ typedef struct _CompPair {
|
|||
|
||||
/***====================================================================***/
|
||||
|
||||
static void
|
||||
ClearList(ListHead *lh)
|
||||
{
|
||||
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
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
lh->list[lh->nListed].file = file;
|
||||
lh->list[lh->nListed].map = map;
|
||||
lh->nListed++;
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
/***====================================================================***/
|
||||
|
||||
static Bool
|
||||
AddComponent(CompPair *cp, char *fileName, XkbFile *map, unsigned dirsToStrip)
|
||||
{
|
||||
|
@ -228,7 +150,7 @@ AddComponent(CompPair *cp, char *fileName, XkbFile *map, unsigned dirsToStrip)
|
|||
XkbComponentNamePtr orig_comp = cp->comp;
|
||||
|
||||
if (cp->sz < 1)
|
||||
cp->sz = 10;
|
||||
cp->sz = 8;
|
||||
else
|
||||
cp->sz *= 2;
|
||||
|
||||
|
@ -281,10 +203,76 @@ AddComponent(CompPair *cp, char *fileName, XkbFile *map, unsigned dirsToStrip)
|
|||
return True;
|
||||
}
|
||||
|
||||
static Bool
|
||||
MapMatches(char *mapToConsider, char *ptrn)
|
||||
{
|
||||
return ptrn ? XkbcNameMatchesPattern(mapToConsider, ptrn) : True;
|
||||
}
|
||||
|
||||
static int
|
||||
ParseComponents(CompPair *cp, char *path, char *map, int *max, unsigned strip)
|
||||
{
|
||||
int extra = 0;
|
||||
FILE *inputFile;
|
||||
XkbFile *rtrn, *mapToUse;
|
||||
unsigned oldWarningLevel;
|
||||
|
||||
if (!cp || !path || !max)
|
||||
return 0;
|
||||
|
||||
#ifdef DEBUG
|
||||
if (warningLevel > 9)
|
||||
fprintf(stderr, "should list:\n");
|
||||
#endif
|
||||
|
||||
oldWarningLevel = warningLevel;
|
||||
warningLevel = 0;
|
||||
|
||||
#ifdef DEBUG
|
||||
if (oldWarningLevel > 9)
|
||||
fprintf(stderr, "%s(%s)\n", path ? path : "*", map ? map : "*");
|
||||
#endif
|
||||
|
||||
inputFile = fopen(path, "r");
|
||||
if (!inputFile) {
|
||||
if (oldWarningLevel > 5)
|
||||
WARN("Couldn't open \"%s\"\n", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
setScanState(path, 1);
|
||||
if (!XKBParseFile(inputFile, &rtrn) || !rtrn) {
|
||||
if (oldWarningLevel > 5)
|
||||
WARN("Couldn't parse file \"%s\"\n", path);
|
||||
fclose(inputFile);
|
||||
return 0;
|
||||
}
|
||||
|
||||
mapToUse = rtrn;
|
||||
for (; mapToUse; mapToUse = (XkbFile *)mapToUse->common.next) {
|
||||
if (!MapMatches(mapToUse->name, map))
|
||||
continue;
|
||||
if (*max <= 0) {
|
||||
extra++;
|
||||
continue;
|
||||
}
|
||||
if (AddComponent(cp, path, mapToUse, strip))
|
||||
(*max)--;
|
||||
}
|
||||
|
||||
warningLevel = oldWarningLevel;
|
||||
|
||||
if (extra)
|
||||
*max = 0;
|
||||
|
||||
return extra;
|
||||
}
|
||||
|
||||
/***====================================================================***/
|
||||
|
||||
static int
|
||||
AddDirectory(ListHead *lh, char *head, char *ptrn, char *rest, char *map)
|
||||
AddDirectory(CompPair *cp, char *head, char *ptrn, char *rest, char *map,
|
||||
int *max, unsigned strip)
|
||||
{
|
||||
#ifdef WIN32
|
||||
HANDLE dirh;
|
||||
|
@ -294,26 +282,33 @@ AddDirectory(ListHead *lh, char *head, char *ptrn, char *rest, char *map)
|
|||
struct dirent *file;
|
||||
#endif
|
||||
int nMatch;
|
||||
size_t baselen;
|
||||
char path[PATH_MAX];
|
||||
|
||||
if (map == NULL)
|
||||
{
|
||||
if (!head) {
|
||||
ERROR("Must specify directory name\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
strncpy(path, head, sizeof(path));
|
||||
path[PATH_MAX - 1] = '\0';
|
||||
baselen = strlen(path);
|
||||
|
||||
if (!map) {
|
||||
char *tmp = ptrn;
|
||||
if ((rest == NULL) && (ptrn != NULL) && (strchr(ptrn, '/') == NULL))
|
||||
{
|
||||
|
||||
if (!rest && ptrn && !strchr(ptrn, '/')) {
|
||||
tmp = ptrn;
|
||||
map = strchr(ptrn, '(');
|
||||
}
|
||||
else if ((rest == NULL) && (ptrn == NULL) &&
|
||||
(head != NULL) && (strchr(head, '/') == NULL))
|
||||
{
|
||||
else if (!rest && !ptrn && !strchr(head, '/')) {
|
||||
tmp = head;
|
||||
map = strchr(head, '(');
|
||||
}
|
||||
if (map != NULL)
|
||||
{
|
||||
|
||||
if (map) {
|
||||
tmp = strchr(tmp, ')');
|
||||
if ((tmp == NULL) || (tmp[1] != '\0'))
|
||||
{
|
||||
if (!tmp || tmp[1] != '\0') {
|
||||
ERROR("File and map must have the format file(map)\n");
|
||||
return 0;
|
||||
}
|
||||
|
@ -322,21 +317,24 @@ AddDirectory(ListHead *lh, char *head, char *ptrn, char *rest, char *map)
|
|||
*tmp = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
if ((dirh = FindFirstFile("*.*", &file)) == INVALID_HANDLE_VALUE)
|
||||
return 0;
|
||||
#else
|
||||
if ((dirp = opendir((head ? head : "."))) == NULL)
|
||||
if (!(dirp = opendir(head))) {
|
||||
ERROR("Could not open directory \"%s\"\n", head ? head : ".");
|
||||
return 0;
|
||||
nMatch = 0;
|
||||
}
|
||||
#endif
|
||||
nMatch = 0;
|
||||
#ifdef WIN32
|
||||
do
|
||||
#else
|
||||
while ((file = readdir(dirp)) != NULL)
|
||||
#endif
|
||||
{
|
||||
char *tmp, *filename;
|
||||
char *filename;
|
||||
struct stat sbuf;
|
||||
|
||||
filename = FileName(file);
|
||||
|
@ -344,28 +342,21 @@ AddDirectory(ListHead *lh, char *head, char *ptrn, char *rest, char *map)
|
|||
continue;
|
||||
if (ptrn && (!XkbcNameMatchesPattern(filename, ptrn)))
|
||||
continue;
|
||||
tmp = _XkbAlloc((head ? strlen(head) : 0) + strlen(filename) + 2);
|
||||
if (!tmp) {
|
||||
ERROR("Could not allocate space for file listing\n");
|
||||
|
||||
snprintf(&path[baselen], sizeof(path) - baselen, "/%s", filename);
|
||||
if (stat(path, &sbuf) < 0) {
|
||||
ERROR("Could not read file \"%s\"\n", path);
|
||||
continue;
|
||||
}
|
||||
sprintf(tmp, "%s%s%s", (head ? head : ""), (head ? "/" : ""),
|
||||
filename);
|
||||
if (stat(tmp, &sbuf) < 0)
|
||||
{
|
||||
uFree(tmp);
|
||||
|
||||
if ((rest && !S_ISDIR(sbuf.st_mode)) ||
|
||||
(map && S_ISDIR(sbuf.st_mode)))
|
||||
continue;
|
||||
}
|
||||
if (((rest != NULL) && (!S_ISDIR(sbuf.st_mode))) ||
|
||||
((map != NULL) && (S_ISDIR(sbuf.st_mode))))
|
||||
{
|
||||
uFree(tmp);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (S_ISDIR(sbuf.st_mode))
|
||||
nMatch += AddDirectory(lh, tmp, rest, NULL, map);
|
||||
nMatch += AddDirectory(cp, path, rest, NULL, map, max, strip);
|
||||
else
|
||||
nMatch += AddListing(lh, tmp, map);
|
||||
nMatch += ParseComponents(cp, path, map, max, strip);
|
||||
}
|
||||
#ifdef WIN32
|
||||
while (FindNextFile(dirh, &file));
|
||||
|
@ -376,13 +367,17 @@ AddDirectory(ListHead *lh, char *head, char *ptrn, char *rest, char *map)
|
|||
/***====================================================================***/
|
||||
|
||||
static int
|
||||
AddMatchingFiles(ListHead *lh, char *head_in, char *base, unsigned type)
|
||||
GenerateComponent(XkbComponentListPtr complist, unsigned type, char *head_in,
|
||||
char *base, int *max)
|
||||
{
|
||||
char *str, *head, *ptrn, *rest = NULL;
|
||||
char *str, *head, *ptrn = NULL, *rest = NULL;
|
||||
char buf[PATH_MAX];
|
||||
size_t len;
|
||||
CompPair cp;
|
||||
unsigned dirsToStrip;
|
||||
int extra;
|
||||
|
||||
if (head_in == NULL)
|
||||
if (!complist || !head_in || !max)
|
||||
return 0;
|
||||
|
||||
ptrn = NULL;
|
||||
|
@ -392,137 +387,56 @@ AddMatchingFiles(ListHead *lh, char *head_in, char *base, unsigned type)
|
|||
if ((str != head_in) && (*str == '/'))
|
||||
ptrn = str;
|
||||
}
|
||||
if (*str == '\0')
|
||||
{ /* no wildcards */
|
||||
|
||||
if (*str == '\0') {
|
||||
/* no wildcards */
|
||||
head = head_in;
|
||||
ptrn = NULL;
|
||||
rest = NULL;
|
||||
}
|
||||
else if (ptrn == NULL)
|
||||
{ /* no slash before the first wildcard */
|
||||
else if (!ptrn) {
|
||||
/* no slash before the first wildcard */
|
||||
head = NULL;
|
||||
ptrn = head_in;
|
||||
}
|
||||
else
|
||||
{ /* slash followed by wildcard */
|
||||
else {
|
||||
/* slash followed by wildcard */
|
||||
head = head_in;
|
||||
*ptrn = '\0';
|
||||
ptrn++;
|
||||
}
|
||||
|
||||
if (ptrn)
|
||||
{
|
||||
if (ptrn) {
|
||||
rest = strchr(ptrn, '/');
|
||||
if (rest != NULL)
|
||||
{
|
||||
if (rest) {
|
||||
*rest = '\0';
|
||||
rest++;
|
||||
}
|
||||
}
|
||||
|
||||
if (((rest && ptrn)
|
||||
&& ((strchr(ptrn, '(') != NULL) || (strchr(ptrn, ')') != NULL)))
|
||||
|| (head
|
||||
&& ((strchr(head, '(') != NULL) || (strchr(head, ')') != NULL))))
|
||||
{
|
||||
if ((rest && ptrn && (strchr(ptrn, '(') || strchr(ptrn, ')'))) ||
|
||||
(head && (strchr(head, '(') || strchr(head, ')')))) {
|
||||
ERROR("Files/maps to list must have the form file(map)\n");
|
||||
ACTION("Illegal specifier ignored\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Prepend XKB directory */
|
||||
snprintf(buf, PATH_MAX, "%s%s%s", base ? base : "", base ? "/" : "",
|
||||
snprintf(buf, sizeof(buf), "%s%s%s", base ? base : "", base ? "/" : "",
|
||||
XkbDirectoryForInclude(type));
|
||||
len = strlen(buf);
|
||||
|
||||
/* Figure out directory stripping */
|
||||
str = buf;
|
||||
dirsToStrip = 0;
|
||||
while ((str = strchr(str, '/')) != NULL) {
|
||||
str++;
|
||||
dirsToStrip++;
|
||||
}
|
||||
|
||||
if (head)
|
||||
snprintf(&buf[len], PATH_MAX - len, "/%s", head);
|
||||
head = buf;
|
||||
|
||||
return AddDirectory(lh, head, ptrn, rest, NULL);
|
||||
}
|
||||
|
||||
/***====================================================================***/
|
||||
|
||||
static Bool
|
||||
MapMatches(char *mapToConsider, char *ptrn)
|
||||
{
|
||||
return ptrn ? XkbcNameMatchesPattern(mapToConsider, ptrn) : True;
|
||||
}
|
||||
|
||||
static int
|
||||
GenerateComponents(ListHead *lh, XkbComponentListPtr complist, unsigned type,
|
||||
int *max, unsigned strip)
|
||||
{
|
||||
int i, extra = 0;
|
||||
FILE *inputFile;
|
||||
CompPair cp = { 0 };
|
||||
XkbFile *rtrn, *mapToUse;
|
||||
unsigned oldWarningLevel;
|
||||
char *mapName;
|
||||
|
||||
if (!lh || !complist || !max) {
|
||||
ERROR("Missing arguments to GenerateComponents\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (warningLevel > 9)
|
||||
fprintf(stderr, "should list:\n");
|
||||
#endif
|
||||
|
||||
oldWarningLevel = warningLevel;
|
||||
warningLevel = 0;
|
||||
|
||||
for (i = 0; i < lh->nListed; i++) {
|
||||
struct stat sbuf;
|
||||
|
||||
#ifdef DEBUG
|
||||
if (oldWarningLevel > 9) {
|
||||
fprintf(stderr, "%s(%s)\n",
|
||||
(lh->list[i].file ? lh->list[i].file : "*"),
|
||||
(lh->list[i].map ? lh->list[i].map : "*"));
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!lh->list[i].file)
|
||||
continue;
|
||||
|
||||
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;
|
||||
}
|
||||
AddComponent(&cp, lh->list[i].file, mapToUse, strip);
|
||||
}
|
||||
}
|
||||
warningLevel = oldWarningLevel;
|
||||
memset(&cp, 0, sizeof(CompPair));
|
||||
extra = AddDirectory(&cp, head, ptrn, rest, NULL, max, dirsToStrip);
|
||||
|
||||
/* Trim excess component slots */
|
||||
if (cp.sz > 0 && cp.sz > cp.num) {
|
||||
|
@ -532,11 +446,6 @@ GenerateComponents(ListHead *lh, XkbComponentListPtr complist, unsigned type,
|
|||
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;
|
||||
|
@ -567,15 +476,14 @@ GenerateComponents(ListHead *lh, XkbComponentListPtr complist, unsigned type,
|
|||
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) {
|
||||
|
@ -586,63 +494,30 @@ XkbcListComponents(unsigned int deviceSpec, XkbComponentNamesPtr ptrns,
|
|||
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 && *ptrns->keymap != '\0')
|
||||
extra += GenerateComponent(complist, XkmKeymapFile, ptrns->keycodes,
|
||||
DFLT_XKB_CONFIG_ROOT, maxMatch);
|
||||
|
||||
if (ptrns->keymap) {
|
||||
AddMatchingFiles(&lh, ptrns->keymap, DFLT_XKB_CONFIG_ROOT,
|
||||
XkmKeymapFile);
|
||||
extra += GenerateComponents(&lh, complist, XkmKeymapFile,
|
||||
maxMatch, dirsToStrip);
|
||||
ClearList(&lh);
|
||||
}
|
||||
if (ptrns->keycodes && *ptrns->keycodes != '\0')
|
||||
extra += GenerateComponent(complist, XkmKeyNamesIndex, ptrns->keycodes,
|
||||
DFLT_XKB_CONFIG_ROOT, maxMatch);
|
||||
|
||||
if (ptrns->keycodes) {
|
||||
AddMatchingFiles(&lh, ptrns->keycodes, DFLT_XKB_CONFIG_ROOT,
|
||||
XkmKeyNamesIndex);
|
||||
extra += GenerateComponents(&lh, complist, XkmKeyNamesIndex,
|
||||
maxMatch, dirsToStrip);
|
||||
ClearList(&lh);
|
||||
}
|
||||
if (ptrns->types && *ptrns->types != '\0')
|
||||
extra += GenerateComponent(complist, XkmTypesIndex, ptrns->types,
|
||||
DFLT_XKB_CONFIG_ROOT, maxMatch);
|
||||
|
||||
if (ptrns->types) {
|
||||
AddMatchingFiles(&lh, ptrns->types, DFLT_XKB_CONFIG_ROOT,
|
||||
XkmTypesIndex);
|
||||
extra += GenerateComponents(&lh, complist, XkmTypesIndex,
|
||||
maxMatch, dirsToStrip);
|
||||
ClearList(&lh);
|
||||
}
|
||||
if (ptrns->compat && *ptrns->compat != '\0')
|
||||
extra += GenerateComponent(complist, XkmCompatMapIndex, ptrns->compat,
|
||||
DFLT_XKB_CONFIG_ROOT, maxMatch);
|
||||
|
||||
if (ptrns->compat) {
|
||||
AddMatchingFiles(&lh, ptrns->compat, DFLT_XKB_CONFIG_ROOT,
|
||||
XkmCompatMapIndex);
|
||||
extra += GenerateComponents(&lh, complist, XkmCompatMapIndex,
|
||||
maxMatch, dirsToStrip);
|
||||
ClearList(&lh);
|
||||
}
|
||||
if (ptrns->symbols && *ptrns->symbols != '\0')
|
||||
extra += GenerateComponent(complist, XkmSymbolsIndex, ptrns->symbols,
|
||||
DFLT_XKB_CONFIG_ROOT, maxMatch);
|
||||
|
||||
if (ptrns->symbols) {
|
||||
AddMatchingFiles(&lh, ptrns->symbols, DFLT_XKB_CONFIG_ROOT,
|
||||
XkmSymbolsIndex);
|
||||
extra += GenerateComponents(&lh, complist, XkmSymbolsIndex,
|
||||
maxMatch, dirsToStrip);
|
||||
ClearList(&lh);
|
||||
}
|
||||
if (ptrns->geometry && *ptrns->geometry != '\0')
|
||||
extra += GenerateComponent(complist, XkmGeometryIndex, ptrns->geometry,
|
||||
DFLT_XKB_CONFIG_ROOT, maxMatch);
|
||||
|
||||
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;
|
||||
|
|
Loading…
Reference in New Issue