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