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