Revert "xkbcomp: Remove listing sources"
[platform/upstream/libxkbcommon.git] / src / xkbcomp / listing.c
1 /************************************************************
2  Copyright 1996 by Silicon Graphics Computer Systems, Inc.
3
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.
15  
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.
24
25  ********************************************************/
26 /***********************************************************
27
28 Copyright 1988, 1998  The Open Group
29
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
34 documentation.
35
36 The above copyright notice and this permission notice shall be included in
37 all copies or substantial portions of the Software.
38
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.
45
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.
49
50
51 Copyright 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
52
53                         All Rights Reserved
54
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.  
62
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
69 SOFTWARE.
70
71 ******************************************************************/
72
73 #include <stdio.h>
74 #include <ctype.h>
75 #include <sys/types.h>
76 #include <sys/stat.h>
77 #include <X11/keysym.h>
78
79 #if defined(sgi)
80 #include <malloc.h>
81 #endif
82
83 #define DEBUG_VAR listingDebug
84 #include "xkbcomp.h"
85 #include <stdlib.h>
86
87 #ifdef _POSIX_SOURCE
88 # include <limits.h>
89 #else
90 # define _POSIX_SOURCE
91 # include <limits.h>
92 # undef _POSIX_SOURCE
93 #endif
94
95 #ifndef PATH_MAX
96 #ifdef WIN32
97 #define PATH_MAX 512
98 #else
99 #include <sys/param.h>
100 #endif
101 #ifndef PATH_MAX
102 #ifdef MAXPATHLEN
103 #define PATH_MAX MAXPATHLEN
104 #else
105 #define PATH_MAX 1024
106 #endif
107 #endif
108 #endif
109
110 #ifdef WIN32
111 # include <windows.h>
112 # define FileName(file) file.cFileName
113 # undef TEXT
114 # undef ALTERNATE
115 #else
116 # include <dirent.h>
117 # define FileName(file) file->d_name
118 #endif
119
120 #include "xkbpath.h"
121 #include "parseutils.h"
122 #include "misc.h"
123 #include "tokens.h"
124 #include <X11/extensions/XKBgeomcommon.h>
125
126 #define lowbit(x)       ((x) & (-(x)))
127
128 unsigned int listingDebug;
129
130 static int szListing = 0;
131 static int nListed = 0;
132 static int nFilesListed = 0;
133
134 typedef struct _Listing
135 {
136     char *file;
137     char *map;
138 } Listing;
139
140 static int szMapOnly;
141 static int nMapOnly;
142 static char **mapOnly;
143
144 static Listing *list = NULL;
145
146 /***====================================================================***/
147
148 int
149 AddMapOnly(char *map)
150 {
151     if (nMapOnly >= szMapOnly)
152     {
153         if (szMapOnly < 1)
154             szMapOnly = 5;
155         else
156             szMapOnly *= 2;
157         mapOnly = uTypedRealloc(list, szMapOnly, char *);
158         if (!mapOnly)
159         {
160             WSGO("Couldn't allocate list of maps\n");
161             return 0;
162         }
163     }
164     mapOnly[nMapOnly++] = map;
165     return 1;
166 }
167
168 int
169 AddListing(char *file, char *map)
170 {
171     if (nListed >= szListing)
172     {
173         if (szListing < 1)
174             szListing = 10;
175         else
176             szListing *= 2;
177         list = uTypedRealloc(list, szListing, Listing);
178         if (!list)
179         {
180             WSGO("Couldn't allocate list of files and maps\n");
181             ACTION("Exiting\n");
182             exit(1);
183         }
184     }
185
186     list[nListed].file = file;
187     list[nListed].map = map;
188     nListed++;
189     if (file != NULL)
190         nFilesListed++;
191     return 1;
192 }
193
194 /***====================================================================***/
195
196 static void
197 ListFile(FILE * outFile, char *fileName, XkbFile * map)
198 {
199     register unsigned flags;
200     char *mapName;
201
202     flags = map->flags;
203     if ((flags & XkbLC_Hidden) && (!(verboseLevel & WantHiddenMaps)))
204         return;
205     if ((flags & XkbLC_Partial) && (!(verboseLevel & WantPartialMaps)))
206         return;
207     if (verboseLevel & WantLongListing)
208     {
209         fprintf(outFile, (flags & XkbLC_Hidden) ? "h" : "-");
210         fprintf(outFile, (flags & XkbLC_Default) ? "d" : "-");
211         fprintf(outFile, (flags & XkbLC_Partial) ? "p" : "-");
212         fprintf(outFile, "----- ");
213         if (map->type == XkmSymbolsIndex)
214         {
215             fprintf(outFile, (flags & XkbLC_AlphanumericKeys) ? "a" : "-");
216             fprintf(outFile, (flags & XkbLC_ModifierKeys) ? "m" : "-");
217             fprintf(outFile, (flags & XkbLC_KeypadKeys) ? "k" : "-");
218             fprintf(outFile, (flags & XkbLC_FunctionKeys) ? "f" : "-");
219             fprintf(outFile, (flags & XkbLC_AlternateGroup) ? "g" : "-");
220             fprintf(outFile, "--- ");
221         }
222         else
223             fprintf(outFile, "-------- ");
224     }
225     mapName = map->name;
226     if ((!(verboseLevel & WantFullNames)) && ((flags & XkbLC_Default) != 0))
227         mapName = NULL;
228     if (dirsToStrip > 0)
229     {
230         char *tmp, *last;
231         int i;
232         for (i = 0, tmp = last = fileName; (i < dirsToStrip) && tmp; i++)
233         {
234             last = tmp;
235             tmp = strchr(tmp, '/');
236             if (tmp != NULL)
237                 tmp++;
238         }
239         fileName = (tmp ? tmp : last);
240     }
241     if (mapName)
242         fprintf(outFile, "%s(%s)\n", fileName, mapName);
243     else
244         fprintf(outFile, "%s\n", fileName);
245     return;
246 }
247
248 /***====================================================================***/
249
250 static int
251 AddDirectory(char *head, char *ptrn, char *rest, char *map)
252 {
253 #ifdef WIN32
254     HANDLE dirh;
255     WIN32_FIND_DATA file;
256 #else
257     DIR *dirp;
258     struct dirent *file;
259 #endif
260     int nMatch;
261
262     if (map == NULL)
263     {
264         char *tmp = ptrn;
265         if ((rest == NULL) && (ptrn != NULL) && (strchr(ptrn, '/') == NULL))
266         {
267             tmp = ptrn;
268             map = strchr(ptrn, '(');
269         }
270         else if ((rest == NULL) && (ptrn == NULL) &&
271                  (head != NULL) && (strchr(head, '/') == NULL))
272         {
273             tmp = head;
274             map = strchr(head, '(');
275         }
276         if (map != NULL)
277         {
278             tmp = strchr(tmp, ')');
279             if ((tmp == NULL) || (tmp[1] != '\0'))
280             {
281                 ERROR1("File and map must have the format file(map)\n");
282                 return 0;
283             }
284             *map = '\0';
285             map++;
286             *tmp = '\0';
287         }
288     }
289 #ifdef WIN32
290     if ((dirh = FindFirstFile("*.*", &file)) == INVALID_HANDLE_VALUE)
291         return 0;
292 #else
293     if ((dirp = opendir((head ? head : "."))) == NULL)
294         return 0;
295     nMatch = 0;
296 #endif
297 #ifdef WIN32
298     do
299 #else
300     while ((file = readdir(dirp)) != NULL)
301 #endif
302     {
303         char *tmp, *filename;
304         struct stat sbuf;
305
306         filename = FileName(file);
307         if (!filename || filename[0] == '.')
308             continue;
309         if (ptrn && (!XkbNameMatchesPattern(filename, ptrn)))
310             continue;
311         tmp =
312             (char *) uAlloc((head ? strlen(head) : 0) + strlen(filename) + 2);
313         if (!tmp)
314             continue;
315         sprintf(tmp, "%s%s%s", (head ? head : ""), (head ? "/" : ""),
316                 filename);
317         if (stat(tmp, &sbuf) < 0)
318         {
319             uFree(tmp);
320             continue;
321         }
322         if (((rest != NULL) && (!S_ISDIR(sbuf.st_mode))) ||
323             ((map != NULL) && (S_ISDIR(sbuf.st_mode))))
324         {
325             uFree(tmp);
326             continue;
327         }
328         if (S_ISDIR(sbuf.st_mode))
329         {
330             if ((rest != NULL) || (verboseLevel & ListRecursive))
331                 nMatch += AddDirectory(tmp, rest, NULL, map);
332         }
333         else
334             nMatch += AddListing(tmp, map);
335     }
336 #ifdef WIN32
337     while (FindNextFile(dirh, &file));
338 #endif
339     return nMatch;
340 }
341
342 /***====================================================================***/
343
344 Bool
345 AddMatchingFiles(char *head_in)
346 {
347     char *str, *head, *ptrn, *rest = NULL;
348
349     if (head_in == NULL)
350         return 0;
351     ptrn = NULL;
352     for (str = head_in; (*str != '\0') && (*str != '?') && (*str != '*');
353          str++)
354     {
355         if ((str != head_in) && (*str == '/'))
356             ptrn = str;
357     }
358     if (*str == '\0')
359     {                           /* no wildcards */
360         head = head_in;
361         ptrn = NULL;
362         rest = NULL;
363     }
364     else if (ptrn == NULL)
365     {                           /* no slash before the first wildcard */
366         head = NULL;
367         ptrn = head_in;
368     }
369     else
370     {                           /* slash followed by wildcard */
371         head = head_in;
372         *ptrn = '\0';
373         ptrn++;
374     }
375     if (ptrn)
376     {
377         rest = strchr(ptrn, '/');
378         if (rest != NULL)
379         {
380             *rest = '\0';
381             rest++;
382         }
383     }
384     if (((rest && ptrn)
385          && ((strchr(ptrn, '(') != NULL) || (strchr(ptrn, ')') != NULL)))
386         || (head
387             && ((strchr(head, '(') != NULL) || (strchr(head, ')') != NULL))))
388     {
389         ERROR1("Files/maps to list must have the form file(map)\n");
390         ACTION("Illegal specifier ignored\n");
391         return 0;
392     }
393     return AddDirectory(head, ptrn, rest, NULL);
394 }
395
396 /***====================================================================***/
397
398 static Bool
399 MapMatches(char *mapToConsider, char *ptrn)
400 {
401     int i;
402
403     if (ptrn != NULL)
404         return XkbNameMatchesPattern(mapToConsider, ptrn);
405     if (nMapOnly < 1)
406         return True;
407     for (i = 0; i < nMapOnly; i++)
408     {
409         if (XkbNameMatchesPattern(mapToConsider, mapOnly[i]))
410             return True;
411     }
412     return False;
413 }
414
415 int
416 GenerateListing(char *out_name)
417 {
418     int i;
419     FILE *inputFile, *outFile;
420     XkbFile *rtrn, *mapToUse;
421     unsigned oldWarningLevel;
422     char *mapName;
423
424     if (nFilesListed < 1)
425     {
426         ERROR1("Must specify at least one file or pattern to list\n");
427         return 0;
428     }
429     if ((!out_name) || ((out_name[0] == '-') && (out_name[1] == '\0')))
430         outFile = stdout;
431     else if ((outFile = fopen(out_name, "w")) == NULL)
432     {
433         ERROR1("Cannot open \"%s\" to write keyboard description\n",
434                out_name);
435         ACTION("Exiting\n");
436         return 0;
437     }
438 #ifdef DEBUG
439     if (warningLevel > 9)
440         fprintf(stderr, "should list:\n");
441 #endif
442     for (i = 0; i < nListed; i++)
443     {
444 #ifdef DEBUG
445         if (warningLevel > 9)
446         {
447             fprintf(stderr, "%s(%s)\n",
448                     (list[i].file ? list[i].file : "*"),
449                     (list[i].map ? list[i].map : "*"));
450         }
451 #endif
452         oldWarningLevel = warningLevel;
453         warningLevel = 0;
454         if (list[i].file)
455         {
456             struct stat sbuf;
457
458             if (stat(list[i].file, &sbuf) < 0)
459             {
460                 if (oldWarningLevel > 5)
461                     WARN1("Couldn't open \"%s\"\n", list[i].file);
462                 continue;
463             }
464             if (S_ISDIR(sbuf.st_mode))
465             {
466                 if (verboseLevel & ListRecursive)
467                     AddDirectory(list[i].file, NULL, NULL, NULL);
468                 continue;
469             }
470
471             inputFile = fopen(list[i].file, "r");
472             if (!inputFile)
473             {
474                 if (oldWarningLevel > 5)
475                     WARN1("Couldn't open \"%s\"\n", list[i].file);
476                 continue;
477             }
478             setScanState(list[i].file, 1);
479             if (XKBParseFile(inputFile, &rtrn) && (rtrn != NULL))
480             {
481                 mapName = list[i].map;
482                 mapToUse = rtrn;
483                 for (; mapToUse; mapToUse = (XkbFile *) mapToUse->common.next)
484                 {
485                     if (!MapMatches(mapToUse->name, mapName))
486                         continue;
487                     ListFile(outFile, list[i].file, mapToUse);
488                 }
489             }
490             fclose(inputFile);
491         }
492         warningLevel = oldWarningLevel;
493     }
494     return 1;
495 }