listing.c revision f46a6179
1/* $Xorg: listing.c,v 1.5 2001/02/09 02:05:49 xorgcvs Exp $ */
2/************************************************************
3 Copyright 1996 by Silicon Graphics Computer Systems, Inc.
4
5 Permission to use, copy, modify, and distribute this
6 software and its documentation for any purpose and without
7 fee is hereby granted, provided that the above copyright
8 notice appear in all copies and that both that copyright
9 notice and this permission notice appear in supporting
10 documentation, and that the name of Silicon Graphics not be
11 used in advertising or publicity pertaining to distribution
12 of the software without specific prior written permission.
13 Silicon Graphics makes no representation about the suitability
14 of this software for any purpose. It is provided "as is"
15 without any express or implied warranty.
16
17 SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
18 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
19 AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
20 GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
21 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
22 DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
23 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
24 THE USE OR PERFORMANCE OF THIS SOFTWARE.
25
26 ********************************************************/
27/***********************************************************
28
29Copyright 1988, 1998  The Open Group
30
31Permission to use, copy, modify, distribute, and sell this software and its
32documentation for any purpose is hereby granted without fee, provided that
33the above copyright notice appear in all copies and that both that
34copyright notice and this permission notice appear in supporting
35documentation.
36
37The above copyright notice and this permission notice shall be included in
38all copies or substantial portions of the Software.
39
40THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
41IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
42FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
43OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
44AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
45CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
46
47Except as contained in this notice, the name of The Open Group shall not be
48used in advertising or otherwise to promote the sale, use or other dealings
49in this Software without prior written authorization from The Open Group.
50
51
52Copyright 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
53
54                        All Rights Reserved
55
56Permission to use, copy, modify, and distribute this software and its
57documentation for any purpose and without fee is hereby granted,
58provided that the above copyright notice appear in all copies and that
59both that copyright notice and this permission notice appear in
60supporting documentation, and that the name of Digital not be
61used in advertising or publicity pertaining to distribution of the
62software without specific, written prior permission.
63
64DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
65ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
66DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
67ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
68WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
69ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
70SOFTWARE.
71
72******************************************************************/
73/* $XFree86: xc/programs/xkbcomp/listing.c,v 3.9 2001/12/14 20:01:57 dawes Exp $ */
74
75
76#include <stdio.h>
77#include <ctype.h>
78#include <sys/types.h>
79#include <sys/stat.h>
80#include <X11/keysym.h>
81
82#if defined(sgi)
83#include <malloc.h>
84#endif
85
86#define	DEBUG_VAR_NOT_LOCAL
87#define	DEBUG_VAR listingDebug
88#include "xkbcomp.h"
89#include <stdlib.h>
90#ifndef X_NOT_POSIX
91#ifdef _POSIX_SOURCE
92#include <limits.h>
93#else
94#define _POSIX_SOURCE
95#include <limits.h>
96#undef _POSIX_SOURCE
97#endif
98#endif
99#ifndef PATH_MAX
100#ifdef WIN32
101#define PATH_MAX 512
102#else
103#include <sys/param.h>
104#endif
105#ifndef PATH_MAX
106#ifdef MAXPATHLEN
107#define PATH_MAX MAXPATHLEN
108#else
109#define PATH_MAX 1024
110#endif
111#endif
112#endif
113
114#ifdef WIN32
115#include <windows.h>
116#define FileName(file) file.cFileName
117#undef TEXT
118#undef ALTERNATE
119#else
120#define FileName(file) file->d_name
121#ifndef X_NOT_POSIX
122#include <dirent.h>
123#else
124#ifdef SYSV
125#include <dirent.h>
126#else
127#ifdef USG
128#include <dirent.h>
129#else
130#include <sys/dir.h>
131#ifndef dirent
132#define dirent direct
133#endif
134#endif
135#endif
136#endif
137#endif
138
139#include "xkbpath.h"
140#include "parseutils.h"
141#include "misc.h"
142#include "tokens.h"
143#include <X11/extensions/XKBgeom.h>
144
145#define	lowbit(x)	((x) & (-(x)))
146
147static	int		szListing= 0;
148static	int		nListed= 0;
149static	int		nFilesListed= 0;
150
151typedef struct _Listing {
152	char *		file;
153	char *		map;
154} Listing;
155
156static	int		szMapOnly;
157static	int		nMapOnly;
158static	char **		mapOnly;
159
160static	Listing *	list= NULL;
161
162/***====================================================================***/
163
164int
165AddMapOnly(char *map)
166{
167    if (nMapOnly>=szMapOnly) {
168	if (szMapOnly<1)	szMapOnly= 5;
169	else			szMapOnly*= 2;
170	mapOnly= uTypedRealloc(list,szMapOnly,char *);
171	if (!mapOnly) {
172	    WSGO("Couldn't allocate list of maps\n");
173	    return 0;
174	}
175    }
176    mapOnly[nMapOnly++]= map;
177    return 1;
178}
179
180int
181AddListing(char *file,char *map)
182{
183    if (nListed>=szListing) {
184	if (szListing<1)	szListing= 10;
185	else			szListing*= 2;
186	list= uTypedRealloc(list,szListing,Listing);
187	if (!list) {
188	    WSGO("Couldn't allocate list of files and maps\n");
189	    ACTION("Exiting\n");
190	    exit(1);
191	}
192    }
193
194    list[nListed].file= file;
195    list[nListed].map= map;
196    nListed++;
197    if (file!=NULL)
198	nFilesListed++;
199    return 1;
200}
201
202/***====================================================================***/
203
204static void
205ListFile(FILE *outFile,char *fileName,XkbFile *map)
206{
207register unsigned	flags;
208char *			mapName;
209
210    flags= map->flags;
211    if ((flags&XkbLC_Hidden)&&(!(verboseLevel&WantHiddenMaps)))
212	return;
213    if ((flags&XkbLC_Partial)&&(!(verboseLevel&WantPartialMaps)))
214	return;
215    if (verboseLevel&WantLongListing) {
216	fprintf(outFile,(flags&XkbLC_Hidden)?"h":"-");
217	fprintf(outFile,(flags&XkbLC_Default)?"d":"-");
218	fprintf(outFile,(flags&XkbLC_Partial)?"p":"-");
219	fprintf(outFile,"----- ");
220	if (map->type==XkmSymbolsIndex) {
221	    fprintf(outFile,(flags&XkbLC_AlphanumericKeys)?"a":"-");
222	    fprintf(outFile,(flags&XkbLC_ModifierKeys)?"m":"-");
223	    fprintf(outFile,(flags&XkbLC_KeypadKeys)?"k":"-");
224	    fprintf(outFile,(flags&XkbLC_FunctionKeys)?"f":"-");
225	    fprintf(outFile,(flags&XkbLC_AlternateGroup)?"g":"-");
226	    fprintf(outFile,"--- ");
227	}
228        else fprintf(outFile,"-------- ");
229    }
230    mapName= map->name;
231    if ((!(verboseLevel&WantFullNames))&&((flags&XkbLC_Default)!=0))
232	mapName= NULL;
233    if (dirsToStrip>0) {
234	char *tmp,*last;
235	int	i;
236	for (i=0,tmp=last=fileName;(i<dirsToStrip)&&tmp;i++) {
237	    last= tmp;
238	    tmp= strchr(tmp,'/');
239	    if (tmp!=NULL)
240		tmp++;
241	}
242	fileName= (tmp?tmp:last);
243    }
244    if (mapName)
245	 fprintf(outFile,"%s(%s)\n",fileName,mapName);
246    else fprintf(outFile,"%s\n",fileName);
247    return;
248}
249
250/***====================================================================***/
251
252static int
253AddDirectory(char *head,char *ptrn,char *rest,char *map)
254{
255#ifdef WIN32
256    HANDLE		dirh;
257    WIN32_FIND_DATA	file;
258#else
259    DIR			*dirp;
260    struct dirent	*file;
261#endif
262    int			nMatch;
263
264    if (map==NULL) {
265	char *tmp = ptrn;
266	if ((rest==NULL)&&(ptrn!=NULL)&&(strchr(ptrn,'/')==NULL)) {
267	    tmp= ptrn;
268	    map= strchr(ptrn,'(');
269	}
270	else if ((rest==NULL)&&(ptrn==NULL)&&
271				(head!=NULL)&&(strchr(head,'/')==NULL)) {
272	    tmp= head;
273	    map= strchr(head,'(');
274	}
275	if (map!=NULL) {
276	    tmp= strchr(tmp,')');
277	    if ((tmp==NULL)||(tmp[1]!='\0')) {
278		ERROR1("File and map must have the format file(map)\n");
279		return 0;
280	    }
281	    *map= '\0'; map++;
282	    *tmp= '\0';
283	}
284    }
285#ifdef WIN32
286    if ((dirh = FindFirstFile("*.*", &file)) == INVALID_HANDLE_VALUE)
287	return 0;
288#else
289    if ((dirp = opendir ((head?head:"."))) == NULL)
290	return 0;
291    nMatch= 0;
292#endif
293#ifdef WIN32
294    do
295#else
296    while ((file = readdir (dirp)) != NULL)
297#endif
298    {
299	char *tmp,*filename;
300	struct stat sbuf;
301
302	filename= FileName(file);
303	if (!filename || filename[0]=='.')
304	    continue;
305	if (ptrn && (!XkbNameMatchesPattern(filename,ptrn)))
306	    continue;
307	tmp= (char *)uAlloc((head?strlen(head):0)+strlen(filename)+2);
308	if (!tmp)
309	    continue;
310	sprintf(tmp,"%s%s%s",(head?head:""),(head?"/":""),filename);
311	if (stat(tmp,&sbuf)<0) {
312	    uFree(tmp);
313	    continue;
314	}
315	if (((rest!=NULL)&&(!S_ISDIR(sbuf.st_mode)))||
316				    ((map!=NULL)&&(S_ISDIR(sbuf.st_mode)))) {
317	    uFree(tmp);
318	    continue;
319	}
320	if (S_ISDIR(sbuf.st_mode)) {
321	     if ((rest!=NULL)||(verboseLevel&ListRecursive))
322		nMatch+= AddDirectory(tmp,rest,NULL,map);
323	}
324	else nMatch+= AddListing(tmp,map);
325    }
326#ifdef WIN32
327    while (FindNextFile(dirh, &file));
328#endif
329    return nMatch;
330}
331
332/***====================================================================***/
333
334Bool
335AddMatchingFiles(char *head_in)
336{
337char 	*str,*head,*ptrn,*rest= NULL;
338
339    if (head_in==NULL)
340	return 0;
341    ptrn= NULL;
342    for (str=head_in;(*str!='\0')&&(*str!='?')&&(*str!='*');str++) {
343	if ((str!=head_in)&&(*str=='/'))
344	    ptrn= str;
345    }
346    if (*str=='\0') { /* no wildcards */
347	head= head_in;
348	ptrn= NULL;
349	rest= NULL;
350    }
351    else if (ptrn==NULL) { /* no slash before the first wildcard */
352	head= NULL;
353	ptrn= head_in;
354    }
355    else {	/* slash followed by wildcard */
356	head= head_in;
357	*ptrn= '\0'; ptrn++;
358    }
359    if (ptrn) {
360	rest= strchr(ptrn,'/');
361	if (rest!=NULL) {
362	    *rest= '\0';
363	    rest++;
364	}
365    }
366    if(((rest && ptrn)&&((strchr(ptrn,'(')!=NULL)||(strchr(ptrn,')')!=NULL)))||
367	(head && ((strchr(head,'(')!=NULL)||(strchr(head,')')!=NULL)))) {
368	ERROR1("Files/maps to list must have the form file(map)\n");
369	ACTION("Illegal specifier ignored\n");
370	return 0;
371    }
372    return AddDirectory(head,ptrn,rest,NULL);
373}
374
375/***====================================================================***/
376
377static Bool
378MapMatches(char *mapToConsider, char *ptrn)
379{
380int	i;
381
382    if (ptrn!=NULL)
383	return XkbNameMatchesPattern(mapToConsider,ptrn);
384    if (nMapOnly<1)
385	return True;
386    for (i=0;i<nMapOnly;i++) {
387	if (XkbNameMatchesPattern(mapToConsider,mapOnly[i]))
388	    return True;
389    }
390    return False;
391}
392
393int
394GenerateListing(char *out_name)
395{
396int		i;
397FILE *		inputFile,*outFile;
398XkbFile *	rtrn,*mapToUse;
399unsigned	oldWarningLevel;
400char *		mapName;
401
402    if (nFilesListed<1) {
403	ERROR1("Must specify at least one file or pattern to list\n");
404	return 0;
405    }
406    if ((!out_name)||((out_name[0]=='-')&&(out_name[1]=='\0')))
407	outFile= stdout;
408    else if ((outFile=fopen(out_name,"w"))==NULL) {
409	ERROR1("Cannot open \"%s\" to write keyboard description\n",out_name);
410	ACTION("Exiting\n");
411	return 0;
412    }
413#ifdef DEBUG
414    if (warningLevel>9)
415	fprintf(stderr,"should list:\n");
416#endif
417    for (i=0;i<nListed;i++) {
418#ifdef DEBUG
419	if (warningLevel>9) {
420	    fprintf(stderr,"%s(%s)\n",(list[i].file?list[i].file:"*"),
421					(list[i].map?list[i].map:"*"));
422	}
423#endif
424	oldWarningLevel= warningLevel;
425	warningLevel= 0;
426	if (list[i].file) {
427	    struct stat sbuf;
428
429	    if (stat(list[i].file,&sbuf)<0) {
430		if (oldWarningLevel>5)
431		    WARN1("Couldn't open \"%s\"\n",list[i].file);
432		continue;
433	    }
434	    if (S_ISDIR(sbuf.st_mode)) {
435		if (verboseLevel&ListRecursive)
436		    AddDirectory(list[i].file,NULL,NULL,NULL);
437		continue;
438	    }
439
440	    inputFile= fopen(list[i].file,"r");
441	    if (!inputFile) {
442		if (oldWarningLevel>5)
443		    WARN1("Couldn't open \"%s\"\n",list[i].file);
444		continue;
445	    }
446	    setScanState(list[i].file, 1);
447	    if (XKBParseFile(inputFile,&rtrn)&&(rtrn!=NULL)) {
448		mapName= list[i].map;
449		mapToUse= rtrn;
450		for (;mapToUse;mapToUse= (XkbFile *)mapToUse->common.next) {
451		    if (!MapMatches(mapToUse->name,mapName))
452			continue;
453		    ListFile(outFile,list[i].file,mapToUse);
454		}
455	    }
456	    fclose(inputFile);
457	}
458	warningLevel= oldWarningLevel;
459    }
460    return 1;
461}
462
463