1f46a6179Smrg/************************************************************
2f46a6179Smrg Copyright 1996 by Silicon Graphics Computer Systems, Inc.
3f46a6179Smrg
4f46a6179Smrg Permission to use, copy, modify, and distribute this
5f46a6179Smrg software and its documentation for any purpose and without
6f46a6179Smrg fee is hereby granted, provided that the above copyright
7f46a6179Smrg notice appear in all copies and that both that copyright
8f46a6179Smrg notice and this permission notice appear in supporting
9bfe6082cSmrg documentation, and that the name of Silicon Graphics not be
10bfe6082cSmrg used in advertising or publicity pertaining to distribution
11f46a6179Smrg of the software without specific prior written permission.
12bfe6082cSmrg Silicon Graphics makes no representation about the suitability
13f46a6179Smrg of this software for any purpose. It is provided "as is"
14f46a6179Smrg without any express or implied warranty.
15bfe6082cSmrg
16bfe6082cSmrg SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17bfe6082cSmrg SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18f46a6179Smrg AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19bfe6082cSmrg GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20bfe6082cSmrg DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21bfe6082cSmrg DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22f46a6179Smrg OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
23f46a6179Smrg THE USE OR PERFORMANCE OF THIS SOFTWARE.
24f46a6179Smrg
25f46a6179Smrg ********************************************************/
26f46a6179Smrg/***********************************************************
27f46a6179Smrg
28f46a6179SmrgCopyright 1988, 1998  The Open Group
29f46a6179Smrg
30f46a6179SmrgPermission to use, copy, modify, distribute, and sell this software and its
31f46a6179Smrgdocumentation for any purpose is hereby granted without fee, provided that
32f46a6179Smrgthe above copyright notice appear in all copies and that both that
33f46a6179Smrgcopyright notice and this permission notice appear in supporting
34f46a6179Smrgdocumentation.
35f46a6179Smrg
36f46a6179SmrgThe above copyright notice and this permission notice shall be included in
37f46a6179Smrgall copies or substantial portions of the Software.
38f46a6179Smrg
39f46a6179SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
40f46a6179SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
41f46a6179SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
42f46a6179SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
43f46a6179SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
44f46a6179SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
45f46a6179Smrg
46f46a6179SmrgExcept as contained in this notice, the name of The Open Group shall not be
47f46a6179Smrgused in advertising or otherwise to promote the sale, use or other dealings
48f46a6179Smrgin this Software without prior written authorization from The Open Group.
49f46a6179Smrg
50f46a6179Smrg
51f46a6179SmrgCopyright 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
52f46a6179Smrg
53f46a6179Smrg                        All Rights Reserved
54f46a6179Smrg
55bfe6082cSmrgPermission to use, copy, modify, and distribute this software and its
56bfe6082cSmrgdocumentation for any purpose and without fee is hereby granted,
57f46a6179Smrgprovided that the above copyright notice appear in all copies and that
58bfe6082cSmrgboth that copyright notice and this permission notice appear in
59f46a6179Smrgsupporting documentation, and that the name of Digital not be
60f46a6179Smrgused in advertising or publicity pertaining to distribution of the
61bfe6082cSmrgsoftware without specific, written prior permission.
62f46a6179Smrg
63f46a6179SmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
64f46a6179SmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
65f46a6179SmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
66f46a6179SmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
67f46a6179SmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
68f46a6179SmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
69f46a6179SmrgSOFTWARE.
70f46a6179Smrg
71f46a6179Smrg******************************************************************/
72f46a6179Smrg
73f46a6179Smrg#include <stdio.h>
74f46a6179Smrg#include <ctype.h>
75f46a6179Smrg#include <sys/types.h>
76f46a6179Smrg#include <sys/stat.h>
77f46a6179Smrg#include <X11/keysym.h>
78f46a6179Smrg
79f46a6179Smrg#define	DEBUG_VAR listingDebug
80f46a6179Smrg#include "xkbcomp.h"
81f46a6179Smrg#include <stdlib.h>
8234345a63Smrg
83f46a6179Smrg#ifdef _POSIX_SOURCE
8434345a63Smrg# include <limits.h>
85f46a6179Smrg#else
8634345a63Smrg# define _POSIX_SOURCE
8734345a63Smrg# include <limits.h>
8834345a63Smrg# undef _POSIX_SOURCE
89f46a6179Smrg#endif
9034345a63Smrg
91f46a6179Smrg#ifndef PATH_MAX
92f46a6179Smrg#ifdef WIN32
93f46a6179Smrg#define PATH_MAX 512
94f46a6179Smrg#else
95f46a6179Smrg#include <sys/param.h>
96f46a6179Smrg#endif
97f46a6179Smrg#ifndef PATH_MAX
98f46a6179Smrg#ifdef MAXPATHLEN
99f46a6179Smrg#define PATH_MAX MAXPATHLEN
100f46a6179Smrg#else
101f46a6179Smrg#define PATH_MAX 1024
102f46a6179Smrg#endif
103f46a6179Smrg#endif
104f46a6179Smrg#endif
105f46a6179Smrg
106f46a6179Smrg#ifdef WIN32
1073fb1fa07Smrg# define WIN32_LEAN_AND_MEAN
108c82dfdfbSmrg# include <X11/Xwindows.h>
10934345a63Smrg# define FileName(file) file.cFileName
11034345a63Smrg# undef TEXT
11134345a63Smrg# undef ALTERNATE
112f46a6179Smrg#else
11334345a63Smrg# include <dirent.h>
11434345a63Smrg# define FileName(file) file->d_name
115f46a6179Smrg#endif
116f46a6179Smrg
117f46a6179Smrg#include "xkbpath.h"
118f46a6179Smrg#include "parseutils.h"
119f46a6179Smrg#include "misc.h"
120f46a6179Smrg#include "tokens.h"
121f46a6179Smrg#include <X11/extensions/XKBgeom.h>
122f46a6179Smrg
123f46a6179Smrg#define	lowbit(x)	((x) & (-(x)))
124f46a6179Smrg
1256930ead5Smrg#ifdef DEBUG
12634345a63Smrgunsigned int listingDebug;
1276930ead5Smrg#endif
12834345a63Smrg
12934345a63Smrgstatic int szListing = 0;
13034345a63Smrgstatic int nListed = 0;
13134345a63Smrgstatic int nFilesListed = 0;
132f46a6179Smrg
13334345a63Smrgtypedef struct _Listing
13434345a63Smrg{
13534345a63Smrg    char *file;
13634345a63Smrg    char *map;
137f46a6179Smrg} Listing;
138f46a6179Smrg
13934345a63Smrgstatic int szMapOnly;
14034345a63Smrgstatic int nMapOnly;
14134345a63Smrgstatic char **mapOnly;
142f46a6179Smrg
14334345a63Smrgstatic Listing *list = NULL;
144f46a6179Smrg
145f46a6179Smrg/***====================================================================***/
146f46a6179Smrg
147f46a6179Smrgint
148f46a6179SmrgAddMapOnly(char *map)
149f46a6179Smrg{
15034345a63Smrg    if (nMapOnly >= szMapOnly)
15134345a63Smrg    {
15234345a63Smrg        if (szMapOnly < 1)
15334345a63Smrg            szMapOnly = 5;
15434345a63Smrg        else
15534345a63Smrg            szMapOnly *= 2;
1566930ead5Smrg        mapOnly = reallocarray(list, szMapOnly, sizeof(char *));
15734345a63Smrg        if (!mapOnly)
15834345a63Smrg        {
15934345a63Smrg            WSGO("Couldn't allocate list of maps\n");
16034345a63Smrg            return 0;
16134345a63Smrg        }
162f46a6179Smrg    }
16334345a63Smrg    mapOnly[nMapOnly++] = map;
164f46a6179Smrg    return 1;
165f46a6179Smrg}
166f46a6179Smrg
1676930ead5Smrgstatic int
16834345a63SmrgAddListing(char *file, char *map)
169f46a6179Smrg{
17034345a63Smrg    if (nListed >= szListing)
17134345a63Smrg    {
17234345a63Smrg        if (szListing < 1)
17334345a63Smrg            szListing = 10;
17434345a63Smrg        else
17534345a63Smrg            szListing *= 2;
1766930ead5Smrg        list = reallocarray(list, szListing, sizeof(Listing));
17734345a63Smrg        if (!list)
17834345a63Smrg        {
17934345a63Smrg            WSGO("Couldn't allocate list of files and maps\n");
18034345a63Smrg            ACTION("Exiting\n");
18134345a63Smrg            exit(1);
18234345a63Smrg        }
183f46a6179Smrg    }
184f46a6179Smrg
18534345a63Smrg    list[nListed].file = file;
18634345a63Smrg    list[nListed].map = map;
187f46a6179Smrg    nListed++;
18834345a63Smrg    if (file != NULL)
18934345a63Smrg        nFilesListed++;
190f46a6179Smrg    return 1;
191f46a6179Smrg}
192f46a6179Smrg
193f46a6179Smrg/***====================================================================***/
194f46a6179Smrg
195f46a6179Smrgstatic void
1966930ead5SmrgListFile(FILE *outFile, const char *fileName, XkbFile *map)
197f46a6179Smrg{
1986930ead5Smrg    unsigned flags;
1996930ead5Smrg    const char *mapName;
20034345a63Smrg
20134345a63Smrg    flags = map->flags;
20234345a63Smrg    if ((flags & XkbLC_Hidden) && (!(verboseLevel & WantHiddenMaps)))
20334345a63Smrg        return;
20434345a63Smrg    if ((flags & XkbLC_Partial) && (!(verboseLevel & WantPartialMaps)))
20534345a63Smrg        return;
20634345a63Smrg    if (verboseLevel & WantLongListing)
20734345a63Smrg    {
20834345a63Smrg        fprintf(outFile, (flags & XkbLC_Hidden) ? "h" : "-");
20934345a63Smrg        fprintf(outFile, (flags & XkbLC_Default) ? "d" : "-");
21034345a63Smrg        fprintf(outFile, (flags & XkbLC_Partial) ? "p" : "-");
21134345a63Smrg        fprintf(outFile, "----- ");
21234345a63Smrg        if (map->type == XkmSymbolsIndex)
21334345a63Smrg        {
21434345a63Smrg            fprintf(outFile, (flags & XkbLC_AlphanumericKeys) ? "a" : "-");
21534345a63Smrg            fprintf(outFile, (flags & XkbLC_ModifierKeys) ? "m" : "-");
21634345a63Smrg            fprintf(outFile, (flags & XkbLC_KeypadKeys) ? "k" : "-");
21734345a63Smrg            fprintf(outFile, (flags & XkbLC_FunctionKeys) ? "f" : "-");
21834345a63Smrg            fprintf(outFile, (flags & XkbLC_AlternateGroup) ? "g" : "-");
21934345a63Smrg            fprintf(outFile, "--- ");
22034345a63Smrg        }
22134345a63Smrg        else
22234345a63Smrg            fprintf(outFile, "-------- ");
223f46a6179Smrg    }
22434345a63Smrg    mapName = map->name;
22534345a63Smrg    if ((!(verboseLevel & WantFullNames)) && ((flags & XkbLC_Default) != 0))
22634345a63Smrg        mapName = NULL;
22734345a63Smrg    if (dirsToStrip > 0)
22834345a63Smrg    {
2296930ead5Smrg        const char *tmp, *last;
23034345a63Smrg        int i;
23134345a63Smrg        for (i = 0, tmp = last = fileName; (i < dirsToStrip) && tmp; i++)
23234345a63Smrg        {
23334345a63Smrg            last = tmp;
23434345a63Smrg            tmp = strchr(tmp, '/');
23534345a63Smrg            if (tmp != NULL)
23634345a63Smrg                tmp++;
23734345a63Smrg        }
23834345a63Smrg        fileName = (tmp ? tmp : last);
239f46a6179Smrg    }
240f46a6179Smrg    if (mapName)
24134345a63Smrg        fprintf(outFile, "%s(%s)\n", fileName, mapName);
24234345a63Smrg    else
24334345a63Smrg        fprintf(outFile, "%s\n", fileName);
244f46a6179Smrg    return;
245f46a6179Smrg}
246f46a6179Smrg
247f46a6179Smrg/***====================================================================***/
248f46a6179Smrg
249f46a6179Smrgstatic int
25034345a63SmrgAddDirectory(char *head, char *ptrn, char *rest, char *map)
251f46a6179Smrg{
252f46a6179Smrg#ifdef WIN32
25334345a63Smrg    HANDLE dirh;
25434345a63Smrg    WIN32_FIND_DATA file;
255f46a6179Smrg#else
25634345a63Smrg    DIR *dirp;
25734345a63Smrg    struct dirent *file;
258f46a6179Smrg#endif
25934345a63Smrg    int nMatch;
26034345a63Smrg
26134345a63Smrg    if (map == NULL)
26234345a63Smrg    {
26334345a63Smrg        char *tmp = ptrn;
26434345a63Smrg        if ((rest == NULL) && (ptrn != NULL) && (strchr(ptrn, '/') == NULL))
26534345a63Smrg        {
26634345a63Smrg            tmp = ptrn;
26734345a63Smrg            map = strchr(ptrn, '(');
26834345a63Smrg        }
26934345a63Smrg        else if ((rest == NULL) && (ptrn == NULL) &&
27034345a63Smrg                 (head != NULL) && (strchr(head, '/') == NULL))
27134345a63Smrg        {
27234345a63Smrg            tmp = head;
27334345a63Smrg            map = strchr(head, '(');
27434345a63Smrg        }
27534345a63Smrg        if (map != NULL)
27634345a63Smrg        {
27734345a63Smrg            tmp = strchr(tmp, ')');
27834345a63Smrg            if ((tmp == NULL) || (tmp[1] != '\0'))
27934345a63Smrg            {
280bfe6082cSmrg                ERROR("File and map must have the format file(map)\n");
28134345a63Smrg                return 0;
28234345a63Smrg            }
28334345a63Smrg            *map = '\0';
28434345a63Smrg            map++;
28534345a63Smrg            *tmp = '\0';
28634345a63Smrg        }
287f46a6179Smrg    }
288f46a6179Smrg#ifdef WIN32
289f46a6179Smrg    if ((dirh = FindFirstFile("*.*", &file)) == INVALID_HANDLE_VALUE)
29034345a63Smrg        return 0;
291f46a6179Smrg#else
29234345a63Smrg    if ((dirp = opendir((head ? head : "."))) == NULL)
29334345a63Smrg        return 0;
294f46a6179Smrg#endif
295c82dfdfbSmrg    nMatch = 0;
296f46a6179Smrg#ifdef WIN32
297f46a6179Smrg    do
298f46a6179Smrg#else
29934345a63Smrg    while ((file = readdir(dirp)) != NULL)
300f46a6179Smrg#endif
301f46a6179Smrg    {
30234345a63Smrg        char *tmp, *filename;
30334345a63Smrg        struct stat sbuf;
30434345a63Smrg
30534345a63Smrg        filename = FileName(file);
30634345a63Smrg        if (!filename || filename[0] == '.')
30734345a63Smrg            continue;
30834345a63Smrg        if (ptrn && (!XkbNameMatchesPattern(filename, ptrn)))
30934345a63Smrg            continue;
3106930ead5Smrg#ifdef HAVE_ASPRINTF
3116930ead5Smrg        if (asprintf(&tmp, "%s%s%s",
3126930ead5Smrg                     (head ? head : ""), (head ? "/" : ""), filename) < 0)
3136930ead5Smrg            continue;
3146930ead5Smrg#else
3156930ead5Smrg        size_t tmpsize = (head ? strlen(head) : 0) + strlen(filename) + 2;
3166930ead5Smrg        tmp = malloc(tmpsize);
31734345a63Smrg        if (!tmp)
31834345a63Smrg            continue;
319c82dfdfbSmrg        snprintf(tmp, tmpsize, "%s%s%s",
320c82dfdfbSmrg                 (head ? head : ""), (head ? "/" : ""), filename);
3216930ead5Smrg#endif
32234345a63Smrg        if (stat(tmp, &sbuf) < 0)
32334345a63Smrg        {
3246930ead5Smrg            free(tmp);
32534345a63Smrg            continue;
32634345a63Smrg        }
32734345a63Smrg        if (((rest != NULL) && (!S_ISDIR(sbuf.st_mode))) ||
32834345a63Smrg            ((map != NULL) && (S_ISDIR(sbuf.st_mode))))
32934345a63Smrg        {
3306930ead5Smrg            free(tmp);
33134345a63Smrg            continue;
33234345a63Smrg        }
33334345a63Smrg        if (S_ISDIR(sbuf.st_mode))
33434345a63Smrg        {
33534345a63Smrg            if ((rest != NULL) || (verboseLevel & ListRecursive))
33634345a63Smrg                nMatch += AddDirectory(tmp, rest, NULL, map);
33734345a63Smrg        }
33834345a63Smrg        else
33934345a63Smrg            nMatch += AddListing(tmp, map);
340f46a6179Smrg    }
341f46a6179Smrg#ifdef WIN32
342f46a6179Smrg    while (FindNextFile(dirh, &file));
343f46a6179Smrg#endif
344f46a6179Smrg    return nMatch;
345f46a6179Smrg}
346f46a6179Smrg
347f46a6179Smrg/***====================================================================***/
348f46a6179Smrg
349f46a6179SmrgBool
350f46a6179SmrgAddMatchingFiles(char *head_in)
351f46a6179Smrg{
35234345a63Smrg    char *str, *head, *ptrn, *rest = NULL;
35334345a63Smrg
35434345a63Smrg    if (head_in == NULL)
35534345a63Smrg        return 0;
35634345a63Smrg    ptrn = NULL;
35734345a63Smrg    for (str = head_in; (*str != '\0') && (*str != '?') && (*str != '*');
35834345a63Smrg         str++)
35934345a63Smrg    {
36034345a63Smrg        if ((str != head_in) && (*str == '/'))
36134345a63Smrg            ptrn = str;
362f46a6179Smrg    }
36334345a63Smrg    if (*str == '\0')
36434345a63Smrg    {                           /* no wildcards */
36534345a63Smrg        head = head_in;
36634345a63Smrg        ptrn = NULL;
36734345a63Smrg        rest = NULL;
368f46a6179Smrg    }
36934345a63Smrg    else if (ptrn == NULL)
37034345a63Smrg    {                           /* no slash before the first wildcard */
37134345a63Smrg        head = NULL;
37234345a63Smrg        ptrn = head_in;
373f46a6179Smrg    }
37434345a63Smrg    else
37534345a63Smrg    {                           /* slash followed by wildcard */
37634345a63Smrg        head = head_in;
37734345a63Smrg        *ptrn = '\0';
37834345a63Smrg        ptrn++;
379f46a6179Smrg    }
38034345a63Smrg    if (ptrn)
38134345a63Smrg    {
38234345a63Smrg        rest = strchr(ptrn, '/');
38334345a63Smrg        if (rest != NULL)
38434345a63Smrg        {
38534345a63Smrg            *rest = '\0';
38634345a63Smrg            rest++;
38734345a63Smrg        }
388f46a6179Smrg    }
38934345a63Smrg    if (((rest && ptrn)
39034345a63Smrg         && ((strchr(ptrn, '(') != NULL) || (strchr(ptrn, ')') != NULL)))
39134345a63Smrg        || (head
39234345a63Smrg            && ((strchr(head, '(') != NULL) || (strchr(head, ')') != NULL))))
39334345a63Smrg    {
394bfe6082cSmrg        ERROR("Files/maps to list must have the form file(map)\n");
39534345a63Smrg        ACTION("Illegal specifier ignored\n");
39634345a63Smrg        return 0;
397f46a6179Smrg    }
39834345a63Smrg    return AddDirectory(head, ptrn, rest, NULL);
399f46a6179Smrg}
400f46a6179Smrg
401f46a6179Smrg/***====================================================================***/
402f46a6179Smrg
403f46a6179Smrgstatic Bool
404f46a6179SmrgMapMatches(char *mapToConsider, char *ptrn)
405f46a6179Smrg{
40634345a63Smrg    if (ptrn != NULL)
40734345a63Smrg        return XkbNameMatchesPattern(mapToConsider, ptrn);
40834345a63Smrg    if (nMapOnly < 1)
40934345a63Smrg        return True;
4106930ead5Smrg    for (int i = 0; i < nMapOnly; i++)
41134345a63Smrg    {
41234345a63Smrg        if (XkbNameMatchesPattern(mapToConsider, mapOnly[i]))
41334345a63Smrg            return True;
414f46a6179Smrg    }
415f46a6179Smrg    return False;
416f46a6179Smrg}
417f46a6179Smrg
418f46a6179Smrgint
4196930ead5SmrgGenerateListing(const char *out_name)
420f46a6179Smrg{
4216930ead5Smrg    FILE *outFile;
4226930ead5Smrg    XkbFile *rtrn;
42334345a63Smrg
42434345a63Smrg    if (nFilesListed < 1)
42534345a63Smrg    {
426bfe6082cSmrg        ERROR("Must specify at least one file or pattern to list\n");
42734345a63Smrg        return 0;
428f46a6179Smrg    }
42934345a63Smrg    if ((!out_name) || ((out_name[0] == '-') && (out_name[1] == '\0')))
43034345a63Smrg        outFile = stdout;
43134345a63Smrg    else if ((outFile = fopen(out_name, "w")) == NULL)
43234345a63Smrg    {
433bfe6082cSmrg        ERROR("Cannot open \"%s\" to write keyboard description\n",
43434345a63Smrg               out_name);
43534345a63Smrg        ACTION("Exiting\n");
43634345a63Smrg        return 0;
437f46a6179Smrg    }
438f46a6179Smrg#ifdef DEBUG
43934345a63Smrg    if (warningLevel > 9)
44034345a63Smrg        fprintf(stderr, "should list:\n");
441f46a6179Smrg#endif
4426930ead5Smrg    for (int i = 0; i < nListed; i++)
44334345a63Smrg    {
4446930ead5Smrg        unsigned oldWarningLevel;
445f46a6179Smrg#ifdef DEBUG
44634345a63Smrg        if (warningLevel > 9)
44734345a63Smrg        {
44834345a63Smrg            fprintf(stderr, "%s(%s)\n",
44934345a63Smrg                    (list[i].file ? list[i].file : "*"),
45034345a63Smrg                    (list[i].map ? list[i].map : "*"));
45134345a63Smrg        }
452f46a6179Smrg#endif
45334345a63Smrg        oldWarningLevel = warningLevel;
45434345a63Smrg        warningLevel = 0;
45534345a63Smrg        if (list[i].file)
45634345a63Smrg        {
4576930ead5Smrg            FILE *inputFile;
45834345a63Smrg            struct stat sbuf;
45934345a63Smrg
46034345a63Smrg            if (stat(list[i].file, &sbuf) < 0)
46134345a63Smrg            {
46234345a63Smrg                if (oldWarningLevel > 5)
463bfe6082cSmrg                    WARN("Couldn't open \"%s\"\n", list[i].file);
46434345a63Smrg                continue;
46534345a63Smrg            }
46634345a63Smrg            if (S_ISDIR(sbuf.st_mode))
46734345a63Smrg            {
46834345a63Smrg                if (verboseLevel & ListRecursive)
46934345a63Smrg                    AddDirectory(list[i].file, NULL, NULL, NULL);
47034345a63Smrg                continue;
47134345a63Smrg            }
47234345a63Smrg
47334345a63Smrg            inputFile = fopen(list[i].file, "r");
47434345a63Smrg            if (!inputFile)
47534345a63Smrg            {
47634345a63Smrg                if (oldWarningLevel > 5)
477bfe6082cSmrg                    WARN("Couldn't open \"%s\"\n", list[i].file);
47834345a63Smrg                continue;
47934345a63Smrg            }
48034345a63Smrg            setScanState(list[i].file, 1);
48134345a63Smrg            if (XKBParseFile(inputFile, &rtrn) && (rtrn != NULL))
48234345a63Smrg            {
4836930ead5Smrg                char *mapName = list[i].map;
4846930ead5Smrg                XkbFile *mapToUse = rtrn;
48534345a63Smrg                for (; mapToUse; mapToUse = (XkbFile *) mapToUse->common.next)
48634345a63Smrg                {
48734345a63Smrg                    if (!MapMatches(mapToUse->name, mapName))
48834345a63Smrg                        continue;
48934345a63Smrg                    ListFile(outFile, list[i].file, mapToUse);
49034345a63Smrg                }
49134345a63Smrg            }
49234345a63Smrg            fclose(inputFile);
49334345a63Smrg        }
49434345a63Smrg        warningLevel = oldWarningLevel;
495f46a6179Smrg    }
4966930ead5Smrg    if (outFile != stdout)
4976930ead5Smrg    {
4986930ead5Smrg        fclose(outFile);
4996930ead5Smrg    }
500f46a6179Smrg    return 1;
501f46a6179Smrg}
502